001: package org.geotools.maven.xmlcodegen;
002:
003: import java.io.BufferedOutputStream;
004: import java.io.File;
005: import java.io.FileOutputStream;
006: import java.io.IOException;
007: import java.io.InputStream;
008: import java.net.URL;
009: import java.net.URLClassLoader;
010: import java.util.ArrayList;
011: import java.util.Iterator;
012: import java.util.List;
013:
014: import org.apache.maven.artifact.Artifact;
015: import org.apache.maven.artifact.factory.ArtifactFactory;
016: import org.apache.maven.artifact.factory.DefaultArtifactFactory;
017: import org.apache.maven.artifact.repository.ArtifactRepository;
018: import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
019: import org.apache.maven.artifact.resolver.ArtifactResolutionException;
020: import org.apache.maven.artifact.resolver.ArtifactResolver;
021: import org.apache.maven.model.Repository;
022: import org.apache.maven.plugin.AbstractMojo;
023: import org.apache.maven.project.MavenProject; //import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.Utils;
024: import org.codehaus.plexus.context.Context;
025: import org.codehaus.plexus.context.ContextException;
026: import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
027: import org.codehaus.plexus.util.FileUtils;
028: import org.eclipse.xsd.XSDSchema;
029: import org.eclipse.xsd.util.XSDSchemaLocationResolver;
030: import org.eclipse.xsd.util.XSDSchemaLocator;
031: import org.geotools.xml.Schemas;
032:
033: /**
034: * Generates the bindings and utility classes used to parse xml documents
035: * for a particular schema.
036: *
037: * @author Justin Deoliveira, The Open Planning Project
038: *
039: */
040: public abstract class AbstractGeneratorMojo extends AbstractMojo {
041:
042: /**
043: * The .xsd file defining the schema to generate bindings for.
044: *
045: * @parameter
046: * @required
047: */
048: protected File schemaLocation;
049:
050: /**
051: * Directory containing xml schemas, default is ${basedir}/src/main/xsd.
052: *
053: * @parameter expression="${basedir}/src/main/xsd"
054: */
055: protected File schemaSourceDirectory;
056:
057: /**
058: * Additional directories used to locate included and imported schemas.
059: *
060: * @parameter
061: */
062: protected File[] schemaLookupDirectories;
063:
064: /**
065: * The destination package of the generated source files in the standard dot-seperated
066: * naming format.
067: *
068: * @parameter
069: */
070: protected String destinationPackage;
071:
072: /**
073: * Directory to output generated files to. Default is ${project.build.sourceDirectory}
074: *
075: * @parameter expression="${project.build.sourceDirectory}"
076: */
077: protected File outputDirectory;
078:
079: /**
080: * Flag controlling wether files should overide files that already
081: * exist with the same name. False by default.
082: *
083: * @param expression="false"
084: */
085: protected boolean overwriteExistingFiles;
086: /**
087: * The prefix to use for the targetNamespace.
088: *
089: * @parameter
090: */
091: protected String targetPrefix;
092: /**
093: * The currently executing project
094: *
095: * @parameter expression="${project}"
096: */
097: MavenProject project;
098:
099: /**
100: * The local maven repository
101: *
102: * @parameter expression="${localRepository}"
103: */
104: ArtifactRepository localRepository;
105:
106: /**
107: * Remote maven repositories
108: *
109: * @parameter expression="${project.remoteArtifactRepositories}"
110: */
111: List remoteRepositories;
112:
113: /**
114: * @component
115: */
116: ArtifactFactory artifactFactory;
117:
118: /**
119: * @component
120: */
121: ArtifactResolver artifactResolver;
122:
123: protected XSDSchema schema() {
124:
125: getLog().info(artifactFactory.toString());
126:
127: //check schema source
128: if (!schemaSourceDirectory.exists()) {
129: getLog().error(
130: schemaSourceDirectory.getAbsolutePath()
131: + " does not exist");
132: return null;
133: }
134:
135: //check schema
136: if (!schemaLocation.exists()) {
137: //check relative to schemaSourceDirectory
138: schemaLocation = new File(schemaSourceDirectory,
139: schemaLocation.getName());
140: if (!schemaLocation.exists()) {
141: getLog().error(
142: "Could not locate schema: "
143: + schemaLocation.getName());
144: return null;
145: }
146: }
147:
148: //build an "extended" classloader for "well-known
149: List artifacts = new ArrayList();
150: artifacts.add(artifactFactory.createArtifact("org.geotools",
151: "gt2-xml-gml2", "2.4-SNAPSHOT", null, "jar"));
152: artifacts.add(artifactFactory.createArtifact("org.geotools",
153: "gt2-xml-gml3", "2.4-SNAPSHOT", null, "jar"));
154: artifacts.add(artifactFactory.createArtifact("org.geotools",
155: "gt2-xml-filter", "2.4-SNAPSHOT", null, "jar"));
156: artifacts.add(artifactFactory.createArtifact("org.geotools",
157: "gt2-xml-sld", "2.4-SNAPSHOT", null, "jar"));
158:
159: List urls = new ArrayList();
160: for (Iterator a = artifacts.iterator(); a.hasNext();) {
161: Artifact artifact = (Artifact) a.next();
162: try {
163: artifactResolver.resolve(artifact, remoteRepositories,
164: localRepository);
165: urls.add(artifact.getFile().toURL());
166: } catch (Exception e) {
167: getLog().warn("Unable to resolve " + artifact.getId());
168: }
169: }
170:
171: ClassLoader ext = new URLClassLoader((URL[]) urls
172: .toArray(new URL[urls.size()]), getClass()
173: .getClassLoader());
174:
175: //use extended classloader to load up configuration classes to load schema files
176: // with
177: final List resolvers = new ArrayList();
178: resolvers
179: .add("org.geotools.xlink.bindings.XLINKSchemaLocationResolver");
180: resolvers
181: .add("org.geotools.gml2.bindings.GMLSchemaLocationResolver");
182: resolvers
183: .add("org.geotools.gml3.bindings.GMLSchemaLocationResolver");
184: resolvers
185: .add("org.geotools.gml3.bindings.smil.SMIL20SchemaLocationResolver");
186: resolvers
187: .add("org.geotools.filter.v1_0.OGCSchemaLocationResolver");
188: resolvers
189: .add("org.geotools.filter.v1_1.OGCSchemaLocationResolver");
190:
191: for (int i = 0; i < resolvers.size(); i++) {
192: String className = (String) resolvers.get(i);
193: try {
194: Class clazz = ext.loadClass(className);
195: resolvers.set(i, clazz);
196: } catch (ClassNotFoundException e) {
197: getLog().debug("Unable to load " + className);
198: resolvers.set(i, null);
199: }
200: }
201:
202: //add a location resolver which checks the schema source directory
203: XSDSchemaLocationResolver locationResolver = new XSDSchemaLocationResolver() {
204:
205: File schemaDir = null;
206:
207: public String resolveSchemaLocation(XSDSchema schema,
208: String namespaceURI, String schemaLocation) {
209:
210: //check location directlry
211: File file = new File(schemaLocation);
212: if (file.exists()) {
213: getLog().debug(
214: "Resolving " + schemaLocation + " to "
215: + schemaLocation);
216: return schemaLocation;
217: }
218:
219: String fileName = new File(schemaLocation).getName();
220:
221: //check under teh schema source directory
222: file = new File(schemaSourceDirectory, fileName);
223: if (file.exists()) {
224: getLog().debug(
225: "Resolving " + schemaLocation + " to "
226: + file.getAbsolutePath());
227: return file.getAbsolutePath();
228: }
229:
230: //check hte lookup directories
231: if (schemaLookupDirectories != null) {
232: for (int i = 0; i < schemaLookupDirectories.length; i++) {
233: File schemaLookupDirectory = schemaLookupDirectories[i];
234: file = new File(schemaLookupDirectory, fileName);
235: if (file.exists()) {
236: getLog().debug(
237: "Resolving " + schemaLocation
238: + " to "
239: + file.getAbsolutePath());
240: return file.getAbsolutePath();
241: }
242:
243: }
244: }
245:
246: //check for well known
247: if (schemaDir == null) {
248: try {
249: schemaDir = File.createTempFile("xmlcodegen",
250: "xsd");
251: getLog().debug(
252: "Creating "
253: + schemaDir.getAbsolutePath());
254: schemaDir.delete();
255: schemaDir.mkdir();
256: } catch (IOException e) {
257: getLog().debug(e);
258: return null;
259: }
260:
261: }
262:
263: file = new File(schemaDir, fileName);
264: if (file.exists()) {
265: getLog().debug(
266: "Resolving " + schemaLocation + " to "
267: + file.getAbsolutePath());
268: return file.getAbsolutePath();
269: }
270:
271: for (Iterator i = resolvers.iterator(); i.hasNext();) {
272: Class configClass = (Class) i.next();
273: if (configClass == null) {
274: continue;
275: }
276:
277: if (configClass.getResource(fileName) != null) {
278: //copy stream to a temp file
279: try {
280: file = new File(schemaDir, fileName);
281: file.deleteOnExit();
282:
283: getLog()
284: .debug(
285: "Copying "
286: + configClass
287: .getResource(fileName)
288: + " " + file);
289:
290: BufferedOutputStream output = new BufferedOutputStream(
291: new FileOutputStream(file));
292: InputStream input = configClass
293: .getResourceAsStream(fileName);
294:
295: int b = -1;
296: while ((b = input.read()) != -1) {
297: output.write(b);
298: }
299:
300: input.close();
301: output.close();
302:
303: getLog().debug(
304: "Resolving " + schemaLocation
305: + " to "
306: + file.getAbsolutePath());
307: return file.getAbsolutePath();
308:
309: } catch (IOException e) {
310: getLog().debug(e);
311: continue;
312: }
313:
314: }
315: }
316:
317: getLog().warn(
318: "Could not resolve location for: " + fileName);
319: return null;
320: }
321:
322: };
323:
324: //parse the schema
325: XSDSchema xsdSchema = null;
326: try {
327: getLog().info("Parsing schema: " + schemaLocation);
328: xsdSchema = Schemas
329: .parse(
330: schemaLocation.getAbsolutePath(),
331: (XSDSchemaLocator[]) null,
332: new XSDSchemaLocationResolver[] { locationResolver });
333:
334: if (xsdSchema == null) {
335: throw new NullPointerException();
336: }
337: } catch (Exception e) {
338: getLog().error("Failed to parse schema");
339: getLog().error(e);
340: return null;
341: }
342:
343: //set the target prefix if set
344: if (targetPrefix != null) {
345: xsdSchema.getQNamePrefixToNamespaceMap().put(targetPrefix,
346: xsdSchema.getTargetNamespace());
347: }
348:
349: //do some sanity checks on the schema
350: if (Schemas.getTargetPrefix(xsdSchema) == null) {
351: String msg = "Unable to determine a prefix for the target namespace "
352: + "of the schema Either include a mapping in the schema or manually "
353: + "specify one with the 'targetPrefix' parameter.";
354: throw new RuntimeException(msg);
355: }
356:
357: return xsdSchema;
358: }
359:
360: }
|