View Javadoc

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 }