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     */
017    package org.apache.xbean.maven;
018    
019    import java.beans.PropertyEditorManager;
020    import java.io.File;
021    import java.net.MalformedURLException;
022    import java.net.URL;
023    import java.net.URLClassLoader;
024    import java.util.ArrayList;
025    import java.util.Arrays;
026    import java.util.Collections;
027    import java.util.HashSet;
028    import java.util.Iterator;
029    import java.util.LinkedList;
030    import java.util.List;
031    import java.util.Set;
032    import java.util.StringTokenizer;
033    
034    import org.apache.maven.artifact.Artifact;
035    import org.apache.maven.model.Resource;
036    import org.apache.maven.plugin.AbstractMojo;
037    import org.apache.maven.plugin.MojoExecutionException;
038    import org.apache.maven.plugin.MojoFailureException;
039    import org.apache.maven.project.MavenProject;
040    import org.apache.maven.project.MavenProjectHelper;
041    import org.apache.tools.ant.BuildException;
042    import org.apache.xbean.spring.generator.DocumentationGenerator;
043    import org.apache.xbean.spring.generator.GeneratorPlugin;
044    import org.apache.xbean.spring.generator.LogFacade;
045    import org.apache.xbean.spring.generator.MappingLoader;
046    import org.apache.xbean.spring.generator.NamespaceMapping;
047    import org.apache.xbean.spring.generator.QdoxMappingLoader;
048    import org.apache.xbean.spring.generator.WikiDocumentationGenerator;
049    import org.apache.xbean.spring.generator.XmlMetadataGenerator;
050    import 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     */
060    public 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    }