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