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.servicemix.maven.plugin.xfire;
018
019 import java.io.File;
020 import java.net.MalformedURLException;
021 import java.net.URL;
022 import java.net.URLClassLoader;
023 import java.util.ArrayList;
024 import java.util.Collection;
025 import java.util.Iterator;
026 import java.util.List;
027
028 import org.apache.maven.artifact.Artifact;
029 import org.apache.maven.model.Resource;
030 import org.apache.maven.plugin.AbstractMojo;
031 import org.apache.maven.plugin.MojoExecutionException;
032 import org.apache.maven.project.MavenProject;
033 import org.apache.tools.ant.AntClassLoader;
034 import org.apache.tools.ant.BuildEvent;
035 import org.apache.tools.ant.BuildException;
036 import org.apache.tools.ant.BuildListener;
037 import org.apache.tools.ant.Project;
038 import org.codehaus.xfire.gen.WsdlGenTask;
039 import org.codehaus.xfire.spring.XFireConfigLoader;
040
041 /**
042 * WsdlGen mojo.
043 * <p/>
044 * Implemented as a wrapper around the XFire WsdlGen Ant task.
045 *
046 * @author <a href="jerome@coffeebreaks.org">Jerome Lacoste</a>
047 * @version $Id$
048 * @goal wsdlgen
049 * @requiresProject
050 * @requiresDependencyResolution
051 */
052 public class WsdlgenMojo extends AbstractMojo {
053
054 /**
055 * Project.
056 *
057 * @parameter expression="${project}"
058 * @required
059 * @readonly
060 */
061 private MavenProject project;
062
063 /**
064 * xfire service.xml config files
065 * If not specified, the list will contain a single value 'src/main/resources/META-INF/xfire/services.xml'
066 *
067 * @parameter
068 */
069 private List configs;
070
071 /**
072 * The directory will be added as Project's Resource.
073 * @parameter expression="${outputDirectory}" default-value="${project.build.directory}/generated-sources/xfire/wsdlgen"
074 * @required
075 */
076 private File outputDirectory;
077
078 /**
079 * The basedir of the project.
080 *
081 * @parameter expression="${basedir}"
082 * @required
083 * @readonly
084 */
085 private File basedir;
086
087 /*
088 private PrintStream systemErr;
089 private PrintStream systemOut;
090 private final PrintStream mySystemErr = new PrintStream(new WsdlgenMojo.MyErrorStream());
091 private final PrintStream mySystemOut = new PrintStream(new WsdlgenMojo.MyOutputStream());
092
093 public void execute()
094 throws MojoExecutionException
095 {
096
097 systemErr = System.err;
098 systemOut = System.out;
099 System.setErr(mySystemErr);
100 // System.setOut(mySystemOut); // causes java.lang.OutOfMemoryError: Java heap space on my box
101
102 try {
103 exec();
104 } finally {
105 System.setErr( systemErr );
106 // System.setOut( systemOut );
107 }
108 }
109
110 class MyErrorStream extends OutputStream {
111 private StringBuffer buffer = new StringBuffer();
112
113 public void write( final int b ) throws IOException {
114 final char c = (char) b;
115 // shouldn't we handle '\r' as well ??
116 if (c == '\n') {
117 getLog().error( buffer );
118 buffer = new StringBuffer();
119 } else {
120 buffer.append( c );
121 }
122 }
123 }
124
125 class MyOutputStream extends OutputStream {
126 private StringBuffer buffer = new StringBuffer();
127
128 public void write( final int b ) throws IOException {
129 final char c = (char) b;
130 // shouldn't we handle '\r' as well ??
131 if (c == '\n') {
132 getLog().info( buffer );
133 buffer = new StringBuffer();
134 } else {
135 buffer.append( c );
136 }
137 }
138 }
139 */
140
141 public void execute() throws MojoExecutionException {
142
143 if (configs == null) {
144 configs = new ArrayList();
145 }
146
147 if (configs.size() == 0) {
148 configs
149 .add(new File(basedir,
150 "src/main/resources/META-INF/xfire/services.xml")
151 .getPath());
152 }
153
154 if (!outputDirectory.exists() && !outputDirectory.mkdirs()) {
155 getLog()
156 .warn(
157 "the output directory "
158 + outputDirectory
159 + " doesn't exist and couldn't be created. The goal with probably fail.");
160 }
161
162 final Project antProject = new Project();
163
164 antProject.addBuildListener(new WsdlgenMojo.DebugAntBuildListener());
165
166 // add current pom dependencies to WsdlGenTask class loader
167 ClassLoader parent = WsdlGenTask.class.getClassLoader();
168
169 URL[] urls;
170 try {
171 Collection l = project.getArtifacts();
172 List theurls = new ArrayList();
173 theurls.add(new File(project.getBuild().getOutputDirectory())
174 .toURL());
175 for (Iterator iterator = l.iterator(); iterator.hasNext();) {
176 Artifact dep = (Artifact) iterator.next();
177 theurls.add(dep.getFile().toURL());
178 }
179 urls = (URL[]) theurls.toArray(new URL[theurls.size()]);
180
181 getLog().debug("classloader classpath: " + theurls);
182
183 } catch (MalformedURLException e) {
184 throw new IllegalStateException(e);
185 }
186
187 URLClassLoader cl = new URLClassLoader(urls, parent);
188 ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
189 Thread.currentThread().setContextClassLoader(cl);
190
191 // displayClasspath(cl, "using classpath");
192 // load("javax.servlet.ServletException", cl);
193 // load("org.codehaus.xfire.transport.http.XFireServletController", cl);
194
195 final WsdlGenTask task = new WsdlGenTask();
196
197 task.setProject(antProject);
198
199 task.setOutputDirectory(outputDirectory.getAbsolutePath());
200
201 for (Iterator iterator = configs.iterator(); iterator.hasNext();) {
202 String configUrl = (String) iterator.next();
203
204 // required for multi-modules projects
205 if (!new File(configUrl).exists()) {
206 getLog().warn("configUrl not found. Task will perhaps fail");
207 }
208
209 task.setConfigUrl(configUrl);
210
211 getLog().info(
212 "Executing XFire WsdlGen task for configUrl: " + configUrl);
213
214 try {
215 task.execute();
216 } catch (BuildException e) {
217 throw new MojoExecutionException("command execution failed", e);
218 }
219
220 getLog().debug("generated " + task.getGeneratedFile());
221 }
222 Thread.currentThread().setContextClassLoader(oldCl);
223
224 getLog().debug("Adding outputDirectory as Project's resource.");
225 Resource resource = new Resource();
226 resource.setDirectory(outputDirectory.getAbsolutePath());
227 project.addResource(resource);
228 }
229
230 /*
231 void displayClasspath(URLClassLoader cl, String message)
232 {
233 URL[] urls = cl.getURLs();
234 for (int i = 0; i < urls.length; i++) {
235 URL urL = urls[i];
236 getLog().info("URL " + i + ":" + urL);
237 }
238 }
239 */
240 private void displayClasspath(ClassLoader classLoader, String message) {
241 getLog().info("------ " + message + ":" + classLoader);
242 if (classLoader == null) {
243 return;
244 }
245 if (classLoader instanceof URLClassLoader) {
246 URLClassLoader cl = (URLClassLoader) classLoader;
247 URL[] urls = cl.getURLs();
248 for (int i = 0; i < urls.length; i++) {
249 URL urL = urls[i];
250 getLog().info("URL " + i + ":" + urL);
251 }
252 } else if (classLoader instanceof AntClassLoader) {
253 AntClassLoader cl = (AntClassLoader) XFireConfigLoader.class
254 .getClassLoader();
255 String[] urls = cl.getClasspath().split(File.pathSeparator);
256 for (int i = 0; i < urls.length; i++) {
257 String url = urls[i];
258 getLog().info("URL " + i + ":" + url);
259 }
260 } else {
261 // not handled
262 }
263 displayClasspath(classLoader.getParent(), "parent->" + message);
264 }
265
266 void load(String className, ClassLoader cl) {
267 try {
268 Class c = Class.forName(className, true, cl);
269 getLog().debug(c.toString());
270 } catch (Exception e) {
271 displayClasspath(cl, "using classpath");
272 getLog().error(e);
273 }
274 }
275
276 private class DebugAntBuildListener implements BuildListener {
277 public void buildStarted(final BuildEvent buildEvent) {
278 getLog().debug(buildEvent.getMessage());
279 }
280
281 public void buildFinished(final BuildEvent buildEvent) {
282 getLog().debug(buildEvent.getMessage());
283 }
284
285 public void targetStarted(final BuildEvent buildEvent) {
286 getLog().debug(buildEvent.getMessage());
287 }
288
289 public void targetFinished(final BuildEvent buildEvent) {
290 getLog().debug(buildEvent.getMessage());
291 }
292
293 public void taskStarted(final BuildEvent buildEvent) {
294 getLog().debug(buildEvent.getMessage());
295 }
296
297 public void taskFinished(final BuildEvent buildEvent) {
298 getLog().debug(buildEvent.getMessage());
299 }
300
301 public void messageLogged(final BuildEvent buildEvent) {
302 getLog().debug(buildEvent.getMessage());
303 }
304 }
305 }