1 /*
2 * JBoss DNA (http://www.jboss.org/dna)
3 * See the COPYRIGHT.txt file distributed with this work for information
4 * regarding copyright ownership. Some portions may be licensed
5 * to Red Hat, Inc. under one or more contributor license agreements.
6 * See the AUTHORS.txt file in the distribution for a full listing of
7 * individual contributors.
8 *
9 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
10 * is licensed to you under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * JBoss DNA is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this software; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23 */
24 package org.modeshape.connector.jcr;
25
26 import java.util.HashSet;
27 import java.util.Set;
28 import javax.jcr.NamespaceException;
29 import javax.jcr.RepositoryException;
30 import javax.jcr.Session;
31 import org.modeshape.common.collection.Collections;
32 import org.modeshape.graph.connector.RepositorySourceException;
33 import org.modeshape.graph.property.Name;
34 import org.modeshape.graph.property.NamespaceRegistry;
35 import org.modeshape.graph.property.Path;
36 import org.modeshape.graph.property.basic.BasicNamespace;
37 import org.modeshape.graph.property.basic.SimpleNamespaceRegistry;
38
39 /**
40 * This represents the {@link NamespaceRegistry} implementation mirroring a supplied JCR Session. This registry is used by a
41 * custom context to create Name and Path objects from JCR Session values, and it ensures that any namespace used is also in the
42 * connector's normal NamespaceRegistry.
43 */
44 public class JcrNamespaceRegistry implements NamespaceRegistry {
45
46 private final String sourceName;
47 private final String defaultNamespaceUri;
48 private final NamespaceRegistry cache;
49 private final Session session;
50 private final javax.jcr.NamespaceRegistry jcrRegistry;
51 private final NamespaceRegistry connectorRegistry;
52
53 JcrNamespaceRegistry( String sourceName,
54 Session session,
55 NamespaceRegistry connectorRegistry ) throws RepositoryException {
56 this.sourceName = sourceName;
57 this.session = session;
58 this.jcrRegistry = this.session.getWorkspace().getNamespaceRegistry();
59 this.connectorRegistry = connectorRegistry;
60 this.cache = new SimpleNamespaceRegistry();
61 assert this.session != null;
62 assert this.cache != null;
63 assert this.jcrRegistry != null;
64 assert this.sourceName != null;
65 this.defaultNamespaceUri = getNamespaceForPrefix("");
66 }
67
68 /**
69 * {@inheritDoc}
70 *
71 * @see org.modeshape.graph.property.NamespaceRegistry#getDefaultNamespaceUri()
72 */
73 @Override
74 public String getDefaultNamespaceUri() {
75 return this.defaultNamespaceUri;
76 }
77
78 /**
79 * {@inheritDoc}
80 * <p>
81 * This method is most commonly used in this connector, because it is called to create {@link Name} and {@link Path} objects
82 * given the string representation returned by the remote JCR session.
83 * </p>
84 *
85 * @see org.modeshape.graph.property.NamespaceRegistry#getNamespaceForPrefix(java.lang.String)
86 */
87 @Override
88 public String getNamespaceForPrefix( String prefix ) {
89 String uri = cache.getNamespaceForPrefix(prefix);
90 if (uri == null) {
91 try {
92 uri = this.jcrRegistry.getURI(prefix);
93 // Make sure this is in the connector's registry ...
94 ensureRegisteredInConnector(prefix, uri);
95 } catch (NamespaceException e) {
96 // namespace is not known, so return null ...
97 } catch (RepositoryException e) {
98 throw new RepositorySourceException(sourceName, e);
99 }
100 }
101 return uri;
102 }
103
104 protected void ensureRegisteredInConnector( String prefix,
105 String uri ) {
106 if (!connectorRegistry.isRegisteredNamespaceUri(uri)) {
107 int index = 0;
108 while (connectorRegistry.getNamespaceForPrefix(prefix) != null) {
109 // The prefix is already used, so let it determine the best one ...
110 prefix = prefix + (++index);
111 }
112 connectorRegistry.register(prefix, uri);
113 }
114 }
115
116 /**
117 * {@inheritDoc}
118 *
119 * @see org.modeshape.graph.property.NamespaceRegistry#getNamespaces()
120 */
121 @Override
122 public Set<Namespace> getNamespaces() {
123 // Always delegate to the session's registry ...
124 Set<Namespace> namespaces = new HashSet<Namespace>();
125 try {
126 for (String prefix : this.jcrRegistry.getPrefixes()) {
127 String uri = this.jcrRegistry.getURI(prefix);
128 namespaces.add(new BasicNamespace(prefix, uri));
129 }
130 } catch (RepositoryException e) {
131 throw new RepositorySourceException(sourceName, e);
132 }
133 return namespaces;
134 }
135
136 /**
137 * {@inheritDoc}
138 *
139 * @see org.modeshape.graph.property.NamespaceRegistry#getPrefixForNamespaceUri(java.lang.String, boolean)
140 */
141 @Override
142 public String getPrefixForNamespaceUri( String namespaceUri,
143 boolean generateIfMissing ) {
144 String prefix = cache.getPrefixForNamespaceUri(namespaceUri, false);
145 if (prefix == null) {
146 try {
147 // Check the session ...
148 prefix = this.jcrRegistry.getPrefix(namespaceUri);
149 // Make sure this is in the connector's registry ...
150 ensureRegisteredInConnector(prefix, namespaceUri);
151 } catch (NamespaceException e) {
152 // namespace is not known, so return null ...
153 } catch (RepositoryException e) {
154 throw new RepositorySourceException(sourceName, e);
155 }
156 }
157 return prefix;
158 }
159
160 /**
161 * {@inheritDoc}
162 *
163 * @see org.modeshape.graph.property.NamespaceRegistry#getRegisteredNamespaceUris()
164 */
165 @Override
166 public Set<String> getRegisteredNamespaceUris() {
167 // Always delegate to the session's registry ...
168 try {
169 return Collections.unmodifiableSet(this.jcrRegistry.getURIs());
170 } catch (RepositoryException e) {
171 throw new RepositorySourceException(sourceName, e);
172 }
173 }
174
175 /**
176 * {@inheritDoc}
177 *
178 * @see org.modeshape.graph.property.NamespaceRegistry#isRegisteredNamespaceUri(java.lang.String)
179 */
180 @Override
181 public boolean isRegisteredNamespaceUri( String namespaceUri ) {
182 // Always delegate to the session's registry ...
183 try {
184 this.jcrRegistry.getPrefix(namespaceUri);
185 return true;
186 } catch (NamespaceException e) {
187 // namespace is not known, so return false ...
188 return false;
189 } catch (RepositoryException e) {
190 throw new RepositorySourceException(sourceName, e);
191 }
192 }
193
194 /**
195 * {@inheritDoc}
196 *
197 * @see org.modeshape.graph.property.NamespaceRegistry#register(java.lang.String, java.lang.String)
198 */
199 @Override
200 public String register( String prefix,
201 String namespaceUri ) {
202 throw new UnsupportedOperationException();
203 }
204
205 /**
206 * {@inheritDoc}
207 *
208 * @see org.modeshape.graph.property.NamespaceRegistry#unregister(java.lang.String)
209 */
210 @Override
211 public boolean unregister( String namespaceUri ) {
212 throw new UnsupportedOperationException();
213 }
214 }