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.importexport;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.HierarchyManager;
38 import info.magnolia.cms.core.ItemType;
39 import info.magnolia.cms.core.MetaData;
40 import info.magnolia.cms.core.NodeData;
41 import info.magnolia.cms.util.ContentUtil;
42 import info.magnolia.cms.util.OrderedProperties;
43 import org.apache.commons.beanutils.ConvertUtils;
44 import org.apache.commons.lang.StringUtils;
45 import org.apache.jackrabbit.util.ISO8601;
46
47 import javax.jcr.PropertyType;
48 import javax.jcr.RepositoryException;
49 import javax.jcr.Value;
50
51 import java.io.ByteArrayInputStream;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.util.Calendar;
55 import java.util.Collection;
56 import java.util.Properties;
57 import java.util.Set;
58
59
60
61
62
63
64
65
66
67
68
69 public class PropertiesImportExport {
70
71 public void createContent(Content root, InputStream propertiesStream) throws IOException, RepositoryException {
72 Properties properties = new OrderedProperties();
73
74 properties.load(propertiesStream);
75
76 properties = keysToInnerFormat(properties);
77
78 for (Object o : properties.keySet()) {
79 String key = (String) o;
80 String valueStr = properties.getProperty(key);
81
82 String propertyName = StringUtils.substringAfterLast(key, ".");
83 String path = StringUtils.substringBeforeLast(key, ".");
84
85 String type = null;
86 if (propertyName.equals("@type")) {
87 type = valueStr;
88 } else if (properties.containsKey(path + ".@type")) {
89 type = properties.getProperty(path + ".@type");
90 }
91
92 type = StringUtils.defaultIfEmpty(type, ItemType.CONTENTNODE.getSystemName());
93 Content c = ContentUtil.createPath(root, path, new ItemType(type));
94 populateContent(c, propertyName, valueStr);
95 }
96 }
97
98
99
100
101 private Properties keysToInnerFormat(Properties properties) {
102 Properties cleaned = new OrderedProperties();
103
104 for (Object o : properties.keySet()) {
105 String orgKey = (String) o;
106
107
108 String newKey = orgKey;
109
110
111 newKey = StringUtils.replace(newKey, "@", ".@");
112
113 newKey = StringUtils.replace(newKey, "..@", ".@");
114
115 String propertyName = StringUtils.substringAfterLast(newKey, ".");
116 String keySuffix = StringUtils.substringBeforeLast(newKey, ".");
117 String path = StringUtils.replace(keySuffix, ".", "/");
118 path = StringUtils.removeStart(path, "/");
119
120
121 if (StringUtils.isEmpty(propertyName)){
122
123 if(StringUtils.isEmpty(properties.getProperty(orgKey))) {
124
125 if(!properties.containsKey(orgKey + "@type")){
126 cleaned.put(path + ".@type", ItemType.CONTENTNODE.getSystemName());
127 }
128 continue;
129 }
130 propertyName = StringUtils.substringAfterLast(path, "/");
131 path = StringUtils.substringBeforeLast(path, "/");
132 }
133 cleaned.put(path + "." + propertyName, properties.get(orgKey));
134 }
135 return cleaned;
136 }
137
138 protected void populateContent(Content c, String name, String valueStr) throws RepositoryException {
139 if (StringUtils.isEmpty(name) && StringUtils.isEmpty(valueStr)) {
140
141 return;
142 }
143 if (name.equals("@type")) {
144
145 } else if (name.equals("@uuid")) {
146 throw new UnsupportedOperationException("Can't see UUIDs on real node. Use MockUtil if you are using MockContent instances.");
147 } else {
148 Object valueObj = convertNodeDataStringToObject(valueStr);
149 c.setNodeData(name, valueObj);
150 }
151 }
152
153 protected Object convertNodeDataStringToObject(String valueStr) {
154 if (contains(valueStr, ':')) {
155 final String type = StringUtils.substringBefore(valueStr, ":");
156 final String value = StringUtils.substringAfter(valueStr, ":");
157
158
159 if (type.equalsIgnoreCase("date")) {
160 return ISO8601.parse(value);
161 } else if (type.equalsIgnoreCase("binary")) {
162 return new ByteArrayInputStream(value.getBytes());
163 } else {
164 try {
165 final Class<?> typeCl;
166 if (type.equals("int")) {
167 typeCl = Integer.class;
168 } else {
169 typeCl = Class.forName("java.lang." + StringUtils.capitalize(type));
170 }
171 return ConvertUtils.convert(value, typeCl);
172 } catch (ClassNotFoundException e) {
173
174 return valueStr;
175 }
176 }
177 }
178
179 return valueStr;
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194 @Deprecated
195 public static Properties toProperties(HierarchyManager hm) throws Exception {
196 return toProperties(hm.getRoot());
197 }
198
199 public static Properties toProperties(Content rootContent) throws Exception {
200 return toProperties(rootContent, ContentUtil.EXCLUDE_META_DATA_CONTENT_FILTER, true);
201 }
202
203 public static Properties contentToProperties(HierarchyManager hm) throws Exception {
204 return contentToProperties(hm.getRoot());
205 }
206
207 public static Properties contentToProperties(Content rootContent) throws Exception {
208 return toProperties(rootContent, ContentUtil.EXCLUDE_META_DATA_CONTENT_FILTER, false);
209 }
210
211 public static Properties contentToProperties(Content rootContent, Content.ContentFilter filter) throws Exception {
212 return toProperties(rootContent, filter, false);
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226 private static Properties toProperties(Content rootContent, Content.ContentFilter contentFilter, final boolean legacyMode) throws Exception {
227 final Properties out = new OrderedProperties();
228 ContentUtil.visit(rootContent, new ContentUtil.Visitor() {
229 @Override
230 public void visit(Content node) throws Exception {
231 if (!legacyMode) {
232 appendNodeTypeAndUUID(node, out, true);
233 }
234 appendNodeProperties(node, out);
235 }
236 }, contentFilter);
237 return out;
238 }
239
240 private static void appendNodeTypeAndUUID(Content node, Properties out, final boolean dumpMetaData) throws RepositoryException {
241 String path = getExportPath(node);
242
243 if (path.equals("/jcr:root")) {
244 return;
245 }
246
247 String nodeTypeName = node.getNodeTypeName();
248 if (nodeTypeName != null && StringUtils.isNotEmpty(nodeTypeName)) {
249 out.put(path + "@type", nodeTypeName);
250 }
251 String nodeUUID = node.getUUID();
252 if (nodeUUID != null && StringUtils.isNotEmpty(nodeUUID)) {
253 out.put(path + "@uuid", node.getUUID());
254 }
255
256
257 if (dumpMetaData && !(nodeTypeName.equals("mgnl:metaData"))) {
258 Content metaDataNode = (node.getChildByName(MetaData.DEFAULT_META_NODE));
259 if (metaDataNode != null) {
260
261 appendNodeTypeAndUUID(metaDataNode, out, false);
262
263 String baseMetadataPath = getExportPath(metaDataNode);
264 MetaData nodeMetaData = node.getMetaData();
265
266 addStringProperty(out, baseMetadataPath + ".mgnl\\:template", nodeMetaData.getTemplate());
267 addStringProperty(out, baseMetadataPath + ".mgnl\\:authorid", nodeMetaData.getAuthorId());
268 addStringProperty(out, baseMetadataPath + ".mgnl\\:activatorid", nodeMetaData.getActivatorId());
269 addStringProperty(out, baseMetadataPath + ".mgnl\\:title", nodeMetaData.getTitle());
270 addDateProperty(out, baseMetadataPath + ".mgnl\\:creationdate", nodeMetaData.getCreationDate());
271 addDateProperty(out, baseMetadataPath + ".mgnl\\:lastaction", nodeMetaData.getLastActionDate());
272 addDateProperty(out, baseMetadataPath + ".mgnl\\:lastmodified", nodeMetaData.getLastActionDate());
273 addBooleanProeprty(out, baseMetadataPath + ".mgnl\\:activated", nodeMetaData.getIsActivated());
274 }
275 }
276 }
277
278 private static void addBooleanProeprty(Properties out, String path, boolean prop) {
279 out.put(path, convertBooleanToExportString(prop));
280 }
281
282 private static void addDateProperty(Properties out, String path, Calendar date) {
283 if (date != null) {
284 out.put(path, convertCalendarToExportString(date));
285 }
286 }
287
288 private static void addStringProperty(Properties out, String path, String stringProperty) {
289 if (StringUtils.isNotEmpty(stringProperty)) {
290 out.put(path, stringProperty);
291 }
292 }
293
294 public static void appendNodeProperties(Content node, Properties out) {
295 final Collection<NodeData> props = node.getNodeDataCollection();
296 for (NodeData prop : props) {
297 final String path = getExportPath(node) + "." + prop.getName();
298
299 String propertyValue = getPropertyString(prop);
300
301 if (propertyValue != null) {
302 out.setProperty(path, propertyValue);
303 }
304 }
305 }
306
307 private static String getExportPath(Content node) {
308 return node.getHandle();
309 }
310
311 private static String getPropertyString(NodeData prop) {
312 int propType = prop.getType();
313
314 switch (propType) {
315 case (PropertyType.STRING): {
316 return prop.getString();
317 }
318 case (PropertyType.BOOLEAN): {
319 return convertBooleanToExportString(prop.getBoolean());
320 }
321 case (PropertyType.BINARY): {
322 return convertBinaryToExportString(prop.getValue());
323 }
324 case (PropertyType.PATH): {
325 return prop.getString();
326 }
327 case (PropertyType.DATE): {
328 return convertCalendarToExportString(prop.getDate());
329 }
330 case (PropertyType.LONG): {
331 return "" + prop.getLong();
332 }
333 case (PropertyType.DOUBLE): {
334 return "" + prop.getDouble();
335 }
336 default: {
337 return prop.getString();
338 }
339 }
340 }
341
342 private static String convertBooleanToExportString(boolean b) {
343 return "boolean:" + (b ? "true" : "false");
344 }
345
346 private static String convertBinaryToExportString(Value value) {
347 return "binary:" + ConvertUtils.convert(value);
348 }
349
350 private static String convertCalendarToExportString(Calendar calendar) {
351 return "date:" + ISO8601.format(calendar);
352 }
353
354
355
356
357
358 public static String dumpPropertiesToString(Content content, Content.ContentFilter filter) throws Exception {
359 Properties properties = PropertiesImportExport.contentToProperties(content, filter);
360 return dumpPropertiesToString(properties);
361 }
362
363 public static String dumpPropertiesToString(Properties properties) {
364 final StringBuilder sb = new StringBuilder();
365 final Set<Object> propertyNames = properties.keySet();
366 for (Object propertyKey : propertyNames) {
367 final String name = propertyKey.toString();
368 final String value = properties.getProperty(name);
369 sb.append(name);
370 sb.append("=");
371 sb.append(value);
372 sb.append("\n");
373 }
374 return sb.toString();
375 }
376
377 private static boolean contains(String s, char ch) {
378 return s.indexOf(ch) > -1;
379 }
380 }