View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
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    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
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   * ModeShape 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.graph.io;
25  
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.net.URI;
29  import org.modeshape.common.text.TextDecoder;
30  import org.modeshape.common.util.CheckArg;
31  import org.modeshape.graph.ExecutionContext;
32  import org.modeshape.graph.Graph;
33  import org.modeshape.graph.JcrLexicon;
34  import org.modeshape.graph.JcrNtLexicon;
35  import org.modeshape.graph.Location;
36  import org.modeshape.graph.connector.RepositorySource;
37  import org.modeshape.graph.connector.RepositorySourceException;
38  import org.modeshape.graph.property.Name;
39  import org.modeshape.graph.property.NamespaceRegistry;
40  import org.modeshape.graph.property.Path;
41  import org.modeshape.graph.xml.XmlHandler;
42  import org.xml.sax.InputSource;
43  import org.xml.sax.SAXException;
44  import org.xml.sax.XMLReader;
45  import org.xml.sax.helpers.XMLReaderFactory;
46  
47  /**
48   * An importer of graph content. This class can be used directly, or the import can be done via the {@link Graph} using the
49   * {@link Graph#importXmlFrom(java.io.File)} (and similar) methods.
50   */
51  public class GraphImporter {
52  
53      private final Graph graph;
54  
55      public GraphImporter( Graph graph ) {
56          CheckArg.isNotNull(graph, "graph");
57          this.graph = graph;
58      }
59  
60      /**
61       * Get the context in which the importer will be executed.
62       * 
63       * @return the execution context; never null
64       */
65      public ExecutionContext getContext() {
66          return this.graph.getContext();
67      }
68  
69      /**
70       * The graph that this importer uses.
71       * 
72       * @return the graph; never null
73       */
74      public Graph getGraph() {
75          return graph;
76      }
77  
78      /**
79       * Read the content from the supplied URI and import into the repository at the supplied location.
80       * 
81       * @param uri the URI where the importer can read the content that is to be imported
82       * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
83       *        be null
84       * @return the batch of requests for creating the graph content that represents the imported content
85       * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
86       * @throws IOException if there is a problem reading the content
87       * @throws SAXException if there is a problem with the SAX Parser
88       * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
89       *         source}
90       */
91      public Graph.Batch importXml( URI uri,
92                                    Location location ) throws IOException, SAXException, RepositorySourceException {
93          return importXml(uri, location, false);
94      }
95  
96      /**
97       * Read the content from the supplied URI and import into the repository at the supplied location.
98       * 
99       * @param uri the URI where the importer can read the content that is to be imported
100      * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
101      *        be null
102      * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element
103      * @return the batch of requests for creating the graph content that represents the imported content
104      * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
105      * @throws IOException if there is a problem reading the content
106      * @throws SAXException if there is a problem with the SAX Parser
107      * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
108      *         source}
109      */
110     public Graph.Batch importXml( URI uri,
111                                   Location location,
112                                   boolean skip ) throws IOException, SAXException, RepositorySourceException {
113         CheckArg.isNotNull(uri, "uri");
114         CheckArg.isNotNull(location, "location");
115         CheckArg.isNotNull(location.getPath(), "location.getPath()");
116         InputStream stream = null;
117         try {
118             stream = uri.toURL().openStream();
119             return importXml(stream, location, skip);
120         } finally {
121             if (stream != null) stream.close();
122         }
123     }
124 
125     /**
126      * Read the content from the supplied URI and import into the repository at the supplied location. This method does <i>not</i>
127      * close the stream.
128      * 
129      * @param stream the stream containing the content to be imported
130      * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
131      *        be null
132      * @return the batch of requests for creating the graph content that represents the imported content
133      * @throws IllegalArgumentException if the <code>stream</code> or destination path are null
134      * @throws IOException if there is a problem reading the content
135      * @throws SAXException if there is a problem with the SAX Parser
136      * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
137      *         source}
138      */
139     public Graph.Batch importXml( InputStream stream,
140                                   Location location ) throws IOException, SAXException, RepositorySourceException {
141         return importXml(stream, location, false);
142     }
143 
144     /**
145      * Read the content from the supplied URI and import into the repository at the supplied location. This method does <i>not</i>
146      * close the stream.
147      * 
148      * @param stream the stream containing the content to be imported
149      * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
150      *        be null
151      * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element
152      * @return the batch of requests for creating the graph content that represents the imported content
153      * @throws IllegalArgumentException if the <code>stream</code> or destination path are null
154      * @throws IOException if there is a problem reading the content
155      * @throws SAXException if there is a problem with the SAX Parser
156      * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
157      *         source}
158      */
159     public Graph.Batch importXml( InputStream stream,
160                                   Location location,
161                                   boolean skip ) throws IOException, SAXException, RepositorySourceException {
162         CheckArg.isNotNull(stream, "uri");
163         CheckArg.isNotNull(location, "location");
164         CheckArg.isNotNull(location.getPath(), "location.getPath()");
165 
166         // Create the destination for the XmlHandler ...
167         Graph.Batch batch = graph.batch();
168         Destination destination = new GraphBatchDestination(batch, true);
169 
170         // Determine where the content is to be placed ...
171         Path parentPath = location.getPath();
172         Name nameAttribute = JcrLexicon.NAME;
173         Name typeAttribute = JcrLexicon.PRIMARY_TYPE;
174         Name typeAttributeValue = null;
175         NamespaceRegistry reg = graph.getContext().getNamespaceRegistry();
176         if (reg.isRegisteredNamespaceUri(JcrNtLexicon.Namespace.URI)) {
177             typeAttributeValue = JcrNtLexicon.UNSTRUCTURED;
178         }
179 
180         TextDecoder decoder = null;
181         XmlHandler.AttributeScoping scoping = XmlHandler.AttributeScoping.USE_DEFAULT_NAMESPACE;
182         XmlHandler handler = new XmlHandler(destination, skip, parentPath, decoder, nameAttribute, typeAttribute,
183                                             typeAttributeValue, scoping);
184         XMLReader reader = XMLReaderFactory.createXMLReader();
185         reader.setContentHandler(handler);
186         reader.setErrorHandler(handler);
187         reader.parse(new InputSource(stream));
188         if (stream != null) stream.close();
189         return batch;
190     }
191 
192     /**
193      * Return an {@link XmlHandler} that can be used to import content directly into the supplied location. The operations
194      * resulting from the {@link XmlHandler} operations are batched until the {@link XmlHandler#endDocument()} is called, at which
195      * point all enqueued operations are submitted to the graph.
196      * 
197      * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
198      *        be null
199      * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element
200      * @return the {@link XmlHandler} that can be used to import content
201      * @throws IllegalArgumentException if the <code>stream</code> or destination path are null
202      */
203     public XmlHandler getHandlerForImportingXml( Location location,
204                                                  boolean skip ) {
205         CheckArg.isNotNull(location, "location");
206         CheckArg.isNotNull(location.getPath(), "location.getPath()");
207 
208         // Create the destination for the XmlHandler ...
209         Graph.Batch batch = graph.batch();
210         Destination destination = new GraphBatchDestination(batch, false);
211 
212         // Determine where the content is to be placed ...
213         Path parentPath = location.getPath();
214         Name nameAttribute = JcrLexicon.NAME;
215         Name typeAttribute = JcrLexicon.PRIMARY_TYPE;
216         Name typeAttributeValue = null;
217         NamespaceRegistry reg = graph.getContext().getNamespaceRegistry();
218         if (reg.isRegisteredNamespaceUri(JcrNtLexicon.Namespace.URI)) {
219             typeAttributeValue = JcrNtLexicon.UNSTRUCTURED;
220         }
221 
222         TextDecoder decoder = null;
223         XmlHandler.AttributeScoping scoping = XmlHandler.AttributeScoping.USE_DEFAULT_NAMESPACE;
224         XmlHandler handler = new XmlHandler(destination, skip, parentPath, decoder, nameAttribute, typeAttribute,
225                                             typeAttributeValue, scoping);
226         return handler;
227     }
228 
229 }