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.jcr.util;
35
36 import info.magnolia.cms.core.MgnlNodeType;
37 import info.magnolia.cms.util.OrderedProperties;
38
39 import java.io.ByteArrayInputStream;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.util.Arrays;
43 import java.util.Properties;
44
45 import javax.jcr.Node;
46 import javax.jcr.RepositoryException;
47
48 import org.apache.commons.beanutils.ConvertUtils;
49 import org.apache.commons.io.IOUtils;
50 import org.apache.commons.lang.StringUtils;
51 import org.apache.jackrabbit.util.ISO8601;
52
53
54
55
56
57
58
59
60
61
62
63
64 public class PropertiesImportExport {
65
66
67
68
69 public void createNodes(Node root, String... properties) throws IOException, RepositoryException {
70 createNodes(root, IOUtils.toInputStream(StringUtils.join(Arrays.asList(properties), "\n")));
71 }
72
73
74
75
76 public void createNodes(Node root, InputStream propertiesStream) throws IOException, RepositoryException {
77 Properties properties = new OrderedProperties();
78
79 properties.load(propertiesStream);
80
81 properties = keysToInnerFormat(properties);
82
83 for (Object o : properties.keySet()) {
84 String key = (String) o;
85 String valueStr = properties.getProperty(key);
86
87 String propertyName = StringUtils.substringAfterLast(key, ".");
88 String path = StringUtils.substringBeforeLast(key, ".");
89
90 String type = null;
91 if (propertyName.equals("@type")) {
92 type = valueStr;
93 } else if (properties.containsKey(path + ".@type")) {
94 type = properties.getProperty(path + ".@type");
95 }
96
97 type = StringUtils.defaultIfEmpty(type, MgnlNodeType.NT_CONTENTNODE);
98 Node c = NodeUtil.createPath(root, path, type);
99 populateNode(c, propertyName, valueStr);
100 }
101 }
102
103
104
105
106
107 private Properties keysToInnerFormat(Properties properties) {
108 Properties cleaned = new OrderedProperties();
109
110 for (Object o : properties.keySet()) {
111 String orgKey = (String) o;
112
113 if (!orgKey.startsWith("/")) {
114 throw new IllegalArgumentException("Missing trailing '/' for key: " + orgKey);
115 }
116 if (StringUtils.countMatches(orgKey, ".") > 1) {
117 throw new IllegalArgumentException("Key must not contain more than one '.': " + orgKey);
118 }
119 if (orgKey.contains("@") && !orgKey.contains(".@")) {
120 throw new IllegalArgumentException("Key containing '@' must be preceeded by a '.': " + orgKey);
121 }
122
123 String newKey = orgKey;
124
125 String propertyName = StringUtils.substringAfterLast(newKey, ".");
126 String keySuffix = StringUtils.substringBeforeLast(newKey, ".");
127 String path = StringUtils.removeStart(keySuffix, "/");
128
129
130 if (StringUtils.isEmpty(propertyName)) {
131
132 if (StringUtils.isEmpty(properties.getProperty(orgKey))) {
133
134 if (!properties.containsKey(orgKey + ".@type")) {
135 cleaned.put(path + ".@type", MgnlNodeType.NT_CONTENTNODE);
136 }
137 continue;
138 }
139 throw new IllegalArgumentException("Key for a path (everything without a '.' is considered to be a path) must not contain a value ('='): " + orgKey);
140 }
141 cleaned.put(path + "." + propertyName, properties.get(orgKey));
142 }
143 return cleaned;
144 }
145
146 protected void populateNode(Node node, String name, String valueStr) throws RepositoryException {
147 if (StringUtils.isEmpty(name) && StringUtils.isEmpty(valueStr)) {
148
149 return;
150 }
151 if (name.equals("@type")) {
152
153 } else if (name.equals("@uuid")) {
154 setIdentifier(node, valueStr);
155 } else {
156 Object valueObj = convertPropertyStringToObject(valueStr);
157 PropertyUtil.setProperty(node, name, valueObj);
158 }
159 }
160
161
162
163
164
165 protected void setIdentifier(Node ignoredNode, String ignoredString) {
166 throw new UnsupportedOperationException("Can't see UUIDs on real node.");
167 }
168
169 protected Object convertPropertyStringToObject(String valueStr) {
170 if (contains(valueStr, ':')) {
171 final String type = StringUtils.substringBefore(valueStr, ":");
172 final String value = StringUtils.substringAfter(valueStr, ":");
173
174
175 if (type.equalsIgnoreCase("date")) {
176 return ISO8601.parse(value);
177 } else if (type.equalsIgnoreCase("binary")) {
178 return new ByteArrayInputStream(value.getBytes());
179 } else {
180 try {
181 final Class<?> typeCl;
182 if (type.equals("int")) {
183 typeCl = Integer.class;
184 } else {
185 typeCl = Class.forName("java.lang." + StringUtils.capitalize(type));
186 }
187 return ConvertUtils.convert(value, typeCl);
188 } catch (ClassNotFoundException e) {
189
190 return valueStr;
191 }
192 }
193 }
194
195 return valueStr;
196 }
197
198 private static boolean contains(String s, char ch) {
199 return s.indexOf(ch) > -1;
200 }
201 }