001: package org.geotools.xml;
002:
003: import java.io.IOException;
004: import java.util.ArrayList;
005: import java.util.Iterator;
006: import java.util.List;
007: import java.util.logging.Level;
008: import java.util.logging.Logger;
009:
010: import org.eclipse.xsd.XSDSchema;
011: import org.eclipse.xsd.util.XSDSchemaLocationResolver;
012: import org.eclipse.xsd.util.XSDSchemaLocator;
013:
014: /**
015: * Creates a schema from scratch for a particular namespace.
016: * <p>
017: * This class works from a {@link org.geotools.xml.Configuration} which defines information about
018: * the schema.
019: * </p>
020: * <p>
021: * Example usage:
022: *
023: * <code>
024: * <pre>
025: * Configuration myConfig = ...
026: * String namespaceURI = myConfig.getNamesapceURI();
027: *
028: * SchemaLocator locator = new SchemaLocator( myConfig );
029: * XSDSchema schema = locator.locateSchema( null, namespaceURI, null, null);
030: * </pre>
031: * </code>
032: *
033: * </p>
034: * @author Justin Deoliveira, The Open Planning Project
035: *
036: */
037: public class SchemaLocator implements XSDSchemaLocator {
038:
039: static Logger logger = org.geotools.util.logging.Logging
040: .getLogger("org.geotools.xml");
041:
042: /**
043: * the configuration
044: */
045: protected Configuration configuration;
046:
047: /**
048: * cached schema
049: */
050: XSDSchema schema;
051:
052: /**
053: * Creates a new schema location.
054: *
055: * @param configuration the configuration defining information about the schema.
056: */
057: public SchemaLocator(Configuration configuration) {
058: this .configuration = configuration;
059: }
060:
061: /**
062: * Creates the schema, returning <code>null</code> if the schema could not be created.
063: * </p>
064: * <code>namespaceURI</code> should not be <code>null</code>. All other paramters are ignored.
065: * </p>
066: * <p>
067: * This method caches the returned schema, and is thread safe.
068: * </p>
069: *
070: * @see XSDSchemaLocator#locateSchema(org.eclipse.xsd.XSDSchema, java.lang.String, java.lang.String, java.lang.String)
071: */
072: public XSDSchema locateSchema(XSDSchema schema,
073: String namespaceURI, String rawSchemaLocationURI,
074: String resolvedSchemaLocationURI) {
075:
076: if (configuration.getNamespaceURI().equals(namespaceURI)) {
077: if (this .schema != null) {
078: logger.finer("returning cached schema for "
079: + namespaceURI);
080: return this .schema;
081: }
082:
083: synchronized (this ) {
084: if (this .schema != null) {
085: logger.finer("returning cached schema for "
086: + namespaceURI);
087: return this .schema;
088: }
089:
090: try {
091: this .schema = createSchema();
092: } catch (Throwable t) {
093: String msg = "Failed to create schema: "
094: + configuration.getNamespaceURI();
095: logger.log(Level.WARNING, msg, t);
096: }
097: }
098:
099: return this .schema;
100: }
101:
102: return null;
103: }
104:
105: /**
106: * Template method for creating the schema instance from the xml configuration.
107: * <p>
108: * Subclasses may with to override or exten this method. The default implementation
109: * uses {@link Configuration#getSchemaFileURL()} and {@link Configuration#getSchemaLocationResolver()}
110: * to parse the schema directly.
111: * </p>
112: *
113: * @return The created schema.
114: *
115: * @throws Exception Any errors that occur while parsing the schema.
116: */
117: protected XSDSchema createSchema() throws Exception {
118: //add dependent location resolvers
119: List resolvers = new ArrayList();
120: for (Iterator d = configuration.allDependencies().iterator(); d
121: .hasNext();) {
122: Configuration dependency = (Configuration) d.next();
123: XSDSchemaLocationResolver resolver = dependency
124: .getSchemaLocationResolver();
125:
126: if (resolver != null) {
127: resolvers.add(resolver);
128: }
129: }
130:
131: String location = configuration.getSchemaFileURL().toString();
132: if (logger.isLoggable(Level.FINE))
133: logger.fine("parsing schema "
134: + configuration.getNamespaceURI());
135: return Schemas.parse(location, null, resolvers);
136: }
137: }
|