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