001 /* 002 * JBoss, Home of Professional Open Source. 003 * Copyright 2008, Red Hat Middleware LLC, and individual contributors 004 * as indicated by the @author tags. See the copyright.txt file in the 005 * distribution for a full listing of individual contributors. 006 * 007 * This is free software; you can redistribute it and/or modify it 008 * under the terms of the GNU Lesser General Public License as 009 * published by the Free Software Foundation; either version 2.1 of 010 * the License, or (at your option) any later version. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022 package org.jboss.dna.graph; 023 024 import java.io.IOException; 025 import java.io.InputStream; 026 import java.net.URI; 027 import java.util.List; 028 import net.jcip.annotations.NotThreadSafe; 029 import org.jboss.dna.common.text.TextDecoder; 030 import org.jboss.dna.common.util.CheckArg; 031 import org.jboss.dna.graph.connectors.RepositorySource; 032 import org.jboss.dna.graph.connectors.RepositorySourceException; 033 import org.jboss.dna.graph.properties.Name; 034 import org.jboss.dna.graph.properties.NamespaceRegistry; 035 import org.jboss.dna.graph.properties.Path; 036 import org.jboss.dna.graph.properties.Property; 037 import org.jboss.dna.graph.xml.XmlHandler; 038 import org.jboss.dna.graph.xml.XmlHandler.Destination; 039 import org.xml.sax.InputSource; 040 import org.xml.sax.SAXException; 041 import org.xml.sax.XMLReader; 042 import org.xml.sax.helpers.XMLReaderFactory; 043 044 /** 045 * @author Randall Hauch 046 * @author John Verhaeg 047 */ 048 public class GraphImporter { 049 050 private final Graph graph; 051 052 public GraphImporter( Graph graph ) { 053 CheckArg.isNotNull(graph, "graph"); 054 this.graph = graph; 055 } 056 057 /** 058 * Get the context in which the importer will be executed. 059 * 060 * @return the execution context; never null 061 */ 062 public ExecutionContext getContext() { 063 return this.graph.getContext(); 064 } 065 066 /** 067 * The graph that this importer uses. 068 * 069 * @return the graph; never null 070 */ 071 public Graph getGraph() { 072 return graph; 073 } 074 075 /** 076 * Read the content from the supplied URI and import into the repository at the supplied location. 077 * 078 * @param uri the URI where the importer can read the content that is to be imported 079 * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not 080 * be null 081 * @return the batch of requests for creating the graph content that represents the imported content 082 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null 083 * @throws IOException if there is a problem reading the content 084 * @throws SAXException if there is a problem with the SAX Parser 085 * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository 086 * source} 087 */ 088 public Graph.Batch importXml( URI uri, 089 Location location ) throws IOException, SAXException, RepositorySourceException { 090 return importXml(uri, location, false); 091 } 092 093 /** 094 * Read the content from the supplied URI and import into the repository at the supplied location. 095 * 096 * @param uri the URI where the importer can read the content that is to be imported 097 * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not 098 * be null 099 * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element 100 * @return the batch of requests for creating the graph content that represents the imported content 101 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null 102 * @throws IOException if there is a problem reading the content 103 * @throws SAXException if there is a problem with the SAX Parser 104 * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository 105 * source} 106 */ 107 public Graph.Batch importXml( URI uri, 108 Location location, 109 boolean skip ) throws IOException, SAXException, RepositorySourceException { 110 CheckArg.isNotNull(uri, "uri"); 111 CheckArg.isNotNull(location, "location"); 112 CheckArg.isNotNull(location.getPath(), "location.getPath()"); 113 114 // Create the destination for the XmlHandler ... 115 Graph.Batch batch = graph.batch(); 116 XmlHandler.Destination destination = new CreateOnGraphInBatch(batch); 117 118 // Determine where the content is to be placed ... 119 Path parentPath = location.getPath(); 120 InputStream stream = null; 121 Name nameAttribute = JcrLexicon.NAME; 122 Name typeAttribute = JcrLexicon.PRIMARY_TYPE; 123 Name typeAttributeValue = null; 124 NamespaceRegistry reg = graph.getContext().getNamespaceRegistry(); 125 if (reg.isRegisteredNamespaceUri(JcrNtLexicon.Namespace.URI)) { 126 typeAttributeValue = JcrNtLexicon.UNSTRUCTURED; 127 } 128 129 TextDecoder decoder = null; 130 XmlHandler.AttributeScoping scoping = XmlHandler.AttributeScoping.USE_DEFAULT_NAMESPACE; 131 XmlHandler handler = new XmlHandler(destination, skip, parentPath, decoder, nameAttribute, typeAttribute, 132 typeAttributeValue, scoping); 133 try { 134 stream = uri.toURL().openStream(); 135 XMLReader reader = XMLReaderFactory.createXMLReader(); 136 reader.setContentHandler(handler); 137 reader.setErrorHandler(handler); 138 reader.parse(new InputSource(stream)); 139 } finally { 140 if (stream != null) stream.close(); 141 } 142 return batch; 143 } 144 145 @NotThreadSafe 146 protected final static class CreateOnGraphInBatch implements Destination { 147 private final Graph.Batch batch; 148 149 protected CreateOnGraphInBatch( Graph.Batch batch ) { 150 assert batch != null; 151 this.batch = batch; 152 } 153 154 public ExecutionContext getExecutionContext() { 155 return batch.getGraph().getContext(); 156 } 157 158 public void create( Path path, 159 List<Property> properties ) { 160 assert properties != null; 161 if (properties.isEmpty()) { 162 batch.create(path).and(); 163 } else { 164 batch.create(path, properties).and(); 165 } 166 } 167 168 public void create( Path path, 169 Property firstProperty, 170 Property... additionalProperties ) { 171 if (firstProperty == null) { 172 batch.create(path).and(); 173 } else { 174 batch.create(path, firstProperty, additionalProperties); 175 } 176 } 177 178 public void submit() { 179 } 180 } 181 182 }