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