1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.jcr;
25
26 import java.security.AccessControlException;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Map;
31 import java.util.Set;
32 import javax.jcr.AccessDeniedException;
33 import javax.jcr.NamespaceException;
34 import javax.jcr.RepositoryException;
35 import javax.jcr.Session;
36 import javax.xml.XMLConstants;
37 import net.jcip.annotations.NotThreadSafe;
38 import org.modeshape.common.util.CheckArg;
39 import org.modeshape.common.xml.XmlCharacters;
40 import org.modeshape.graph.JcrLexicon;
41 import org.modeshape.graph.JcrMixLexicon;
42 import org.modeshape.graph.JcrNtLexicon;
43 import org.modeshape.graph.property.NamespaceRegistry;
44 import org.modeshape.graph.property.Path;
45 import org.modeshape.graph.property.NamespaceRegistry.Namespace;
46
47
48
49
50
51
52
53
54
55
56 @NotThreadSafe
57 class JcrNamespaceRegistry implements javax.jcr.NamespaceRegistry {
58
59 public static enum Behavior {
60 JSR170_SESSION,
61 JSR283_SESSION,
62 WORKSPACE;
63 }
64
65 static final String DEFAULT_NAMESPACE_PREFIX = "";
66 static final String DEFAULT_NAMESPACE_URI = "";
67
68 static final String XML_NAMESPACE_PREFIX = XMLConstants.XML_NS_PREFIX;
69 static final String XML_NAMESPACE_URI = XMLConstants.XML_NS_URI;
70 static final String XMLNS_NAMESPACE_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
71 static final String XMLNS_NAMESPACE_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
72
73 static final String XML_SCHEMA_NAMESPACE_PREFIX = "xs";
74 static final String XML_SCHEMA_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema";
75 static final String XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX = "xsi";
76 static final String XML_SCHEMA_INSTANCE_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
77
78 static final Set<String> STANDARD_BUILT_IN_PREFIXES;
79 static final Set<String> STANDARD_BUILT_IN_URIS;
80 static final Map<String, String> STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX;
81 static final Map<String, String> STANDARD_BUILT_IN_PREFIXES_BY_NAMESPACE;
82
83 static {
84
85 Map<String, String> namespaces = new HashMap<String, String>();
86 namespaces.put(DEFAULT_NAMESPACE_PREFIX, DEFAULT_NAMESPACE_URI);
87 namespaces.put(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
88 namespaces.put(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
89 namespaces.put(JcrMixLexicon.Namespace.PREFIX, JcrMixLexicon.Namespace.URI);
90 namespaces.put(JcrSvLexicon.Namespace.PREFIX, JcrSvLexicon.Namespace.URI);
91 namespaces.put(XML_NAMESPACE_PREFIX, XML_NAMESPACE_URI);
92 namespaces.put(XMLNS_NAMESPACE_PREFIX, XMLNS_NAMESPACE_URI);
93 namespaces.put(XML_SCHEMA_NAMESPACE_PREFIX, XML_SCHEMA_NAMESPACE_URI);
94 namespaces.put(XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX, XML_SCHEMA_INSTANCE_NAMESPACE_URI);
95 namespaces.put(ModeShapeLexicon.Namespace.PREFIX, ModeShapeLexicon.Namespace.URI);
96 namespaces.put(ModeShapeIntLexicon.Namespace.PREFIX, ModeShapeIntLexicon.Namespace.URI);
97
98 Map<String, String> prefixes = new HashMap<String, String>();
99 for (Map.Entry<String, String> entry : namespaces.entrySet()) {
100 String uri = entry.getValue();
101 String prefix = entry.getKey();
102 prefixes.put(uri, prefix);
103 }
104
105 STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX = Collections.unmodifiableMap(namespaces);
106 STANDARD_BUILT_IN_PREFIXES_BY_NAMESPACE = Collections.unmodifiableMap(prefixes);
107 STANDARD_BUILT_IN_PREFIXES = Collections.unmodifiableSet(namespaces.keySet());
108 STANDARD_BUILT_IN_URIS = Collections.unmodifiableSet(new HashSet<String>(namespaces.values()));
109 }
110
111 private final Behavior behavior;
112 private final NamespaceRegistry registry;
113 private final NamespaceRegistry workspaceRegistry;
114 private final JcrSession session;
115
116 JcrNamespaceRegistry( NamespaceRegistry workspaceRegistry,
117 JcrSession session ) {
118 this(Behavior.WORKSPACE, null, workspaceRegistry, session);
119 }
120
121 JcrNamespaceRegistry( Behavior behavior,
122 NamespaceRegistry localRegistry,
123 NamespaceRegistry workspaceRegistry,
124 JcrSession session ) {
125 this.behavior = behavior;
126 this.registry = localRegistry != null ? localRegistry : workspaceRegistry;
127 this.workspaceRegistry = workspaceRegistry;
128 this.session = session;
129
130 assert this.behavior != null;
131 assert this.registry != null;
132 assert this.workspaceRegistry != null;
133 assert this.session != null;
134 }
135
136
137
138
139
140
141 protected final void checkSession() throws RepositoryException {
142 session.checkLive();
143 }
144
145
146
147
148
149
150 public String getPrefix( String uri ) throws NamespaceException, RepositoryException {
151 checkSession();
152 if (behavior == Behavior.WORKSPACE) {
153
154 String prefix = STANDARD_BUILT_IN_PREFIXES_BY_NAMESPACE.get(uri);
155 if (prefix != null) return prefix;
156 }
157
158 String prefix = registry.getPrefixForNamespaceUri(uri, false);
159 if (prefix == null) {
160 throw new NamespaceException(JcrI18n.noNamespaceWithUri.text(uri));
161 }
162 return prefix;
163 }
164
165
166
167
168
169
170 public String[] getPrefixes() throws RepositoryException {
171 checkSession();
172 Set<Namespace> namespaces = registry.getNamespaces();
173 String[] prefixes = new String[namespaces.size()];
174 int i = 0;
175 for (Namespace namespace : namespaces) {
176 prefixes[i++] = namespace.getPrefix();
177 }
178 return prefixes;
179 }
180
181
182
183
184
185
186 public String getURI( String prefix ) throws NamespaceException, RepositoryException {
187 checkSession();
188 if (behavior == Behavior.WORKSPACE) {
189
190 String uri = STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX.get(prefix);
191 if (uri != null) return uri;
192 }
193
194 String uri = registry.getNamespaceForPrefix(prefix);
195 if (uri == null) {
196 throw new NamespaceException(JcrI18n.noNamespaceWithPrefix.text(prefix));
197 }
198 return uri;
199 }
200
201
202
203
204
205
206 public String[] getURIs() throws RepositoryException {
207 checkSession();
208 Set<Namespace> namespaces = registry.getNamespaces();
209 String[] uris = new String[namespaces.size()];
210 int i = 0;
211 for (Namespace namespace : namespaces) {
212 uris[i++] = namespace.getNamespaceUri();
213 }
214 return uris;
215 }
216
217
218
219
220
221
222 public synchronized void registerNamespace( String prefix,
223 String uri ) throws NamespaceException, RepositoryException {
224 CheckArg.isNotNull(prefix, "prefix");
225 CheckArg.isNotNull(uri, "uri");
226 checkSession();
227
228 boolean global = false;
229 switch (behavior) {
230 case JSR170_SESSION:
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 String existingPrefix = registry.getPrefixForNamespaceUri(uri, false);
250 if (existingPrefix == null) {
251
252 throw new NamespaceException(JcrI18n.unableToRemapUriNotRegisteredInNamespaceRegistry.text(prefix, uri));
253 }
254 if (existingPrefix.equals(prefix)) return;
255
256
257 String existingUri = registry.getNamespaceForPrefix(prefix);
258 if (existingUri != null) {
259
260 String globalPrefix = workspaceRegistry.getPrefixForNamespaceUri(existingUri, false);
261 if (!prefix.equals(globalPrefix)) {
262
263 registry.unregister(existingUri);
264 }
265
266
267 String msg = JcrI18n.unableToRemapUriUsingPrefixUsedInNamespaceRegistry.text(prefix, uri, existingUri);
268 throw new NamespaceException(msg);
269 }
270
271
272
273 break;
274
275 case JSR283_SESSION:
276
277
278
279
280
281
282 String existingUriForPrefix = registry.getNamespaceForPrefix(prefix);
283 if (existingUriForPrefix != null) {
284 registry.unregister(existingUriForPrefix);
285 }
286 registry.unregister(uri);
287
288 break;
289
290 case WORKSPACE:
291
292
293
294 global = true;
295
296 try {
297 session.checkPermission((Path)null, ModeShapePermissions.REGISTER_NAMESPACE);
298 } catch (AccessControlException ace) {
299 throw new AccessDeniedException(ace);
300 }
301
302
303 if (DEFAULT_NAMESPACE_PREFIX.equals(prefix) || DEFAULT_NAMESPACE_URI.equals(uri)) {
304 throw new NamespaceException(JcrI18n.unableToChangeTheDefaultNamespace.text());
305 }
306
307 if (STANDARD_BUILT_IN_PREFIXES.contains(prefix)) {
308 throw new NamespaceException(JcrI18n.unableToRegisterReservedNamespacePrefix.text(prefix, uri));
309 }
310 if (STANDARD_BUILT_IN_URIS.contains(uri)) {
311 throw new NamespaceException(JcrI18n.unableToRegisterReservedNamespaceUri.text(prefix, uri));
312 }
313 break;
314 default:
315 assert false;
316 }
317
318
319 if (DEFAULT_NAMESPACE_PREFIX.equals(prefix) || DEFAULT_NAMESPACE_URI.equals(uri)) {
320 throw new NamespaceException(JcrI18n.unableToChangeTheDefaultNamespace.text());
321 }
322
323
324 if (prefix.toLowerCase().startsWith(XML_NAMESPACE_PREFIX)) {
325 throw new NamespaceException(JcrI18n.unableToRegisterNamespaceUsingXmlPrefix.text(prefix, uri));
326 }
327
328
329 if (!XmlCharacters.isValidName(prefix)) {
330 throw new NamespaceException(JcrI18n.unableToRegisterNamespaceWithInvalidPrefix.text(prefix, uri));
331 }
332
333
334 session.signalNamespaceChanges(global);
335
336
337 try {
338 registry.register(prefix, uri);
339 } catch (RuntimeException e) {
340 throw new RepositoryException(e.getMessage(), e.getCause());
341 }
342 }
343
344
345
346
347
348
349 public synchronized void unregisterNamespace( String prefix )
350 throws NamespaceException, AccessDeniedException, RepositoryException {
351 CheckArg.isNotNull(prefix, "prefix");
352 checkSession();
353
354
355 if (behavior.equals(Behavior.WORKSPACE)) {
356 try {
357 session.checkPermission((Path)null, ModeShapePermissions.REGISTER_NAMESPACE);
358 } catch (AccessControlException ace) {
359 throw new AccessDeniedException(ace);
360 }
361 }
362
363
364 String uri = registry.getNamespaceForPrefix(prefix);
365
366 if (uri == null) {
367 throw new NamespaceException(JcrI18n.unableToUnregisterPrefixForNamespaceThatIsNotRegistered.text(prefix));
368 }
369
370 if (STANDARD_BUILT_IN_PREFIXES.contains(prefix)) {
371 throw new NamespaceException(JcrI18n.unableToUnregisterReservedNamespacePrefix.text(prefix, uri));
372 }
373 if (STANDARD_BUILT_IN_URIS.contains(uri)) {
374 throw new NamespaceException(JcrI18n.unableToUnregisterReservedNamespaceUri.text(prefix, uri));
375 }
376
377
378 session.workspace().nodeTypeManager().signalNamespaceChanges();
379
380
381 try {
382 registry.unregister(uri);
383 } catch (RuntimeException e) {
384 throw new RepositoryException(e.getMessage(), e.getCause());
385 }
386 }
387
388
389
390
391
392
393 @Override
394 public String toString() {
395 return registry.toString();
396 }
397 }