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