View Javadoc

1   /*
2    * Copyright 2005 The Codehaus.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.codehaus.mojo.castor;
17  
18  import java.io.File;
19  import java.io.FileWriter;
20  import java.io.Writer;
21  import java.lang.reflect.Method;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import java.net.URLClassLoader;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.apache.maven.artifact.Artifact;
29  import org.apache.maven.artifact.DependencyResolutionRequiredException;
30  import org.apache.maven.plugin.AbstractMojo;
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.plugin.MojoFailureException;
33  import org.apache.maven.plugins.annotations.Parameter;
34  import org.apache.maven.project.MavenProject;
35  import org.exolab.castor.tools.MappingTool;
36  
37  /**
38   * A mojo that uses Castor MappingTool to generate mapping files from a Class. <a
39   * href="http://castor.codehaus.org/javadoc/org/exolab/castor/tools/MappingTool.html"> MappingTool</a>.
40   * 
41   * @author nicolas <nicolas@apache.org>
42   */
43  public abstract class AbstractMappingMojo
44      extends AbstractMojo
45  {
46      /**
47       * The Maven project to act upon.
48       */
49      @Parameter(property = "project", defaultValue = "${project}", required = true)
50      private MavenProject project;
51  
52      /**
53       * Whether to force generation of mapping file where one already exists.
54       */
55      @Parameter(property = "force", defaultValue = "false")
56      private boolean force;
57  
58      /**
59       * The output directory.
60       */
61      @Parameter(property = "outputDirectory", defaultValue = "${project.build.outputDirectory}")
62      private File outputDirectory;
63  
64      /**
65       * Private (project) class loader.
66       */
67      private ClassLoader projectClassLoader;
68  
69      /**
70       * {@inheritDoc}
71       * 
72       * @see org.apache.maven.plugin.Mojo#execute()
73       */
74      public void execute()
75          throws MojoExecutionException, MojoFailureException
76      {
77          try
78          {
79              outputDirectory.mkdirs();
80              getLog().info( "Generate mapping " + getMappingName() + " for class " + getClassName() );
81  
82              ClassLoader cl = getProjectClassLoader();
83  
84              MappingTool tool = new MappingTool();
85  
86              // As of Castor 1.2, an InternalContext needs to be set; using reflection
87              // to set it or not
88              Class<?> internalContextClass;
89              try
90              {
91                  internalContextClass = Class.forName( "org.castor.xml.InternalContext" );
92                  Class<?> backwardsCompatibilityClass = Class.forName( "org.castor.xml.BackwardCompatibilityContext" );
93                  Method setter =
94                      MappingTool.class.getMethod( "setInternalContext", new Class[] { internalContextClass } );
95                  if ( setter != null )
96                  {
97                      getLog().info( "About to invoke 'setInternalContext()' on org.exolab.castor.tools.MappingTool" );
98                      setter.invoke( tool, new Object[] { backwardsCompatibilityClass.newInstance() } );
99                  }
100             }
101             catch ( ClassNotFoundException e )
102             {
103                 // nothing to do as we check whether the class(es) exist or not
104             }
105 
106             Class<?> clazz = cl.loadClass( getClassName() );
107             tool.addClass( clazz );
108 
109             File file = new File( outputDirectory, getMappingName().trim() );
110             if ( file.exists() && ( !force ) )
111             {
112                 getLog().info( getMappingName() + " allready generated" );
113                 return;
114             }
115 
116             Writer writer = new FileWriter( file );
117             tool.write( writer );
118         }
119         catch ( Exception e )
120         {
121             throw new MojoExecutionException( "Failed to generate mapping for " + getClassName(), e );
122         }
123     }
124 
125     /**
126      * Returns the private project {@link ClassLoader}.
127      * 
128      * @return A project-specific {@link ClassLoader}.
129      * @throws DependencyResolutionRequiredException If a dependecy cannot be resolved.
130      * @throws MalformedURLException If an URL is malformed.
131      */
132     protected ClassLoader getProjectClassLoader()
133         throws DependencyResolutionRequiredException, MalformedURLException
134     {
135         if ( projectClassLoader != null )
136         {
137             return projectClassLoader;
138         }
139 
140         List compile = project.getCompileClasspathElements();
141         URL[] urls = new URL[compile.size()];
142         int i = 0;
143         for ( Iterator iterator = compile.iterator(); iterator.hasNext(); )
144         {
145             Object object = (Object) iterator.next();
146             if ( object instanceof Artifact )
147             {
148                 urls[i] = ( (Artifact) object ).getFile().toURL();
149             }
150             else
151             {
152                 urls[i] = new File( (String) object ).toURL();
153             }
154             i++;
155         }
156         projectClassLoader = new URLClassLoader( urls, getClass().getClassLoader().getSystemClassLoader() );
157         return projectClassLoader;
158     }
159 
160     /**
161      * Returns the class name.
162      * 
163      * @return the classname
164      */
165     protected abstract String getClassName();
166 
167     /**
168      * Returns the name of the mapping file.
169      * 
170      * @return the mappingName
171      */
172     protected abstract String getMappingName();
173 }