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.ui.form.field.transformer.item;
35
36 import info.magnolia.cms.beans.runtime.FileProperties;
37 import info.magnolia.cms.core.Path;
38 import info.magnolia.jcr.util.NodeTypes;
39 import info.magnolia.jcr.util.NodeUtil;
40 import info.magnolia.objectfactory.Components;
41 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
42 import info.magnolia.ui.form.field.definition.BasicUploadFieldDefinition;
43 import info.magnolia.ui.form.field.transformer.Transformer;
44 import info.magnolia.ui.form.field.upload.UploadReceiver;
45 import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter;
46 import info.magnolia.ui.vaadin.integration.jcr.DefaultProperty;
47 import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
48 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
49
50 import java.io.FileInputStream;
51 import java.io.InputStream;
52 import java.io.OutputStream;
53 import java.util.ArrayList;
54 import java.util.Date;
55 import java.util.List;
56 import java.util.Locale;
57
58 import javax.inject.Inject;
59 import javax.jcr.Binary;
60 import javax.jcr.Node;
61 import javax.jcr.RepositoryException;
62
63 import org.apache.commons.io.IOUtils;
64 import org.apache.jackrabbit.JcrConstants;
65 import org.apache.jackrabbit.value.BinaryImpl;
66 import org.apache.jackrabbit.value.ValueFactoryImpl;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
69
70 import com.vaadin.data.Item;
71 import com.vaadin.data.Property;
72
73
74
75
76
77
78 public class FileTransformer<T extends UploadReceiver> implements Transformer<T> {
79
80 private static final Logger log = LoggerFactory.getLogger(FileTransformer.class);
81
82 protected Item relatedFormItem;
83 protected final BasicUploadFieldDefinition definition;
84 protected final Class<T> type;
85 private Locale locale;
86
87 protected String basePropertyName;
88
89
90
91
92
93 @Deprecated
94 protected String i18NPropertyName;
95
96 private boolean isReadOnly = false;
97
98 private I18NAuthoringSupport i18NAuthoringSupport;
99
100 @Inject
101 public FileTransformer(Item relatedFormItem, BasicUploadFieldDefinition definition, Class<T> type, I18NAuthoringSupport i18NAuthoringSupport) {
102 this.definition = definition;
103 this.relatedFormItem = relatedFormItem;
104 this.type = type;
105 this.basePropertyName = getBasePropertyName();
106 this.i18NAuthoringSupport = i18NAuthoringSupport;
107 }
108
109
110
111
112 @Deprecated
113 public FileTransformer(Item relatedFormItem, BasicUploadFieldDefinition definition, Class<T> type) {
114 this(relatedFormItem, definition, type, Components.getComponent(I18NAuthoringSupport.class));
115 }
116
117
118
119
120
121
122 @Override
123 public void writeToItem(T newValue) {
124 Item item = getOrCreateFileItem();
125 if (isValid(newValue, item)) {
126 populateItem(newValue, item);
127 getRootItem().addChild((AbstractJcrNodeAdapter) item);
128 } else {
129 handleInvalid(newValue, item);
130 }
131 }
132
133
134
135
136 @Override
137 public T readFromItem() {
138
139 JcrNodeAdapter rootItem = getRootItem();
140
141 if (!rootItem.hasChildItemChanges()) {
142 populateStoredChildItems(rootItem);
143 }
144
145 Item item = getOrCreateFileItem();
146 return createPropertyFromItem(item);
147 }
148
149
150
151
152 protected Item getOrCreateFileItem() {
153 String itemName = getItemName();
154 Item child = getRootItem().getChild(itemName);
155 if (child != null) {
156 return child;
157 }
158 Node node = null;
159 try {
160 node = getRootItem().getJcrItem();
161 if (node.hasNode(itemName) && !(getRootItem() instanceof JcrNewNodeAdapter)) {
162 child = new JcrNodeAdapter(node.getNode(itemName));
163 } else {
164 child = new JcrNewNodeAdapter(node, NodeTypes.Resource.NAME, itemName);
165 }
166 } catch (RepositoryException e) {
167 log.error("Could get or create a child Item for {} ", NodeUtil.getPathIfPossible(node), e);
168 }
169 return child;
170 }
171
172
173
174
175 protected String getItemName() {
176 if (hasI18NSupport()) {
177 if (locale != null && !i18NAuthoringSupport.isDefaultLocale(locale, relatedFormItem)) {
178 return i18NAuthoringSupport.deriveLocalisedPropertyName(this.basePropertyName, locale);
179 }
180 }
181 return this.basePropertyName;
182 }
183
184
185
186
187 public T createPropertyFromItem(Item item) {
188 T uploadReceiver = initializeUploadReceiver();
189
190
191 if (item.getItemProperty(JcrConstants.JCR_DATA) != null && item.getItemProperty(JcrConstants.JCR_DATA).getValue() != null) {
192 String fileName = item.getItemProperty(FileProperties.PROPERTY_FILENAME) != null ? (String) item.getItemProperty(FileProperties.PROPERTY_FILENAME).getValue() : "";
193 String MIMEType = item.getItemProperty(FileProperties.PROPERTY_CONTENTTYPE) != null ? String.valueOf(item.getItemProperty(FileProperties.PROPERTY_CONTENTTYPE).getValue()) : "";
194
195 try (OutputStream out = uploadReceiver.receiveUpload(fileName, MIMEType);
196 InputStream in = ((BinaryImpl) item.getItemProperty(JcrConstants.JCR_DATA).getValue()).getStream()) {
197 IOUtils.copy(in, out);
198 } catch (Exception e) {
199 e.printStackTrace();
200 }
201 }
202 return uploadReceiver;
203 }
204
205 protected T initializeUploadReceiver() {
206 return (T) Components.newInstance(UploadReceiver.class, Path.getTempDirectory());
207 }
208
209
210
211
212 protected boolean isValid(T newValue, Item item) {
213 return newValue != null && !newValue.isEmpty();
214 }
215
216
217
218
219
220
221 public Item populateItem(T newValue, Item item) {
222
223 Property<Binary> data = getOrCreateProperty(item, JcrConstants.JCR_DATA, Binary.class);
224 if (newValue != null) {
225 try {
226 data.setValue(ValueFactoryImpl.getInstance().createBinary(new FileInputStream(newValue.getFile())));
227 } catch (Exception re) {
228 log.error("Could not get Binary. Upload will not be performed", re);
229 getRootItem().removeChild((AbstractJcrNodeAdapter) item);
230 return null;
231 }
232 }
233 getOrCreateProperty(item, FileProperties.PROPERTY_FILENAME, String.class).setValue(newValue.getFileName());
234 getOrCreateProperty(item, FileProperties.PROPERTY_CONTENTTYPE, String.class).setValue(newValue.getMimeType());
235 getOrCreateProperty(item, FileProperties.PROPERTY_LASTMODIFIED, Date.class).setValue(new Date());
236 getOrCreateProperty(item, FileProperties.PROPERTY_SIZE, Long.class).setValue(newValue.getFileSize());
237 getOrCreateProperty(item, FileProperties.PROPERTY_EXTENSION, String.class).setValue(newValue.getExtension());
238 return item;
239 }
240
241
242
243
244
245
246 protected void handleInvalid(T newValue, Item item) {
247 if (((AbstractJcrNodeAdapter) item).getParent() != null) {
248 ((AbstractJcrNodeAdapter) item).getParent().removeChild((AbstractJcrNodeAdapter) item);
249 }
250 }
251
252
253
254
255 protected Property getOrCreateProperty(Item item, String propertyName, Class<?> type) {
256 if (item.getItemProperty(propertyName) == null) {
257 item.addItemProperty(propertyName, new DefaultProperty(type, null));
258 }
259 return item.getItemProperty(propertyName);
260 }
261
262
263
264
265 protected JcrNodeAdapter getRootItem() {
266 return (JcrNodeAdapter) relatedFormItem;
267 }
268
269
270
271
272 protected void populateStoredChildItems(JcrNodeAdapter rootItem) {
273 List<Node> childNodes = getStoredChildNodes(rootItem);
274 for (Node child : childNodes) {
275 JcrNodeAdapter item = new JcrNodeAdapter(child);
276 rootItem.addChild(item);
277 }
278 }
279
280
281
282
283 protected List<Node> getStoredChildNodes(JcrNodeAdapter parent) {
284 try {
285 if (!(parent instanceof JcrNewNodeAdapter) && parent.getJcrItem().hasNodes()) {
286 return NodeUtil.asList(NodeUtil.getNodes(parent.getJcrItem(), NodeUtil.MAGNOLIA_FILTER));
287 }
288 } catch (RepositoryException re) {
289 log.warn("Not able to access the Child Nodes of the following Node Identifier {}", parent.getItemId(), re);
290 }
291 return new ArrayList<Node>();
292 }
293
294 @Override
295 public String getBasePropertyName() {
296 return this.definition.getBinaryNodeName();
297 }
298
299 @Override
300 public Class<T> getType() {
301 return this.type;
302 }
303
304 @Override
305 public boolean isReadOnly() {
306 if (this.isReadOnly) {
307 return true;
308 }
309 final Property property = relatedFormItem.getItemProperty(JcrConstants.JCR_DATA);
310 boolean isPropertyReadOnly = property != null && property.isReadOnly();
311 return isPropertyReadOnly || definition.isReadOnly();
312 }
313
314 @Override
315 public void setReadOnly(boolean isReadOnly) {
316 this.isReadOnly = isReadOnly;
317 }
318
319
320
321
322 @Override
323 public boolean hasI18NSupport() {
324 return definition.isI18n();
325 }
326
327 @Override
328 public void setLocale(Locale locale) {
329 this.locale = locale;
330 }
331
332
333
334
335 @Deprecated
336 @Override
337 public void setI18NPropertyName(String i18nPropertyName) {
338 this.i18NPropertyName = i18nPropertyName;
339 }
340
341 @Override
342 public Locale getLocale() {
343 return this.locale;
344 }
345
346 }