View Javadoc

1   /*
2    * Copyright 2006 Guillaume Nodet.
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  
17  package org.codehaus.mojo.jaxws;
18  
19  import java.io.File;
20  import java.io.FileFilter;
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.apache.maven.plugin.MojoExecutionException;
27  
28  import com.sun.tools.ws.wscompile.WsimportTool;
29  
30  
31  /**
32   * @svnLink $Revision: 3899 $;$Date: 2009-08-11 12:22:49 +0200 (Di, 11. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/maven/plugins/maven-jaxws-plugin/src/main/java/org/codehaus/mojo/jaxws/WsImportMojo.java $
33   *
34   * @author gnodet <gnodet@apache.org>
35   * @author dantran <dantran@apache.org>
36   * @version $Id: WsImportMojo.java 3899 2009-08-11 10:22:49Z swismer $
37   */
38  abstract class WsImportMojo extends AbstractJaxwsMojo
39  {
40  
41  	/**
42  	 * The package in which the source files will be generated.
43  	 *
44  	 * @parameter
45  	 */
46  	private String packageName;
47  
48  	/**
49  	 * Catalog file to resolve external entity references support TR9401,
50  	 * XCatalog, and OASIS XML Catalog format.
51  	 *
52  	 * @parameter
53  	 */
54  	private File catalog;
55  
56  	/**
57  	 * Set HTTP/HTTPS proxy. Format is [user[:password]@]proxyHost[:proxyPort]
58  	 *
59  	 * @parameter
60  	 */
61  	private String httpproxy;
62  
63  	/**
64  	 * Directory containing wsdl files.
65  	 *
66  	 * @parameter default-value="${basedir}/src/wsdl"
67  	 */
68  	private File wsdlDirectory;
69  
70  	/**
71  	 * List of files to use for wsdls. If not specified, all .wsdl files
72  	 * in the wsdlDirectory will be used.
73  	 *
74  	 * @parameter
75  	 */
76  	protected List wsdlFiles;
77  
78  	/**
79  	 * List of external wsdl urls to be compiled.
80  	 *
81  	 * @parameter
82  	 */
83  	private List wsdlUrls;
84  
85  	/**
86  	 * Directory containing binding files.
87  	 *
88  	 * @parameter default-value="${basedir}/src/jaxws"
89  	 */
90  	protected File bindingDirectory;
91  
92  	/**
93  	 * List of files to use for bindings.If not specified, all .xml files
94  	 * in the bindingDirectory will be used.
95  	 *
96  	 * @parameter
97  	 */
98  	protected List bindingFiles;
99  
100 	/**
101 	 * @WebService.wsdlLocation and
102 	 * @WebServiceClient.wsdlLocation value.
103 	 *
104 	 * @parameter
105 	 */
106 	private String wsdlLocation;
107 
108 	/**
109 	 * Generate code as per the given JAXWS specification version.
110 	 * Setting "2.0" will cause JAX-WS to generate artifacts
111 	 * that run with JAX-WS 2.0 runtime.
112 	 *
113 	 * @parameter
114 	 */
115 	private String target;
116 	
117 	/**
118 	 * Specify where to place generated source files, keep is turned on with this option.
119 	 *
120 	 * @parameter default-value="${project.build.directory}/jaxws/wsimport/java"
121 	 */
122 	protected File sourceDestDir;
123 	
124 	/**
125 	 * Specify optional XJC-specific parameters that should simply be passed to xjc
126 	 * using -B option of WsImport command.
127 	 *
128 	 * @parameter
129 	 */
130 	private List xjcArgs;
131 	
132 	/**
133 	 * The location of the flag file used to determine if the output is stale.
134 	 * @parameter default-value="${project.build.directory}/jaxws/stale/.staleFlag"
135 	 */
136 	private File staleFile;
137 
138 	public void execute()
139 		throws MojoExecutionException
140 	{
141 
142 		if (getWSDLFiles().length > 1 && wsdlLocation != null) {
143 			getLog().warn("If 'wsdlLocation' is set, only one wsdl can be properly processed "
144 				+ "per maven execution. Define multiple maven executions having different ids!");
145 			getLog().warn("Also define different staleFiles "
146 				+ "(see http://blog.darevay.com/2009/03/importing-multiple-wsdls-with-maven/)");
147 		}
148 		
149 		// Need to build a URLClassloader since Maven removed it form the chain
150 		ClassLoader parent = this.getClass().getClassLoader();
151 		String originalSystemClasspath = this.initClassLoader( parent );
152 
153 		try
154 		{
155 
156 			sourceDestDir.mkdirs();
157 			getDestDir().mkdirs();
158 
159 			this.processWsdlViaUrls();
160 
161 			this.processLocalWsdlFiles();
162 
163 			// even thou the generated source already compiled, we still want to
164 			//  add the source path so that IDE can pick it up
165 			project.addCompileSourceRoot( sourceDestDir.getAbsolutePath() );
166 
167 		}
168 		catch ( MojoExecutionException e )
169 		{
170 			throw e;
171 		}
172 		catch ( Exception e )
173 		{
174 			throw new MojoExecutionException( e.getMessage(), e );
175 		}
176 		finally
177 		{
178 			// Set back the old classloader
179 			Thread.currentThread().setContextClassLoader( parent );
180 			System.setProperty( "java.class.path", originalSystemClasspath );
181 		}
182 
183 	}
184 
185 	/**
186 	 *
187 	 * @throws MojoExecutionException
188 	 * @throws IOException
189 	 */
190 	private void processLocalWsdlFiles()
191 		throws MojoExecutionException,  IOException
192 	{
193 
194 		if ( isOutputStale() )
195 		{
196 			File[] wsdls = getWSDLFiles();
197 			for ( int i = 0; i < wsdls.length; i++ )
198 			{
199 				getLog().info( "Processing: " + wsdls[i].getAbsolutePath() );
200 				ArrayList<String> args = getWsImportArgs();
201 				args.add( wsdls[i].getAbsolutePath() );
202 				getLog().info( "jaxws:wsimport args: " + args );
203 				wsImport( args );
204 				
205 			}
206 			touchStaleFile();
207 		}
208 
209 	}
210 
211 	/**
212 	 * process external wsdl
213 	 * @throws MojoExecutionException
214 	 */
215 	private void processWsdlViaUrls()
216 		throws MojoExecutionException
217 	{
218 		//TODO can we do some stale check against a URL?
219 		
220 		for ( int i = 0; wsdlUrls != null && i < wsdlUrls.size(); i++ )
221 		{
222 			String wsdlUrl = wsdlUrls.get( i ).toString();
223 
224 			getLog().info( "Processing: " + wsdlUrl );
225 			ArrayList<String> args = getWsImportArgs();
226 			args.add( wsdlUrl );
227 			getLog().info( "jaxws:wsimport args: " + args );
228 			wsImport( args );
229 		}
230 	}
231 
232 	/**
233 	 * Invoke wsimport compiler
234 	 * @param args
235 	 * @throws MojoExecutionException
236 	 */
237 	private void wsImport( ArrayList<String> args )
238 		throws MojoExecutionException
239 	{
240 		WsimportTool compTool = new WsimportTool( System.out );
241 		if ( !compTool.run( args.toArray( new String[args.size()] ) ) )
242 		{
243 			throw new MojoExecutionException( "Error executing: wsimport " + args );
244 		}
245 	}
246 
247 	/**
248 	 *
249 	 * @return wsimport's command arguments
250 	 * @throws MojoExecutionException
251 	 */
252 	private ArrayList<String> getWsImportArgs()
253 		throws MojoExecutionException
254 	{
255 		ArrayList<String> args = new ArrayList<String>();
256 
257 		args.add( "-s" );
258 		args.add( sourceDestDir.getAbsolutePath() );
259 
260 		args.add( "-d" );
261 		args.add( getDestDir().getAbsolutePath() );
262 
263 		if ( verbose )
264 		{
265 			args.add( "-verbose" );
266 		}
267 
268 		if ( httpproxy != null )
269 		{
270 			args.add( "-httpproxy" );
271 			args.add( httpproxy );
272 		}
273 
274 		if ( packageName != null )
275 		{
276 			args.add( "-p" );
277 			args.add( packageName );
278 		}
279 
280 		if ( catalog != null )
281 		{
282 			args.add( "-catalog" );
283 			args.add( catalog.getAbsolutePath() );
284 		}
285 
286 		if ( wsdlLocation != null )
287 		{
288 			args.add( "-wsdllocation" );
289 			args.add( wsdlLocation );
290 		}
291 
292 		if ( target != null )
293 		{
294 			args.add( "-target" );
295 			args.add( target );
296 		}
297 		
298 		if ( extension )
299 		{
300 			args.add( "-extension" );
301 		}
302 
303 		// xjcOIptions
304 		if (xjcArgs != null)
305 		{
306 			Iterator xjcArgsIter = xjcArgs.iterator();
307 			while ( xjcArgsIter.hasNext() )
308 			{
309 				String xjcArg = (String)xjcArgsIter.next();
310 				args.add( "-B" + xjcArg );
311 			}
312 		}
313 		
314 		// Bindings
315 		File bindings[] = getBindingFiles();
316 		for ( int i = 0; i < bindings.length; i++ )
317 		{
318 			args.add( "-b" );
319 			args.add( bindings[i].getAbsolutePath() );
320 		}
321 
322 		getLog().debug( "jaxws:wsimport args: " + args );
323 
324 		return args;
325 	}
326 
327 	/**
328 	 * Returns a file array of xml files to translate to object models.
329 	 *
330 	 * @return An array of schema files to be parsed by the schema compiler.
331 	 */
332 	public final File[] getBindingFiles()
333 	{
334 		File [] bindings;
335 		
336 		if ( bindingFiles != null )
337 		{
338 			bindings = new File[bindingFiles.size()];
339 			for ( int i = 0 ; i < bindingFiles.size(); ++i )
340 			{
341 				String schemaName = (String) bindingFiles.get( i );
342 				File file = new File( schemaName );
343 				if (!file.isAbsolute()) {
344 					file = new File( bindingDirectory, schemaName );
345 				}
346 				bindings[i] = file;
347 			}
348 		}
349 		else
350 		{
351 			getLog().debug( "The binding Directory is " + bindingDirectory );
352 			bindings =  bindingDirectory.listFiles( new XMLFile() );
353 			if ( bindings == null )
354 			{
355 				bindings = new File[0];
356 			}
357 		}
358 
359 		return bindings;
360 	}
361 
362 	/**
363 	 * Returns a file array of wsdl files to translate to object models.
364 	 *
365 	 * @return An array of schema files to be parsed by the schema compiler.
366 	 */
367 	public final File[] getWSDLFiles()
368 	{
369 		File [] files;
370 
371 		if ( wsdlFiles != null )
372 		{
373 			files = new File[ wsdlFiles.size() ];
374 			for ( int i = 0 ; i < wsdlFiles.size(); ++i )
375 			{
376 				String schemaName = (String) wsdlFiles.get( i );
377 				files[i] = new File( wsdlDirectory, schemaName ) ;
378 			}
379 		}
380 		else
381 		{
382 			getLog().debug( "The wsdl Directory is " + wsdlDirectory );
383 			files = wsdlDirectory.listFiles( new WSDLFile() );
384 			if ( files == null )
385 			{
386 				files = new File[0];
387 			}
388 		}
389 
390 		return files;
391 	}
392 
393 	/**
394 	 * A class used to look up .xml documents from a given directory.
395 	 */
396 	private final class XMLFile
397 		implements FileFilter
398 	{
399 		/**
400 		 * Returns true if the file ends with an xml extension.
401 		 *
402 		 * @param file
403 		 *            The filed being reviewed by the filter.
404 		 * @return true if an xml file.
405 		 */
406 		public boolean accept( final java.io.File file )
407 		{
408 			return file.getName().endsWith( ".xml" );
409 		}
410 	}
411 
412 	/**
413 	 * A class used to look up .wsdl documents from a given directory.
414 	 */
415 	private final class WSDLFile
416 		implements FileFilter
417 	{
418 
419 		/**
420 		 * Returns true if the file ends with a wsdl extension.
421 		 *
422 		 * @param file
423 		 *            The filed being reviewed by the filter.
424 		 * @return true if an wsdl file.
425 		 */
426 		public boolean accept( final java.io.File file )
427 		{
428 			return file.getName().endsWith( ".wsdl" );
429 		}
430 
431 	}
432 
433 	/**
434 	 * Returns true of any one of the files in the WSDL/XJB array are more new than the <code>staleFlag</code> file.
435 	 *
436 	 * @return True if wsdl files have been modified since the last build.
437 	 */
438 	private boolean isOutputStale()
439 	{
440 		File[] sourceWsdls = getWSDLFiles();
441 		File[] sourceBindings = getBindingFiles();
442 		boolean stale = !staleFile.exists();
443 		if ( !stale )
444 		{
445 			getLog().debug( "Stale flag file exists, comparing to wsdls and bindings." );
446 			long staleMod = staleFile.lastModified();
447 
448 			for ( int i = 0; i < sourceWsdls.length; i++ )
449 			{
450 				if ( sourceWsdls[i].lastModified() > staleMod )
451 				{
452 					getLog().debug( sourceWsdls[i].getName() + " is newer than the stale flag file." );
453 					stale = true;
454 				}
455 			}
456 
457 			for ( int i = 0; i < sourceBindings.length; i++ )
458 			{
459 				if ( sourceBindings[i].lastModified() > staleMod )
460 				{
461 					getLog().debug( sourceBindings[i].getName() + " is newer than the stale flag file." );
462 					stale = true;
463 				}
464 			}
465 		}
466 		return stale;
467 	}
468 
469 	private void touchStaleFile()
470 		throws IOException
471 	{
472 		if ( !staleFile.exists() )
473 		{
474 			staleFile.getParentFile().mkdirs();
475 			staleFile.createNewFile();
476 			getLog().debug( "Stale flag file created." );
477 		}
478 		else
479 		{
480 			staleFile.setLastModified( System.currentTimeMillis() );
481 		}
482 	}
483 
484 }