KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > xb > binding > sunday > unmarshalling > DefaultSchemaResolver


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.xb.binding.sunday.unmarshalling;
23
24 import java.net.URL JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import org.jboss.logging.Logger;
30 import org.jboss.util.xml.JBossEntityResolver;
31 import org.w3c.dom.ls.LSInput JavaDoc;
32 import org.xml.sax.InputSource JavaDoc;
33
34 /**
35  * A default SchemaBindingResolver that uses a JBossEntityResolver to locate
36  * the schema xsd.
37  *
38  * @author Scott.Stark@jboss.org
39  * @version $Revision: 2123 $
40  */

41 public class DefaultSchemaResolver implements SchemaBindingResolver
42 {
43    private static Logger log = Logger.getLogger(DefaultSchemaResolver.class);
44
45    private String JavaDoc baseURI;
46    private JBossEntityResolver resolver;
47    private boolean cacheResolvedSchemas = true;
48    private Map JavaDoc schemasByUri = Collections.EMPTY_MAP;
49    private Map JavaDoc schemaInitByUri = Collections.EMPTY_MAP;
50    private Map JavaDoc schemaParseAnnotationsByUri = Collections.EMPTY_MAP;
51
52    public DefaultSchemaResolver()
53    {
54       this(new JBossEntityResolver());
55    }
56
57    public DefaultSchemaResolver(JBossEntityResolver resolver)
58    {
59       this.resolver = resolver;
60    }
61
62    /**
63     * @return true if resolved SchemaBinding's are cached, false otherwise
64     */

65    public boolean isCacheResolvedSchemas()
66    {
67       return cacheResolvedSchemas;
68    }
69
70    /**
71     * Passing in true will make the schema resolver to cache successfully resolved
72     * schemas (which is the default) with namespace URI being the identifier of a schema.
73     * False will flush the cache and make the schema resolver to resolve schemas
74     * on each request.
75     * @param cacheResolvedSchemas
76     */

77    public void setCacheResolvedSchemas(boolean cacheResolvedSchemas)
78    {
79       this.cacheResolvedSchemas = cacheResolvedSchemas;
80       if(!cacheResolvedSchemas)
81       {
82          schemasByUri = Collections.EMPTY_MAP;
83       }
84    }
85
86    /**
87     * Registers a location for the namespace URI.<p>
88     *
89     * This location is looked using the JBossEntityResolver, i.e. it is a classpath location
90     *
91     * @param nsUri the namespace location
92     * @param location the classpath location
93     */

94    public void addSchemaLocation(String JavaDoc nsUri, String JavaDoc location)
95    {
96       resolver.registerLocalEntity(nsUri, location);
97    }
98    
99
100    /**
101     * Removes a location for the namespace URI.
102     *
103     * @todo actually remove it rather than setting null
104     * @param nsUri the namespace location
105     */

106    public void removeSchemaLocation(String JavaDoc nsUri)
107    {
108       resolver.registerLocalEntity(nsUri, null);
109    }
110
111    /**
112     * Whether to parse annotations for this namespace.
113     *
114     * @param nsUri the namespace
115     * @param value the value of the option
116     */

117    public void addSchemaParseAnnotations(String JavaDoc nsUri, Boolean JavaDoc value)
118    {
119       if (nsUri == null)
120          throw new IllegalArgumentException JavaDoc("Null namespace uri");
121       if (value == null)
122          throw new IllegalArgumentException JavaDoc("Null value");
123       switch(schemaParseAnnotationsByUri.size())
124       {
125          case 0:
126             schemaParseAnnotationsByUri = Collections.singletonMap(nsUri, value);
127             break;
128          case 1:
129             schemaParseAnnotationsByUri = new HashMap JavaDoc(schemaParseAnnotationsByUri);
130          default:
131             schemaParseAnnotationsByUri.put(nsUri, value);
132       }
133    }
134    
135    /**
136     * Removes the parse annotation configuration for this namespace
137     *
138     * @param nsUri the namespace
139     * @return the previous value
140     */

141    public Boolean JavaDoc removeSchemaParseAnnotations(String JavaDoc nsUri)
142    {
143       if (nsUri == null)
144          throw new IllegalArgumentException JavaDoc("Null namespace uri");
145       return (Boolean JavaDoc) schemaParseAnnotationsByUri.remove(nsUri);
146    }
147    
148    /**
149     * Registers a SchemaBindingInitializer for the namespace URI.
150     * When the schema binding that corresponds to the namespace URI
151     * is resolved, the init(SchemaBinding schema) method will be invoked on the
152     * instance of SchemaBindingInitializer with the SchemaBinding returned from the
153     * XsdBinder.bind() method.
154     *
155     * @param nsUri the namespace URI to register the schema initializer for
156     * @param sbiClassName the class name SchemaBindingInitializer
157     * @throws Exception for any error
158     */

159    public void addSchemaInitializer(String JavaDoc nsUri, String JavaDoc sbiClassName) throws Exception JavaDoc
160    {
161       if (sbiClassName == null)
162          throw new IllegalArgumentException JavaDoc("Null class name");
163       Class JavaDoc clazz = Thread.currentThread().getContextClassLoader().loadClass(sbiClassName);
164       Object JavaDoc object = clazz.newInstance();
165       if (object instanceof SchemaBindingInitializer == false)
166          throw new IllegalArgumentException JavaDoc(clazz.getName() + " is not an instance of " + SchemaBindingInitializer.class.getName());
167       SchemaBindingInitializer sbi = (SchemaBindingInitializer) object;
168       addSchemaInitializer(nsUri, sbi);
169    }
170
171    /**
172     * Registers an instance of SchemaBindingInitializer for the namespace URI.
173     * When the schema binding that corresponds to the namespace URI
174     * is resolved, the init(SchemaBinding schema) method will be invoked on the
175     * instance of SchemaBindingInitializer with the SchemaBinding returned from the
176     * XsdBinder.bind() method.
177     *
178     * @param nsUri the namespace URI to register the schema initializer for
179     * @param sbi an instance of SchemaBindingInitializer
180     */

181    public void addSchemaInitializer(String JavaDoc nsUri, SchemaBindingInitializer sbi)
182    {
183       if (nsUri == null)
184          throw new IllegalArgumentException JavaDoc("Null namespace uri");
185       if (sbi == null)
186          throw new IllegalArgumentException JavaDoc("Null schema binding initializer");
187       switch(schemaInitByUri.size())
188       {
189          case 0:
190             schemaInitByUri = Collections.singletonMap(nsUri, sbi);
191             break;
192          case 1:
193             schemaInitByUri = new HashMap JavaDoc(schemaInitByUri);
194          default:
195             schemaInitByUri.put(nsUri, sbi);
196       }
197    }
198
199    /**
200     * Unregisters and returns the SchemaBindingInitializer for the namespace URI.
201     * @param nsUri the namespace URI to unregister SchemaBindingInitializer for
202     * @return unregistered SchemaBindingInitializer for the namespace URI or null
203     * if there was no SchemaBindingInitialzer registered for the namespace URI
204     */

205    public SchemaBindingInitializer removeSchemaInitializer(String JavaDoc nsUri)
206    {
207       if (nsUri == null)
208          throw new IllegalArgumentException JavaDoc("Null namespace uri");
209       return (SchemaBindingInitializer)schemaInitByUri.remove(nsUri);
210    }
211
212    public String JavaDoc getBaseURI()
213    {
214       return baseURI;
215    }
216
217    public void setBaseURI(String JavaDoc baseURI)
218    {
219       this.baseURI = baseURI;
220    }
221
222    /**
223     * Uses the JBossEntityResolver.resolveEntity by:
224     *
225     * 1. Using the nsUri as the systemID
226     * 2. Using the schemaLocation as the systemID
227     * 3. If that fails, the baseURI is not null, the xsd is located using URL(baseURL, schemaLocation)
228     * 4. If the baseURI is null, the xsd is located using URL(schemaLocation)
229     */

230    public SchemaBinding resolve(String JavaDoc nsURI, String JavaDoc baseURI, String JavaDoc schemaLocation)
231    {
232       SchemaBinding schema = (SchemaBinding)schemasByUri.get(nsURI);
233       if(schema != null)
234       {
235          return schema;
236       }
237
238       InputSource JavaDoc is = getInputSource(nsURI, baseURI, schemaLocation);
239       
240       if (is != null)
241       {
242          if( baseURI == null )
243             baseURI = this.baseURI;
244
245          Boolean JavaDoc processAnnotationsBoolean = (Boolean JavaDoc) schemaParseAnnotationsByUri.get(nsURI);
246          boolean processAnnotations = (processAnnotationsBoolean == null) ? true : processAnnotationsBoolean.booleanValue();
247          schema = XsdBinder.bind(is.getByteStream(), null, baseURI, processAnnotations);
248       }
249
250       if(schema != null)
251       {
252          schema.setSchemaResolver(this);
253          SchemaBindingInitializer sbi = (SchemaBindingInitializer)schemaInitByUri.get(nsURI);
254          if(sbi != null)
255          {
256             schema = sbi.init(schema);
257          }
258
259          if(schema != null && cacheResolvedSchemas)
260          {
261             if(schemasByUri == Collections.EMPTY_MAP)
262             {
263                schemasByUri = new HashMap JavaDoc();
264             }
265             schemasByUri.put(nsURI, schema);
266          }
267       }
268
269       if(log.isTraceEnabled())
270       {
271          log.trace("resolved schema: " + schema);
272       }
273
274       return schema;
275    }
276
277    public LSInput JavaDoc resolveAsLSInput(String JavaDoc nsURI, String JavaDoc baseURI, String JavaDoc schemaLocation)
278    {
279       LSInput JavaDoc lsInput = null;
280       InputSource JavaDoc is = getInputSource(nsURI, baseURI, schemaLocation);
281       if (is != null)
282       {
283          String JavaDoc publicId = is.getPublicId();
284          String JavaDoc systemId = is.getSystemId();
285          lsInput = new LSInputAdaptor(publicId, systemId, baseURI);
286          lsInput.setCharacterStream(is.getCharacterStream());
287          lsInput.setByteStream(is.getByteStream());
288          lsInput.setEncoding(is.getEncoding());
289       }
290       return lsInput;
291    }
292
293    private InputSource JavaDoc getInputSource(String JavaDoc nsURI, String JavaDoc baseURI, String JavaDoc schemaLocation)
294    {
295       boolean trace = log.isTraceEnabled();
296       InputSource JavaDoc is = null;
297
298       if( trace )
299          log.trace("getInputSource, nsURI="+nsURI+", baseURI="+baseURI+", schemaLocation="+schemaLocation);
300
301       // First try what is requested
302
try
303       {
304          is = resolver.resolveEntity(nsURI, schemaLocation);
305          if (trace)
306             log.trace("Resolved schema using namespace as publicId and schemaLocation as systemId");
307       }
308       catch (Exception JavaDoc e)
309       {
310          if (trace)
311             log.trace("Failed to use nsUri/schemaLocation", e);
312       }
313
314       // Next, try to use the baseURI to resolve the schema location
315
if(baseURI == null)
316       {
317          baseURI = this.baseURI;
318       }
319
320       if (is == null && baseURI != null && schemaLocation != null)
321       {
322          try
323          {
324             URL JavaDoc url = new URL JavaDoc(baseURI);
325             url = new URL JavaDoc(url, schemaLocation);
326             String JavaDoc resolvedSchemaLocation = url.toString();
327             // No point if the schema location was already absolute
328
if (schemaLocation.equals(resolvedSchemaLocation) == false)
329             {
330                is = resolver.resolveEntity(null, url.toString());
331                if( trace && is != null )
332                   log.trace("Resolved schema location using baseURI");
333             }
334          }
335          catch (Exception JavaDoc e)
336          {
337             if (trace)
338                log.trace("Failed to use schema location with baseURI", e);
339          }
340       }
341
342       // Finally, just try the namespace as the system id
343
if (is == null && nsURI != null)
344       {
345          try
346          {
347             is = resolver.resolveEntity(null, nsURI);
348             if( trace && is != null )
349                log.trace("Resolved namespace as system id");
350          }
351          catch (Exception JavaDoc e)
352          {
353             if (trace)
354                log.trace("Failed to use namespace as system id", e);
355          }
356       }
357       if( trace )
358       {
359          log.trace("getInputSource, nsURI="+nsURI+", baseURI="
360             +baseURI+", schemaLocation="+schemaLocation+", is="+is);
361       }
362       return is;
363    }
364 }
365
Popular Tags