org.codehaus.mojo.jaxws.WsImportMojo Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2013 Oracle and/or its affiliates. All rights reserved.
*
* Oracle licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2006 Guillaume Nodet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.mojo.jaxws;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Formatter;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Settings;
/**
*
* @author gnodet ([email protected])
* @author dantran ([email protected])
*/
abstract class WsImportMojo
extends AbstractJaxwsMojo
{
private static final String STALE_FILE_PREFIX = ".";
private static final String PATTERN = "[^\\s]+\\.wsdl$";
/**
* The package in which the source files will be generated.
*/
@Parameter
private String packageName;
/**
* Catalog file to resolve external entity references support TR9401,
* XCatalog, and OASIS XML Catalog format.
*/
@Parameter
private File catalog;
/**
* Set HTTP/HTTPS proxy. Format is [user[:password]@]proxyHost[:proxyPort]
.
*/
@Parameter
private String httpproxy;
/**
* Directory containing WSDL files.
*/
@Parameter( defaultValue = "${project.basedir}/src/wsdl" )
private File wsdlDirectory;
/**
* List of files to use for WSDLs. If not specified, all .wsdl
* files in the wsdlDirectory
will be used.
*/
@Parameter
protected List wsdlFiles;
/**
* List of external WSDL URLs to be compiled.
*/
@Parameter
private List> wsdlUrls;
/**
* Directory containing binding files.
*/
@Parameter( defaultValue = "${project.basedir}/src/jaxws" )
protected File bindingDirectory;
/**
* List of files to use for bindings. If not specified, all .xml
* files in the bindingDirectory
will be used.
*/
@Parameter
protected List bindingFiles;
/**
* @WebService.wsdlLocation and @WebServiceClient.wsdlLocation value.
*
*
* Can end with asterisk in which case relative path of the WSDL will
* be appended to the given wsdlLocation
.
*
*
* Example:
*
* ...
* <configuration>
* <wsdlDirectory>src/mywsdls</wsdlDirectory>
* <wsdlFiles>
* <wsdlFile>a.wsdl</wsdlFile>
* <wsdlFile>b/b.wsdl</wsdlFile>
* <wsdlFile>${project.basedir}/src/mywsdls/c.wsdl</wsdlFile>
* </wsdlFiles>
* <wsdlLocation>http://example.com/mywebservices/*</wsdlLocation>
* </configuration>
* ...
*
* wsdlLocation for a.wsdl
will be http://example.com/mywebservices/a.wsdl
* wsdlLocation for b/b.wsdl
will be http://example.com/mywebservices/b/b.wsdl
* wsdlLocation for ${project.basedir}/src/mywsdls/c.wsdl
will be file://absolute/path/to/c.wsdl
*
*
*
* Note: External binding files cannot be used if asterisk notation is in place.
*
*/
@Parameter
private String wsdlLocation;
/**
* Generate code as per the given JAXWS specification version.
* Setting "2.0" will cause JAX-WS to generate artifacts
* that run with JAX-WS 2.0 runtime.
*/
@Parameter
private String target;
/**
* Suppress wsimport output.
*/
@Parameter( defaultValue = "false" )
private boolean quiet;
/**
* Local portion of service name for generated JWS implementation.
* Implies genJWS=true
.
*
* Note: It is a QName string, formatted as: "{" + Namespace URI + "}" + local part
*/
@Parameter
private String implServiceName;
/**
* Local portion of port name for generated JWS implementation.
* Implies genJWS=true
.
*
* Note: It is a QName string, formatted as: "{" + Namespace URI + "}" + local part
*/
@Parameter
private String implPortName;
/**
* Generate stubbed JWS implementation file.
*/
@Parameter( defaultValue = "false" )
private boolean genJWS;
/**
* Turn off compilation after code generation and let generated sources be
* compiled by maven during compilation phase; keep is turned on with this option.
*/
@Parameter( defaultValue = "true" )
private boolean xnocompile;
/**
* Maps headers not bound to the request or response messages to Java method parameters.
*/
@Parameter( defaultValue = "false" )
private boolean xadditionalHeaders;
/**
* Turn on debug message.
*/
@Parameter( defaultValue = "false" )
private boolean xdebug;
/**
* Binding W3C EndpointReferenceType to Java. By default WsImport follows spec and does not bind
* EndpointReferenceType to Java and uses the spec provided {@link javax.xml.ws.wsaddressing.W3CEndpointReference}
*/
@Parameter( defaultValue = "false" )
private boolean xnoAddressingDataBinding;
/**
* Specify the location of authorization file.
*/
@Parameter
protected File xauthFile;
/**
* Disable the SSL Hostname verification while fetching WSDL(s).
*/
@Parameter( defaultValue = "false" )
private boolean xdisableSSLHostnameVerification;
/**
* If set, the generated Service classes will load the WSDL file from a URL generated from the base resource.
*/
@Parameter( defaultValue = "false" )
private boolean xuseBaseResourceAndURLToLoadWSDL;
/**
* Disable Authenticator used by JAX-WS RI, xauthfile
will be ignored if set.
*/
@Parameter( defaultValue = "false" )
private boolean xdisableAuthenticator;
/**
* Specify optional XJC-specific parameters that should simply be passed to xjc
* using -B
option of WsImport command.
*
* Multiple elements can be specified, and each token must be placed in its own list.
*
*/
@Parameter
private List xjcArgs;
/**
* The folder containing flag files used to determine if the output is stale.
*/
@Parameter( defaultValue = "${project.build.directory}/jaxws/stale" )
private File staleFile;
/**
*/
@Parameter( defaultValue = "${settings}", readonly = true, required = true )
private Settings settings;
protected abstract File getImplDestDir();
/**
* Returns the dependencies that should be placed on the classpath for the classloader
* to lookup wsdl files.
*/
protected abstract List getWSDLFileLookupClasspathElements();
@Override
public void executeJaxws()
throws MojoExecutionException
{
try
{
URL[] wsdls = getWSDLFiles();
if ( wsdls.length == 0 && ( wsdlUrls == null || wsdlUrls.isEmpty() ) )
{
getLog().info( "No WSDLs are found to process, Specify at least one of the following parameters: "
+ "wsdlFiles, wsdlDirectory or wsdlUrls." );
return;
}
this.processWsdlViaUrls();
this.processLocalWsdlFiles( wsdls );
}
catch ( MojoExecutionException e )
{
throw e;
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
@Override
protected String getMain()
{
return "com.sun.tools.ws.wscompile.WsimportTool";
}
@Override
protected String getToolName()
{
return "wsimport";
}
@Override
protected boolean isXnocompile()
{
return xnocompile;
}
private void processLocalWsdlFiles( URL[] wsdls )
throws MojoExecutionException, IOException
{
for ( URL u : wsdls )
{
String url = u.toExternalForm();
if ( isOutputStale( url ) )
{
getLog().info( "Processing: " + url );
String relPath = null;
if ( "file".equals( u.getProtocol() ) )
{
relPath = getRelativePath( new File( u.getPath() ) );
}
ArrayList args = getWsImportArgs( relPath );
args.add( "\"" + url + "\"" );
getLog().info( "jaxws:wsimport args: " + args );
exec( args );
touchStaleFile( url );
}
else
{
getLog().info( "Ignoring: " + url );
}
addSourceRoot( getSourceDestDir().getAbsolutePath() );
}
}
/**
* Process external wsdl
*/
private void processWsdlViaUrls()
throws MojoExecutionException, IOException
{
for ( int i = 0; wsdlUrls != null && i < wsdlUrls.size(); i++ )
{
String wsdlUrl = wsdlUrls.get( i ).toString();
if ( isOutputStale( wsdlUrl ) )
{
getLog().info( "Processing: " + wsdlUrl );
ArrayList args = getWsImportArgs( null );
args.add( "\"" + wsdlUrl + "\"" );
getLog().info( "jaxws:wsimport args: " + args );
exec( args );
touchStaleFile( wsdlUrl );
}
addSourceRoot( getSourceDestDir().getAbsolutePath() );
}
}
/**
* Returns wsimport's command arguments as a list
*/
private ArrayList getWsImportArgs( String relativePath )
throws MojoExecutionException
{
ArrayList args = new ArrayList<>();
args.addAll( getCommonArgs() );
if ( httpproxy != null )
{
args.add( "-httpproxy:" + httpproxy );
}
else if ( settings != null )
{
String proxyString = getActiveHttpProxy( settings );
if ( proxyString != null )
{
args.add( "-httpproxy:" + proxyString );
}
String nonProxyHostsString = getActiveNonProxyHosts( settings );
if ( nonProxyHostsString != null )
{
addVmArg( "-Dhttp.nonProxyHosts=" + nonProxyHostsString.replace( "|", "^|" ) );
}
}
if ( packageName != null )
{
args.add( "-p" );
args.add( packageName );
}
if ( catalog != null )
{
args.add( "-catalog" );
args.add( "'" + catalog.getAbsolutePath() + "'" );
}
if ( wsdlLocation != null )
{
if ( relativePath != null )
{
args.add( "-wsdllocation" );
args.add( wsdlLocation.replaceAll( "\\*", relativePath ) );
}
else if ( !wsdlLocation.contains( "*" ) )
{
args.add( "-wsdllocation" );
args.add( wsdlLocation );
}
}
if ( target != null )
{
args.add( "-target" );
args.add( target );
}
if ( quiet )
{
args.add( "-quiet" );
}
if ( ( genJWS || implServiceName != null || implPortName != null ) && isArgSupported( "-generateJWS" ) )
{
args.add( "-generateJWS" );
if ( implServiceName != null && isArgSupported( "-implServiceName" ) )
{
args.add( "-implServiceName" );
args.add( implServiceName );
}
if ( implPortName != null && isArgSupported( "-implPortName" ) )
{
args.add( "-implPortName" );
args.add( implPortName );
}
File implDestDir = getImplDestDir();
if ( !implDestDir.mkdirs() && !implDestDir.exists() )
{
getLog().warn( "Cannot create directory: " + implDestDir.getAbsolutePath() );
}
args.add( "-implDestDir" );
args.add( "'" + implDestDir.getAbsolutePath() + "'" );
if ( !project.getCompileSourceRoots().contains( implDestDir.getAbsolutePath() ) )
{
project.addCompileSourceRoot( implDestDir.getAbsolutePath() );
}
}
if ( xdebug )
{
args.add( "-Xdebug" );
}
if ( xnoAddressingDataBinding )
{
args.add( "-Xno-addressing-databinding" );
}
if ( xadditionalHeaders )
{
args.add( "-XadditionalHeaders" );
}
if ( xauthFile != null )
{
args.add( "-Xauthfile" );
args.add( xauthFile.getAbsolutePath() );
}
if ( xdisableSSLHostnameVerification )
{
args.add( "-XdisableSSLHostnameVerification" );
}
if ( xuseBaseResourceAndURLToLoadWSDL )
{
args.add( "-XuseBaseResourceAndURLToLoadWSDL" );
}
if ( xdisableAuthenticator && isArgSupported( "-XdisableAuthenticator" ) )
{
args.add( "-XdisableAuthenticator" );
}
if ( xjcArgs != null )
{
for ( String xjcArg : xjcArgs )
{
if ( xjcArg.startsWith( "-" ) )
{
args.add( "-B" + xjcArg );
}
else
{
args.add( xjcArg );
}
}
}
// Bindings
File[] bindings = getBindingFiles();
if ( bindings.length > 0 && wsdlLocation != null && wsdlLocation.contains( "*" ) )
{
throw new MojoExecutionException( "External binding file(s) can not be bound to more WSDL files ("
+ wsdlLocation + ")\n" + "Please use either inline binding(s) or multiple execution tags." );
}
for ( File binding : bindings )
{
args.add( "-b" );
args.add( "'" + binding.toURI() + "'" );
}
return args;
}
/**
* Returns a file array of xml files to translate to object models.
*
* @return An array of schema files to be parsed by the schema compiler.
*/
public final File[] getBindingFiles()
{
File[] bindings;
if ( bindingFiles != null )
{
bindings = new File[bindingFiles.size()];
for ( int i = 0; i < bindingFiles.size(); ++i )
{
String schemaName = bindingFiles.get( i );
File file = new File( schemaName );
if ( !file.isAbsolute() )
{
file = new File( bindingDirectory, schemaName );
}
bindings[i] = file;
}
}
else
{
getLog().debug( "The binding Directory is " + bindingDirectory );
bindings = bindingDirectory.listFiles( XML_FILE_FILTER );
if ( bindings == null )
{
bindings = new File[0];
}
}
return bindings;
}
/**
* Returns an array of wsdl files to translate to object models.
*
* @return An array of schema files to be parsed by the schema compiler.
*/
private URL[] getWSDLFiles()
throws MojoExecutionException
{
List files = new ArrayList<>();
List classpathElements = getWSDLFileLookupClasspathElements();
List urlCpath = new ArrayList<>( classpathElements.size() );
for ( String el : classpathElements )
{
try
{
URL u = new File( el ).toURI().toURL();
urlCpath.add( u );
}
catch ( MalformedURLException e )
{
throw new MojoExecutionException( "Error while retrieving list of WSDL files to process", e );
}
}
try ( URLClassLoader loader = new URLClassLoader( urlCpath.toArray( new URL[0] ) ) )
{
if ( wsdlFiles != null )
{
for ( String wsdlFileName : wsdlFiles )
{
File wsdl = new File( wsdlFileName );
URL toAdd = null;
if ( !wsdl.isAbsolute() )
{
wsdl = new File( wsdlDirectory, wsdlFileName );
}
if ( !wsdl.exists() )
{
toAdd = loader.getResource( wsdlFileName );
}
else
{
try
{
toAdd = wsdl.toURI().toURL();
}
catch ( MalformedURLException ex )
{
getLog().error( ex );
}
}
getLog().debug( "The wsdl File is '" + wsdlFileName + "' from '" + toAdd + "'" );
if ( toAdd != null )
{
files.add( toAdd );
}
else
{
throw new MojoExecutionException( "'" + wsdlFileName + "' not found." );
}
}
}
else
{
getLog().debug( "The wsdl Directory is " + wsdlDirectory );
if ( wsdlDirectory.exists() )
{
File[] wsdls = wsdlDirectory.listFiles( WSDL_FILE_FILTER );
for ( File wsdl : wsdls )
{
files.add( wsdl.toURI().toURL() );
}
}
else
{
URI rel = project.getBasedir().toURI().relativize( wsdlDirectory.toURI() );
String dir = rel.getPath();
URL u = loader.getResource( dir );
if ( u == null )
{
dir = "WEB-INF/wsdl/";
u = loader.getResource( dir );
}
if ( u == null )
{
dir = "META-INF/wsdl/";
u = loader.getResource( dir );
}
if ( !( u == null || !"jar".equalsIgnoreCase( u.getProtocol() ) ) )
{
String path = u.getPath();
Pattern p = Pattern.compile( dir.replace( File.separatorChar, '/' ) + PATTERN,
Pattern.CASE_INSENSITIVE );
try ( JarFile jarFile = new JarFile( path.substring( 5, path.indexOf( "!/" ) ) ) )
{
Enumeration jes = jarFile.entries();
while ( jes.hasMoreElements() )
{
JarEntry je = jes.nextElement();
Matcher m = p.matcher( je.getName() );
if ( m.matches() )
{
String s = "jar:" + path.substring( 0, path.indexOf( "!/" ) + 2 ) + je.getName();
files.add( new URL( s ) );
}
}
}
catch ( IOException ex )
{
getLog().error( ex );
}
}
}
}
}
catch ( MojoExecutionException e )
{
throw e;
}
catch ( Exception e )
{
throw new MojoExecutionException( "Error while retrieving list of WSDL files to process", e );
}
return files.toArray( new URL[0] );
}
/**
* A class used to look up .xml documents from a given directory.
*/
private static final FileFilter XML_FILE_FILTER = f -> f.getName().endsWith( ".xml" );
/**
* A class used to look up .wsdl documents from a given directory.
*/
private static final FileFilter WSDL_FILE_FILTER = f -> f.getName().endsWith( ".wsdl" );
private String getRelativePath( File f )
{
if ( wsdlFiles != null )
{
for ( String s : wsdlFiles )
{
String path = f.getPath().replace( File.separatorChar, '/' );
if ( path.endsWith( s ) && path.length() != s.length() )
{
return s;
}
}
}
else if ( wsdlDirectory != null && wsdlDirectory.exists() )
{
File[] wsdls = wsdlDirectory.listFiles( WSDL_FILE_FILTER );
for ( File wsdl : wsdls )
{
String path = f.getPath().replace( File.separatorChar, '/' );
if ( path.endsWith( wsdl.getName() ) )
{
return wsdl.getName();
}
}
}
return null;
}
/**
* Returns true if given WSDL resource or any binding file is newer than the staleFlag
file.
*
* @return True if wsdl files have been modified since the last build.
*/
private boolean isOutputStale( String resource )
{
File[] sourceBindings = getBindingFiles();
File stFile = new File( staleFile, STALE_FILE_PREFIX + getHash( resource ) );
boolean stale = !stFile.exists();
if ( !stale )
{
getLog().debug( "Stale flag file exists, comparing to wsdls and bindings." );
long staleMod = stFile.lastModified();
try
{
// resource can be URL
URL sourceWsdl = new URL( resource );
if ( sourceWsdl.openConnection().getLastModified() > staleMod )
{
getLog().debug( resource + " is newer than the stale flag file." );
stale = true;
}
}
catch ( MalformedURLException mue )
{
// or a file
File sourceWsdl = new File( resource );
if ( sourceWsdl.lastModified() > staleMod )
{
getLog().debug( resource + " is newer than the stale flag file." );
stale = true;
}
}
catch ( IOException ioe )
{
// possible error while opening connection
getLog().error( ioe );
}
for ( File sourceBinding : sourceBindings )
{
if ( sourceBinding.lastModified() > staleMod )
{
getLog().debug( sourceBinding.getName() + " is newer than the stale flag file." );
stale = true;
}
}
}
return stale;
}
private void touchStaleFile( String resource )
throws IOException
{
File stFile = new File( staleFile, STALE_FILE_PREFIX + getHash( resource ) );
if ( !stFile.exists() )
{
File staleDir = stFile.getParentFile();
if ( !staleDir.mkdirs() && !staleDir.exists() )
{
getLog().warn( "Cannot create directory: " + staleDir.getAbsolutePath() );
}
if ( !stFile.createNewFile() )
{
getLog().warn( "Cannot create file: " + stFile.getAbsolutePath() );
}
getLog().debug( "Stale flag file created.[" + stFile.getAbsolutePath() + "]" );
}
else
{
if ( !stFile.setLastModified( System.currentTimeMillis() ) )
{
getLog().warn( "Stale file has not been updated!" );
}
}
}
private String getHash( String s )
{
try ( Formatter formatter = new Formatter() )
{
MessageDigest md = MessageDigest.getInstance( "SHA" );
for ( byte b : md.digest( s.getBytes( "UTF-8" ) ) )
{
formatter.format( "%02x", b );
}
return formatter.toString();
}
catch ( UnsupportedEncodingException ex )
{
getLog().debug( ex.getMessage(), ex );
}
catch ( NoSuchAlgorithmException ex )
{
getLog().debug( ex.getMessage(), ex );
}
// fallback to some default
getLog().warn( "Could not compute hash for " + s + ". Using fallback method." );
return s.substring( s.lastIndexOf( '/' ) ).replaceAll( "\\.", "-" );
}
/**
* @return proxy string as [user[:password]@]proxyHost[:proxyPort] or null
*/
static String getActiveHttpProxy( Settings s )
{
String retVal = null;
for ( Proxy p : s.getProxies() )
{
if ( p.isActive() && "http".equals( p.getProtocol() ) )
{
StringBuilder sb = new StringBuilder();
String user = p.getUsername();
String pwd = p.getPassword();
if ( user != null )
{
sb.append( user );
if ( pwd != null )
{
sb.append( ":" );
sb.append( pwd );
}
sb.append( "@" );
}
sb.append( p.getHost() );
sb.append( ":" );
sb.append( p.getPort() );
retVal = sb.toString().trim();
break;
}
}
return retVal;
}
static String getActiveNonProxyHosts( Settings s )
{
String retVal = null;
for ( Proxy p : s.getProxies() )
{
if ( p.isActive() && "http".equals( p.getProtocol() ) )
{
retVal = p.getNonProxyHosts();
break;
}
}
return retVal;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy