1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.resources.app;
35
36 import info.magnolia.cms.beans.runtime.FileProperties;
37 import info.magnolia.cms.core.Path;
38 import info.magnolia.context.Context;
39 import info.magnolia.context.MgnlContext;
40 import info.magnolia.jcr.util.NodeTypes;
41 import info.magnolia.jcr.util.NodeUtil;
42 import info.magnolia.resourceloader.Resource;
43 import info.magnolia.resourceloader.ResourceOrigin;
44 import info.magnolia.resourceloader.jcr.JcrResourceOrigin;
45 import info.magnolia.resourceloader.layered.LayeredResource;
46 import info.magnolia.resources.app.workbench.ResourcesContainer;
47 import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
48
49 import java.io.IOException;
50 import java.util.Calendar;
51
52 import javax.inject.Inject;
53 import javax.jcr.Binary;
54 import javax.jcr.Node;
55 import javax.jcr.RepositoryException;
56 import javax.jcr.Session;
57
58 import org.apache.commons.io.IOUtils;
59 import org.apache.jackrabbit.JcrConstants;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 import com.google.common.net.MediaType;
64 import com.vaadin.data.Item;
65 import com.vaadin.data.Property;
66
67
68
69
70
71
72
73 public class ResourcesContentConnector implements ContentConnector {
74
75 private static final Logger log = LoggerFactory.getLogger(ResourcesContentConnector.class);
76
77 private final ResourceOrigin<LayeredResource> origin;
78
79 private Context context;
80
81 @Inject
82 @SuppressWarnings("unchecked")
83 public ResourcesContentConnector(ResourceOrigin resourceOrigin, Context context) {
84 this.context = context;
85 this.origin = (ResourceOrigin<LayeredResource>) resourceOrigin;
86 }
87
88
89
90
91 @Deprecated
92 public ResourcesContentConnector(ResourceOrigin resourceOrigin) {
93 this((ResourceOrigin<LayeredResource>) resourceOrigin, MgnlContext.getInstance());
94 }
95
96 @Override
97 public String getItemUrlFragment(Object itemId) {
98 return origin.getByPath((String) itemId).getPath();
99 }
100
101 @Override
102 public String getItemIdByUrlFragment(String urlFragment) {
103 return urlFragment;
104 }
105
106 @Override
107 public String getDefaultItemId() {
108
109 return "/";
110 }
111
112 @Override
113 public Item getItem(Object itemId) {
114 return ResourcesContainer.newItem(origin.getByPath((String) itemId));
115 }
116
117 @Override
118 public String getItemId(Item item) {
119 Property<?> resourcePathProperty = item.getItemProperty(ResourcesContainer.RESOURCE_PATH);
120 if (resourcePathProperty != null) {
121 return (String) resourcePathProperty.getValue();
122 }
123 return null;
124 }
125
126 @Override
127 public boolean canHandleItem(Object itemId) {
128 return itemId instanceof String && origin.hasPath((String) itemId);
129 }
130
131 public ResourceOrigin getOrigin() {
132 return origin;
133 }
134
135
136
137
138 public Resource createNewFolder(Resource parentResource, Item item) {
139 String fileName = item.getItemProperty(ResourcesContainer.RESOURCE_NAME) != null ? item.getItemProperty(ResourcesContainer.RESOURCE_NAME).getValue().toString() : "untitled";
140 try {
141 Session session = context.getJCRSession(JcrResourceOrigin.RESOURCES_WORKSPACE);
142
143 Node parentNode = NodeUtil.createPath(session.getRootNode(), parentResource.getPath(), NodeTypes.Folder.NAME);
144 Node addedFolder = parentNode.addNode(generateUniqueNodeNameForResource(parentNode, fileName), NodeTypes.Folder.NAME);
145 session.save();
146
147 return origin.getByPath(addedFolder.getPath());
148 } catch (Exception e) {
149 log.error("New folder failed to be created in JCR", e);
150 return null;
151 }
152 }
153
154
155
156
157
158
159 @SuppressWarnings("unchecked")
160 public Resource createNewResource(Resource parentResource, Item item) {
161
162 final Property<Binary> jcrData = (Property<Binary>) item.getItemProperty(JcrConstants.JCR_DATA);
163 String fileName;
164
165 boolean hasBinary = jcrData != null;
166 if (hasBinary) {
167 fileName = item.getItemProperty(FileProperties.PROPERTY_FILENAME) != null ? item.getItemProperty(FileProperties.PROPERTY_FILENAME).getValue().toString() : "untitled";
168 } else {
169 fileName = item.getItemProperty(ResourcesContainer.RESOURCE_NAME) != null ? item.getItemProperty(ResourcesContainer.RESOURCE_NAME).getValue().toString() : "untitled";
170 }
171 try {
172 final Session jcrSession = context.getJCRSession(JcrResourceOrigin.RESOURCES_WORKSPACE);
173
174 final Node parent = NodeUtil.createPath(jcrSession.getRootNode(), parentResource.getPath(), NodeTypes.Folder.NAME);
175 final Node resourceNode = parent.addNode(generateUniqueNodeNameForResource(parent, fileName), NodeTypes.Content.NAME);
176 if (hasBinary) {
177 MediaType type = extractMediaType(item);
178 if (type.is(MediaType.ANY_TEXT_TYPE)) {
179 resourceNode.setProperty(JcrResourceOrigin.TEXT_PROPERTY, IOUtils.toString(jcrData.getValue().getStream()));
180 } else {
181 Node binaryNode = resourceNode.addNode(JcrResourceOrigin.BINARY_NODE_NAME, NodeTypes.Resource.NAME);
182 setBinaryProperty(binaryNode, item, FileProperties.SIZE);
183 setBinaryProperty(binaryNode, item, FileProperties.EXTENSION);
184 setBinaryProperty(binaryNode, item, JcrConstants.JCR_MIMETYPE);
185 setBinaryProperty(binaryNode, item, JcrConstants.JCR_DATA);
186 }
187 } else {
188 resourceNode.setProperty(JcrResourceOrigin.TEXT_PROPERTY, "");
189 }
190
191 resourceNode.setProperty(NodeTypes.LastModified.LAST_MODIFIED, Calendar.getInstance());
192 jcrSession.save();
193
194 return origin.getByPath(resourceNode.getPath());
195 } catch (RepositoryException | IOException e) {
196 log.error("New node failed to be created in JCR", e);
197 return null;
198 }
199 }
200
201 private void setBinaryProperty(Node binaryNode, Item item, String propertyName) throws RepositoryException {
202 Property<?> p = item.getItemProperty(propertyName);
203 if (p != null) {
204 if (String.class.isAssignableFrom(p.getType())) {
205 binaryNode.setProperty(propertyName, (String) p.getValue());
206 } else if (Binary.class.isAssignableFrom(p.getType())) {
207 binaryNode.setProperty(propertyName, (Binary) p.getValue());
208 }
209 }
210 }
211
212 private String generateUniqueNodeNameForResource(final Node parent, String newNodeName) throws RepositoryException {
213 return Path.getUniqueLabel(parent.getSession(), parent.getPath(), Path.getValidatedLabel(newNodeName));
214 }
215
216
217
218
219
220
221
222
223 final MediaType extractMediaType(Item item) throws RepositoryException {
224 Property<?> mimeType;
225 if (item == null) {
226 throw new IllegalArgumentException("Item can't be null");
227 }
228 mimeType = item.getItemProperty(FileProperties.PROPERTY_CONTENTTYPE);
229 if (mimeType == null) {
230 mimeType = item.getItemProperty(FileProperties.PROPERTY_EXTENSION);
231 if (mimeType == null) {
232 throw new IllegalStateException("Expected to find either a [jcr:mimeType] or [extension] property but none was found");
233 } else {
234
235 return MediaType.create("text", "x-" + item.getItemProperty(FileProperties.PROPERTY_EXTENSION).getValue());
236 }
237 } else {
238
239 if (mimeType.getValue().toString().equals(MediaType.OCTET_STREAM.toString())) {
240 return MediaType.create("text", "x-" + item.getItemProperty(FileProperties.PROPERTY_EXTENSION).getValue());
241 }
242 return MediaType.parse(mimeType.getValue().toString());
243 }
244 }
245 }