View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Intalio, Inc.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Intalio, Inc. Exolab is a registered
23   *    trademark of Intalio, Inc.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 1999-2004 (C) Intalio, Inc. All Rights Reserved.
42   *
43   * $Id$
44   */
45  
46  package org.exolab.castor.xml.schema.reader;
47  
48  //-- imported classes and packages
49  import org.exolab.castor.net.URIException;
50  import org.exolab.castor.net.URILocation;
51  import org.exolab.castor.net.URIResolver;
52  import org.exolab.castor.xml.AttributeSet;
53  import org.exolab.castor.xml.XMLException;
54  import org.exolab.castor.xml.schema.Schema;
55  import org.exolab.castor.xml.schema.SchemaContext;
56  import org.exolab.castor.xml.schema.SchemaException;
57  import org.exolab.castor.xml.schema.SchemaNames;
58  import org.xml.sax.InputSource;
59  import org.xml.sax.Locator;
60  import org.xml.sax.Parser;
61  
62  /**
63   * A simple unmarshaller to read included schemas.
64   * Included schemas can be cached in the original parent Schema or
65   * can be inlined in that same XML Schema as recommended by the XML Schema
66   * specification.
67   * 
68   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
69   * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
70   * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
71   **/
72  public class IncludeUnmarshaller extends ComponentReader
73  {
74  
75  
76      public IncludeUnmarshaller(
77              final SchemaContext schemaContext,
78              final Schema schema,
79              final AttributeSet atts,
80              final URIResolver uriResolver,
81              final Locator locator,
82              final SchemaUnmarshallerState state)
83      throws XMLException {
84          super(schemaContext);
85  
86          setURIResolver(uriResolver);
87          URILocation uri = null;
88  		//-- Get schemaLocation
89  		String include = atts.getValue("schemaLocation");
90  		if (include == null)
91  			throw new SchemaException("'schemaLocation' attribute missing on 'include'");
92  
93  		if (include.indexOf("\\") != -1) {
94              String err = include+" is not a valid URI as defined by IETF RFC 2396.";
95              err += "The URI must not contain '\\'.";
96              throw new SchemaException(err);
97  		}
98  
99          try {
100             String documentBase = locator.getSystemId();
101             if (documentBase != null) {
102                 if (!documentBase.endsWith("/"))
103                     documentBase = documentBase.substring(0, documentBase.lastIndexOf("/") +1 );
104             }
105 		    uri = getURIResolver().resolve(include, documentBase);
106         } catch (URIException ure) {
107             throw new XMLException(ure);
108         }
109 
110         if (uri != null)
111             include = uri.getAbsoluteURI();
112 
113         //-- Has this schema location been included yet?
114         if (schema.includeProcessed(include)) {
115             return;
116         }
117         else if (include.equals(schema.getSchemaLocation())) {
118             return;
119         }
120         
121         Schema includedSchema = null;
122         boolean alreadyLoaded = false;
123 
124         //-- caching is on
125         if (state.cacheIncludedSchemas) {
126             if (uri instanceof SchemaLocation) {
127         		includedSchema = ((SchemaLocation)uri).getSchema();
128         		schema.cacheIncludedSchema(includedSchema);
129         		alreadyLoaded = true;
130         	}
131         	//-- Have we already imported this XML Schema file?
132 	        if (state.processed(include)) {
133 	        	includedSchema = state.getSchema(include);
134 	        	schema.cacheIncludedSchema(includedSchema);
135 	        	alreadyLoaded = true;
136 	        }
137         }
138 	    
139         if (includedSchema == null)
140 	    	includedSchema = new Schema();
141         else
142         	state.markAsProcessed(include, includedSchema);
143         
144         //-- keep track of the schemaLocation
145         schema.addInclude(include);
146 
147         if (alreadyLoaded)
148         	return;
149 		Parser parser = null;
150 		try {
151 		    parser = getSchemaContext().getParser();
152 		}
153 		catch(RuntimeException rte) {}
154 		if (parser == null) {
155 		    throw new SchemaException("Error failed to create parser for include");
156 		}
157 		SchemaUnmarshaller schemaUnmarshaller = new SchemaUnmarshaller(getSchemaContext(), true, state, getURIResolver());
158 
159 		if (state.cacheIncludedSchemas)
160 		    schemaUnmarshaller.setSchema(includedSchema);
161 		else
162 			schemaUnmarshaller.setSchema(schema);
163 		
164 		Sax2ComponentReader handler = new Sax2ComponentReader(schemaUnmarshaller);
165 		parser.setDocumentHandler(handler);
166 		parser.setErrorHandler(handler);
167 
168 		try {
169             InputSource source = new InputSource(uri.getReader());
170             source.setSystemId(uri.getAbsoluteURI());
171             parser.parse(source);
172 		}
173 		catch(java.io.IOException ioe) {
174 		    throw new SchemaException("Error reading include file '"+include+"'");
175 		}
176 		catch(org.xml.sax.SAXException sx) {
177 		    throw new SchemaException(sx);
178 		}
179 		if (state.cacheIncludedSchemas) {
180 			String ns = includedSchema.getTargetNamespace();
181 			if (ns == null || ns == "")
182 				includedSchema.setTargetNamespace(schema.getTargetNamespace());
183 			else if (!ns.equals(schema.getTargetNamespace()))
184 				throw new SchemaException("The target namespace of the included components must be the same as the target namespace of the including schema");
185 			schema.cacheIncludedSchema(includedSchema);
186 		}
187 	}
188 
189 
190     /**
191      * Sets the name of the element that this UnknownUnmarshaller handles
192     **/
193     public String elementName() {
194         return SchemaNames.INCLUDE;
195     } //-- elementName
196 
197     /**
198      * Returns the Object created by this ComponentReader
199      * @return the Object created by this ComponentReader
200     **/
201     public Object getObject() {
202         return null;
203     } //-- getObject
204 
205 }