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.util.SelectorUtil;
37 import info.magnolia.init.MagnoliaConfigurationProperties;
38
39 import java.nio.charset.StandardCharsets;
40
41 import javax.inject.Inject;
42 import javax.inject.Singleton;
43 import javax.jcr.Node;
44 import javax.jcr.RepositoryException;
45 import javax.jcr.Session;
46
47 import org.apache.commons.io.FilenameUtils;
48 import org.apache.commons.lang3.StringUtils;
49
50
51
52
53 @Singleton
54 public class NodeNameHelper {
55
56 private final String DEFAULT_UNTITLED_NODE_NAME = "untitled";
57
58 private final MagnoliaConfigurationProperties magnoliaConfigurationProperties;
59
60 @Inject
61 public NodeNameHelper(MagnoliaConfigurationProperties magnoliaConfigurationProperties) {
62 this.magnoliaConfigurationProperties = magnoliaConfigurationProperties;
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public String getUniqueName(Session session, String parentPath, String name) throws RepositoryException {
83 if (parentPath.equals("/")) {
84 parentPath = StringUtils.EMPTY;
85 }
86 while (session.itemExists(parentPath + "/" + name)) {
87 name = createUniqueName(name);
88 }
89 return name;
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 public String getUniqueName(Session session, String parentPath, String name, String extension) throws RepositoryException {
111 if (StringUtils.isNotEmpty(extension) && extension.equals(FilenameUtils.getExtension(name))) {
112 parentPath = "/".equals(parentPath) ? StringUtils.EMPTY : parentPath;
113 String basename = FilenameUtils.getBaseName(name);
114 String fullName = name;
115
116 while (session.itemExists(parentPath + "/" + fullName)) {
117 basename = createUniqueName(basename);
118 fullName = basename + FilenameUtils.EXTENSION_SEPARATOR + extension;
119 }
120 return fullName;
121 }
122
123 return getUniqueName(session, parentPath, name);
124 }
125
126 public String getUniqueName(Node parent, String name) throws RepositoryException {
127 while (parent.hasNode(name) || parent.hasProperty(name)) {
128 name = createUniqueName(name);
129 }
130 return name;
131 }
132
133
134
135
136
137
138 public String getValidatedName(String name) {
139 String charset = StringUtils.EMPTY;
140 if (magnoliaConfigurationProperties.getBooleanProperty(MagnoliaConfigurationProperties.MAGNOLIA_UTF8_ENABLED)) {
141 charset = StandardCharsets.UTF_8.name();
142 }
143 return getValidatedName(name, charset);
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 public String getValidatedName(String name, String charset) {
160 if (StringUtils.isEmpty(name)) {
161 return DEFAULT_UNTITLED_NODE_NAME;
162 }
163 final StringBuilder newLabel = new StringBuilder(name.length());
164
165
166 int ch = name.charAt(0);
167 if (!isCharValid(ch, charset) || ch == 46) {
168 newLabel.append("-");
169 } else {
170 newLabel.append(name.charAt(0));
171 }
172
173 for (int i = 1; i < name.length(); i++) {
174 int charCode = name.charAt(i);
175 if (isCharValid(charCode, charset)) {
176 newLabel.append(name.charAt(i));
177 } else {
178 newLabel.append("-");
179 }
180 }
181 if (newLabel.length() == 0) {
182 newLabel.append(DEFAULT_UNTITLED_NODE_NAME);
183 }
184 return newLabel.toString();
185 }
186
187 public boolean isValidName(String name) {
188 String charset = StringUtils.EMPTY;
189 if (magnoliaConfigurationProperties.getBooleanProperty(MagnoliaConfigurationProperties.MAGNOLIA_UTF8_ENABLED)) {
190 charset = StandardCharsets.UTF_8.name();
191 }
192 return isValidName(name, charset);
193 }
194
195 public boolean isValidName(String name, String charset) {
196 return name.equals(getValidatedName(name, charset));
197 }
198
199 private boolean isCharValid(int charCode, String charset) {
200
201
202
203
204
205
206
207
208
209
210
211 if (StandardCharsets.UTF_8.name().equals(charset)) {
212
213
214 if (charCode != 32
215 && charCode != '['
216 && charCode != ']'
217 && charCode != '*'
218 && charCode != '"'
219 && charCode != ':'
220 && charCode != 92
221 && charCode != 39
222 && charCode != ';'
223 && charCode != '/'
224 && charCode != '?'
225 && charCode != '+'
226 && charCode != '%'
227 && charCode != '!'
228 && charCode != '#'
229 && charCode != '@'
230 && charCode != '='
231 && charCode != '&'
232 && charCode != SelectorUtil.SELECTOR_DELIMITER.charAt(0)) {
233 return true;
234 }
235 } else {
236
237 if (((charCode >= 48) && (charCode <= 57))
238 || ((charCode >= 65) && (charCode <= 90))
239 || ((charCode >= 97) && (charCode <= 122))
240 || charCode == 45
241 || charCode == 46
242 || charCode == 95) {
243 return true;
244 }
245
246 }
247 return false;
248 }
249
250 private String createUniqueName(String baseName) {
251 int pos;
252 for (pos = baseName.length() - 1; pos >= 0; pos--) {
253 char c = baseName.charAt(pos);
254 if (c < '0' || c > '9') {
255 break;
256 }
257 }
258 String base;
259 int cnt;
260 if (pos == -1) {
261 if (baseName.length() > 1) {
262 pos = baseName.length() - 2;
263 }
264 }
265 if (pos == -1) {
266 base = baseName;
267 cnt = -1;
268 } else {
269 pos++;
270 base = baseName.substring(0, pos);
271 if (pos == baseName.length()) {
272 cnt = -1;
273 } else {
274 cnt = Integer.parseInt(baseName.substring(pos));
275 }
276 }
277 return (base + ++cnt);
278 }
279 }