001 /*
002 * JBoss DNA (http://www.jboss.org/dna)
003 * See the COPYRIGHT.txt file distributed with this work for information
004 * regarding copyright ownership. Some portions may be licensed
005 * to Red Hat, Inc. under one or more contributor license agreements.
006 * See the AUTHORS.txt file in the distribution for a full listing of
007 * individual contributors.
008 *
009 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010 * is licensed to you under the terms of the GNU Lesser General Public License as
011 * published by the Free Software Foundation; either version 2.1 of
012 * the License, or (at your option) any later version.
013 *
014 * JBoss DNA is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017 * Lesser General Public License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this software; if not, write to the Free
021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023 */
024 package org.jboss.dna.graph.io;
025
026 import java.io.IOException;
027 import java.io.InputStream;
028 import java.net.URI;
029 import org.jboss.dna.common.text.TextDecoder;
030 import org.jboss.dna.common.util.CheckArg;
031 import org.jboss.dna.graph.ExecutionContext;
032 import org.jboss.dna.graph.Graph;
033 import org.jboss.dna.graph.JcrLexicon;
034 import org.jboss.dna.graph.JcrNtLexicon;
035 import org.jboss.dna.graph.Location;
036 import org.jboss.dna.graph.connector.RepositorySource;
037 import org.jboss.dna.graph.connector.RepositorySourceException;
038 import org.jboss.dna.graph.property.Name;
039 import org.jboss.dna.graph.property.NamespaceRegistry;
040 import org.jboss.dna.graph.property.Path;
041 import org.jboss.dna.graph.xml.XmlHandler;
042 import org.xml.sax.InputSource;
043 import org.xml.sax.SAXException;
044 import org.xml.sax.XMLReader;
045 import org.xml.sax.helpers.XMLReaderFactory;
046
047 /**
048 * @author Randall Hauch
049 * @author John Verhaeg
050 */
051 public class GraphImporter {
052
053 private final Graph graph;
054
055 public GraphImporter( Graph graph ) {
056 CheckArg.isNotNull(graph, "graph");
057 this.graph = graph;
058 }
059
060 /**
061 * Get the context in which the importer will be executed.
062 *
063 * @return the execution context; never null
064 */
065 public ExecutionContext getContext() {
066 return this.graph.getContext();
067 }
068
069 /**
070 * The graph that this importer uses.
071 *
072 * @return the graph; never null
073 */
074 public Graph getGraph() {
075 return graph;
076 }
077
078 /**
079 * Read the content from the supplied URI and import into the repository at the supplied location.
080 *
081 * @param uri the URI where the importer can read the content that is to be imported
082 * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
083 * be null
084 * @return the batch of requests for creating the graph content that represents the imported content
085 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
086 * @throws IOException if there is a problem reading the content
087 * @throws SAXException if there is a problem with the SAX Parser
088 * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
089 * source}
090 */
091 public Graph.Batch importXml( URI uri,
092 Location location ) throws IOException, SAXException, RepositorySourceException {
093 return importXml(uri, location, false);
094 }
095
096 /**
097 * Read the content from the supplied URI and import into the repository at the supplied location.
098 *
099 * @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 }