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 SESSION,
61 WORKSPACE;
62 }
63
64 static final String DEFAULT_NAMESPACE_PREFIX = "";
65 static final String DEFAULT_NAMESPACE_URI = "";
66
67 static final String XML_NAMESPACE_PREFIX = XMLConstants.XML_NS_PREFIX;
68 static final String XML_NAMESPACE_URI = XMLConstants.XML_NS_URI;
69 static final String XMLNS_NAMESPACE_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
70 static final String XMLNS_NAMESPACE_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
71
72 static final String XML_SCHEMA_NAMESPACE_PREFIX = "xs";
73 static final String XML_SCHEMA_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema";
74 static final String XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX = "xsi";
75 static final String XML_SCHEMA_INSTANCE_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
76
77 static final Set<String> STANDARD_BUILT_IN_PREFIXES;
78 static final Set<String> STANDARD_BUILT_IN_URIS;
79 static final Map<String, String> STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX;
80 static final Map<String, String> STANDARD_BUILT_IN_PREFIXES_BY_NAMESPACE;
81
82 static {
83
84 Map<String, String> namespaces = new HashMap<String, String>();
85 namespaces.put(DEFAULT_NAMESPACE_PREFIX, DEFAULT_NAMESPACE_URI);
86 namespaces.put(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
87 namespaces.put(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
88 namespaces.put(JcrMixLexicon.Namespace.PREFIX, JcrMixLexicon.Namespace.URI);
89 namespaces.put(JcrSvLexicon.Namespace.PREFIX, JcrSvLexicon.Namespace.URI);
90 namespaces.put(XML_NAMESPACE_PREFIX, XML_NAMESPACE_URI);
91 namespaces.put(XMLNS_NAMESPACE_PREFIX, XMLNS_NAMESPACE_URI);
92 namespaces.put(XML_SCHEMA_NAMESPACE_PREFIX, XML_SCHEMA_NAMESPACE_URI);
93 namespaces.put(XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX, XML_SCHEMA_INSTANCE_NAMESPACE_URI);
94 namespaces.put(ModeShapeLexicon.Namespace.PREFIX, ModeShapeLexicon.Namespace.URI);
95 namespaces.put(ModeShapeIntLexicon.Namespace.PREFIX, ModeShapeIntLexicon.Namespace.URI);
96
97 Map<String, String> prefixes = new HashMap<String, String>();
98 for (Map.Entry<String, String> entry : namespaces.entrySet()) {
99 String uri = entry.getValue();
100 String prefix = entry.getKey();
101 prefixes.put(uri, prefix);
102 }
103
104 STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX = Collections.unmodifiableMap(namespaces);
105 STANDARD_BUILT_IN_PREFIXES_BY_NAMESPACE = Collections.unmodifiableMap(prefixes);
106 STANDARD_BUILT_IN_PREFIXES = Collections.unmodifiableSet(namespaces.keySet());
107 STANDARD_BUILT_IN_URIS = Collections.unmodifiableSet(new HashSet<String>(namespaces.values()));
108 }
109
110 private final Behavior behavior;
111 private final NamespaceRegistry registry;
112 private final NamespaceRegistry workspaceRegistry;
113 private final JcrSession session;
114
115 JcrNamespaceRegistry( NamespaceRegistry workspaceRegistry,
116 JcrSession session ) {
117 this(Behavior.WORKSPACE, null, workspaceRegistry, session);
118 }
119
120 JcrNamespaceRegistry( Behavior behavior,
121 NamespaceRegistry localRegistry,
122 NamespaceRegistry workspaceRegistry,
123 JcrSession session ) {
124 this.behavior = behavior;
125 this.registry = localRegistry != null ? localRegistry : workspaceRegistry;
126 this.workspaceRegistry = workspaceRegistry;
127 this.session = session;
128
129 assert this.behavior != null;
130 assert this.registry != null;
131 assert this.workspaceRegistry != null;
132 assert this.session != null;
133 }
134
135
136
137
138
139
140 protected final void checkSession() throws RepositoryException {
141 session.checkLive();
142 }
143
144
145
146
147
148
149 public String getPrefix( String uri ) throws NamespaceException, RepositoryException {
150 checkSession();
151 if (behavior == Behavior.WORKSPACE) {
152
153 String prefix = STANDARD_BUILT_IN_PREFIXES_BY_NAMESPACE.get(uri);
154 if (prefix != null) return prefix;
155 }
156
157 String prefix = registry.getPrefixForNamespaceUri(uri, false);
158 if (prefix == null) {
159 throw new NamespaceException(JcrI18n.noNamespaceWithUri.text(uri));
160 }
161 return prefix;
162 }
163
164
165
166
167
168
169 public String[] getPrefixes() throws RepositoryException {
170 checkSession();
171 Set<Namespace> namespaces = registry.getNamespaces();
172 String[] prefixes = new String[namespaces.size()];
173 int i = 0;
174 for (Namespace namespace : namespaces) {
175 prefixes[i++] = namespace.getPrefix();
176 }
177 return prefixes;
178 }
179
180
181
182
183
184
185 public String getURI( String prefix ) throws NamespaceException, RepositoryException {
186 checkSession();
187 if (behavior == Behavior.WORKSPACE) {
188
189 String uri = STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX.get(prefix);
190 if (uri != null) return uri;
191 }
192
193 String uri = registry.getNamespaceForPrefix(prefix);
194 if (uri == null) {
195 throw new NamespaceException(JcrI18n.noNamespaceWithPrefix.text(prefix));
196 }
197 return uri;
198 }
199
200
201
202
203
204
205 public String[] getURIs() throws RepositoryException {
206 checkSession();
207 Set<Namespace> namespaces = registry.getNamespaces();
208 String[] uris = new String[namespaces.size()];
209 int i = 0;
210 for (Namespace namespace : namespaces) {
211 uris[i++] = namespace.getNamespaceUri();
212 }
213 return uris;
214 }
215
216
217
218
219
220
221 public synchronized void registerNamespace( String prefix,
222 String uri ) throws NamespaceException, RepositoryException {
223 CheckArg.isNotNull(prefix, "prefix");
224 CheckArg.isNotNull(uri, "uri");
225 checkSession();
226
227 boolean global = false;
228 switch (behavior) {
229 case SESSION:
230
231
232
233
234
235
236 String existingUriForPrefix = registry.getNamespaceForPrefix(prefix);
237 if (existingUriForPrefix != null) {
238 registry.unregister(existingUriForPrefix);
239 }
240 registry.unregister(uri);
241
242 break;
243
244 case WORKSPACE:
245
246
247
248 global = true;
249
250 try {
251 session.checkPermission((Path)null, ModeShapePermissions.REGISTER_NAMESPACE);
252 } catch (AccessControlException ace) {
253 throw new AccessDeniedException(ace);
254 }
255
256
257 if (DEFAULT_NAMESPACE_PREFIX.equals(prefix) || DEFAULT_NAMESPACE_URI.equals(uri)) {
258 throw new NamespaceException(JcrI18n.unableToChangeTheDefaultNamespace.text());
259 }
260
261 if (STANDARD_BUILT_IN_PREFIXES.contains(prefix)) {
262 throw new NamespaceException(JcrI18n.unableToRegisterReservedNamespacePrefix.text(prefix, uri));
263 }
264 if (STANDARD_BUILT_IN_URIS.contains(uri)) {
265 throw new NamespaceException(JcrI18n.unableToRegisterReservedNamespaceUri.text(prefix, uri));
266 }
267 break;
268 default:
269 assert false;
270 }
271
272
273 if (DEFAULT_NAMESPACE_PREFIX.equals(prefix) || DEFAULT_NAMESPACE_URI.equals(uri)) {
274 throw new NamespaceException(JcrI18n.unableToChangeTheDefaultNamespace.text());
275 }
276
277
278 if (prefix.toLowerCase().startsWith(XML_NAMESPACE_PREFIX)) {
279 throw new NamespaceException(JcrI18n.unableToRegisterNamespaceUsingXmlPrefix.text(prefix, uri));
280 }
281
282
283 if (!XmlCharacters.isValidName(prefix)) {
284 throw new NamespaceException(JcrI18n.unableToRegisterNamespaceWithInvalidPrefix.text(prefix, uri));
285 }
286
287
288 session.signalNamespaceChanges(global);
289
290
291 try {
292 registry.register(prefix, uri);
293 } catch (RuntimeException e) {
294 throw new RepositoryException(e.getMessage(), e.getCause());
295 }
296 }
297
298
299
300
301
302
303 public synchronized void unregisterNamespace( String prefix )
304 throws NamespaceException, AccessDeniedException, RepositoryException {
305 CheckArg.isNotNull(prefix, "prefix");
306 checkSession();
307
308
309 if (behavior.equals(Behavior.WORKSPACE)) {
310 try {
311 session.checkPermission((Path)null, ModeShapePermissions.REGISTER_NAMESPACE);
312 } catch (AccessControlException ace) {
313 throw new AccessDeniedException(ace);
314 }
315 }
316
317
318 String uri = registry.getNamespaceForPrefix(prefix);
319
320 if (uri == null) {
321 throw new NamespaceException(JcrI18n.unableToUnregisterPrefixForNamespaceThatIsNotRegistered.text(prefix));
322 }
323
324 if (STANDARD_BUILT_IN_PREFIXES.contains(prefix)) {
325 throw new NamespaceException(JcrI18n.unableToUnregisterReservedNamespacePrefix.text(prefix, uri));
326 }
327 if (STANDARD_BUILT_IN_URIS.contains(uri)) {
328 throw new NamespaceException(JcrI18n.unableToUnregisterReservedNamespaceUri.text(prefix, uri));
329 }
330
331
332 session.workspace().nodeTypeManager().signalNamespaceChanges();
333
334
335 try {
336 registry.unregister(uri);
337 } catch (RuntimeException e) {
338 throw new RepositoryException(e.getMessage(), e.getCause());
339 }
340 }
341
342
343
344
345
346
347 @Override
348 public String toString() {
349 return registry.toString();
350 }
351 }