001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.xbean.maven;
018
019import java.beans.PropertyEditorManager;
020import java.io.File;
021import java.net.MalformedURLException;
022import java.net.URL;
023import java.net.URLClassLoader;
024import java.util.ArrayList;
025import java.util.Arrays;
026import java.util.Collections;
027import java.util.HashSet;
028import java.util.Iterator;
029import java.util.LinkedList;
030import java.util.List;
031import java.util.Set;
032import java.util.StringTokenizer;
033
034import org.apache.maven.artifact.Artifact;
035import org.apache.maven.model.Resource;
036import org.apache.maven.plugin.AbstractMojo;
037import org.apache.maven.plugin.MojoExecutionException;
038import org.apache.maven.plugin.MojoFailureException;
039import org.apache.maven.project.MavenProject;
040import org.apache.maven.project.MavenProjectHelper;
041import org.apache.tools.ant.BuildException;
042import org.apache.xbean.spring.generator.DocumentationGenerator;
043import org.apache.xbean.spring.generator.GeneratorPlugin;
044import org.apache.xbean.spring.generator.LogFacade;
045import org.apache.xbean.spring.generator.MappingLoader;
046import org.apache.xbean.spring.generator.NamespaceMapping;
047import org.apache.xbean.spring.generator.QdoxMappingLoader;
048import org.apache.xbean.spring.generator.WikiDocumentationGenerator;
049import org.apache.xbean.spring.generator.XmlMetadataGenerator;
050import org.apache.xbean.spring.generator.XsdGenerator;
051
052/**
053 * @author <a href="gnodet@apache.org">Guillaume Nodet</a>
054 * @version $Id: GenerateApplicationXmlMojo.java 314956 2005-10-12 16:27:15Z brett $
055 * @goal mapping
056 * @description Creates xbean mapping file
057 * @phase generate-sources
058 * @requiresDependencyResolution compile
059 */
060public class XBeanMojo extends AbstractMojo implements LogFacade {
061
062    /**
063     * @parameter expression="${project}"
064     * @required
065     */
066    private MavenProject project;
067
068    /**
069     * Maven ProjectHelper
070     *
071     * @component
072     */
073    protected MavenProjectHelper projectHelper;
074
075    /**
076     * @parameter
077     * @required
078     */
079    private String namespace;
080
081    /**
082     * @parameter expression="${basedir}/src/main/java"
083     * @required
084     */
085    private File srcDir;
086
087    /**
088     * @parameter
089     */
090    private String excludedClasses;
091
092    /**
093     * @parameter expression="${basedir}/target/xbean/"
094     * @required
095     */
096    private File outputDir;
097
098    /**
099     * @parameter
100     */
101    private File schema;
102
103    /**
104     * @parameter expression="org.apache.xbean.spring.context.impl"
105     */
106    private String propertyEditorPaths;
107
108    /**
109     * @parameter schemaAsArtifact
110     */
111    private boolean schemaAsArtifact = true;
112    
113    /**
114     * @parameter 
115     */
116    private boolean generateSpringSchemasFile = true;
117
118    /**
119     * @parameter 
120     */
121    private boolean generateSpringHandlersFile = true;
122    
123    /**
124     * A list of additional GeneratorPlugins that should get used executed
125     * when generating output.
126     *
127     * @parameter
128     */
129    private List<GeneratorPlugin> generatorPlugins = Collections.emptyList();
130
131    public void execute() throws MojoExecutionException, MojoFailureException {
132        getLog().debug( " ======= XBeanMojo settings =======" );
133        getLog().debug( "namespace[" + namespace + "]" );
134        getLog().debug( "srcDir[" + srcDir + "]" );
135        getLog().debug( "schema[" + schema + "]" );
136        getLog().debug( "excludedClasses[" + excludedClasses + "]");
137        getLog().debug( "outputDir[" + outputDir + "]" );
138        getLog().debug( "propertyEditorPaths[" + propertyEditorPaths + "]" );
139        getLog().debug( "schemaAsArtifact[" + schemaAsArtifact + "]");
140        getLog().debug( "generateSpringSchemasFile[" + generateSpringSchemasFile + "]");
141        getLog().debug( "generateSpringHandlersFile[" + generateSpringHandlersFile + "]");
142        
143        if (schema == null) {
144            schema = new File(outputDir, project.getArtifactId() + ".xsd");
145        }
146
147        if (propertyEditorPaths != null) {
148            List<String> editorSearchPath = new LinkedList<String>(Arrays.asList(PropertyEditorManager.getEditorSearchPath()));
149            for (StringTokenizer paths = new StringTokenizer(propertyEditorPaths, " ,"); paths.hasMoreElements(); ) {
150                //StringTokenizer implements Enumeration<Object>, not Enumeration<String> !!
151                editorSearchPath.add((String) paths.nextElement());
152            }
153            PropertyEditorManager.setEditorSearchPath( editorSearchPath.toArray(new String[editorSearchPath.size()]));
154        }
155
156        ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
157        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
158        try {
159            schema.getParentFile().mkdirs();
160
161            String[] excludedClasses = null;
162            if (this.excludedClasses != null) {
163                excludedClasses = this.excludedClasses.split(" *, *");
164            }
165            Set<Artifact> dependencies = project.getDependencyArtifacts();
166            List<File> sourceJars = new ArrayList<File>();
167            sourceJars.add(srcDir);
168            for (Artifact dependency : dependencies) {
169                if ("sources".equals(dependency.getClassifier())) {
170                    File file = dependency.getFile();
171                    sourceJars.add(file);
172                }
173            }
174            File[] srcJars = sourceJars.toArray(new File[sourceJars.size()]);
175            MappingLoader mappingLoader = new QdoxMappingLoader(namespace, srcJars, excludedClasses);
176            GeneratorPlugin[] plugins = new GeneratorPlugin[]{
177                new XmlMetadataGenerator(outputDir.getAbsolutePath(), schema, generateSpringSchemasFile, generateSpringHandlersFile),
178                new DocumentationGenerator(schema),
179                new XsdGenerator(schema),
180                new WikiDocumentationGenerator(schema),
181            };
182
183            // load the mappings
184            Thread.currentThread().setContextClassLoader(getClassLoader());
185            Set<NamespaceMapping> namespaces = mappingLoader.loadNamespaces();
186            if (namespaces.isEmpty()) {
187                System.out.println("Warning: no namespaces found!");
188            }
189
190            // generate the files
191            for (NamespaceMapping namespaceMapping : namespaces) {
192                for (GeneratorPlugin plugin : plugins) {
193                    plugin.setLog(this);
194                    plugin.generate(namespaceMapping);
195                }
196                for (GeneratorPlugin plugin : generatorPlugins) {
197                    plugin.setLog(this);
198                    plugin.generate(namespaceMapping);
199                }
200            }
201
202            // Attach them as artifacts
203            if (schemaAsArtifact) {
204                projectHelper.attachArtifact(project, "xsd", null, schema);
205                projectHelper.attachArtifact(project, "html", "schema", new File(schema.getAbsolutePath() + ".html"));
206            }
207
208            Resource res = new Resource();
209            res.setDirectory(outputDir.toString());
210            project.addResource(res);
211
212            log("...done.");
213        } catch (Exception e) {
214            throw new BuildException(e);
215        } finally {
216            Thread.currentThread().setContextClassLoader(oldCL);
217        }
218    }
219
220    public void log(String message) {
221        getLog().info(message);
222    }
223
224    public void log(String message, int level) {
225        getLog().info(message);
226    }
227
228    protected URLClassLoader getClassLoader() throws MojoExecutionException {
229        try {
230            Set<URL> urls = new HashSet<URL>();
231
232            URL mainClasses = new File(project.getBuild().getOutputDirectory())
233                    .toURL();
234            getLog().debug("Adding to classpath : " + mainClasses);
235            urls.add(mainClasses);
236
237            URL testClasses = new File(project.getBuild()
238                    .getTestOutputDirectory()).toURL();
239            getLog().debug("Adding to classpath : " + testClasses);
240            urls.add(testClasses);
241
242            Set<Artifact> dependencies = project.getArtifacts();
243            Iterator iter = dependencies.iterator();
244            for (Artifact classPathElement : dependencies) {
245                getLog().debug(
246                        "Adding artifact: " + classPathElement.getFile()
247                                + " to classpath");
248                urls.add(classPathElement.getFile().toURL());
249            }
250            URLClassLoader appClassloader = new URLClassLoader(urls.toArray(new URL[urls.size()]), 
251                    this.getClass().getClassLoader());
252            return appClassloader;
253        } catch (MalformedURLException e) {
254            throw new MojoExecutionException(
255                    "Error during setting up classpath", e);
256        }
257    }
258
259}