/*=============================================================================*
* Copyright 2004 The Apache Software Foundation
*
* 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.apache.ws.resource.tool;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.FileUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.ws.resource.ResourceDefinition;
import org.apache.ws.resource.handler.ResourceHandler;
import org.apache.ws.resource.i18n.Keys;
import org.apache.ws.resource.i18n.MessagesImpl;
import org.apache.ws.resource.impl.ResourceDefinitionImpl;
import org.apache.ws.resource.metadataexchange.v2004_09.porttype.MetadataExchangePortType;
import org.apache.ws.resource.tool.velocity.ImplementsListBuilder;
import org.apache.ws.resource.tool.velocity.ServiceProperties;
import org.apache.ws.util.OperationInfo;
import org.apache.ws.util.WsrfWsdlUtils;
import org.apache.ws.util.XmlBeanNameUtils;
import org.apache.ws.util.i18n.Messages;
import org.apache.ws.util.jsr109.DummyEndpoint;
import org.apache.ws.util.jsr109.DummyEndpointImpl;
import org.apache.ws.util.velocity.CommonsLogLogSystem;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.impl.common.NameUtil;
import org.apache.xmlbeans.impl.common.XmlErrorPrinter;
import org.apache.xmlbeans.impl.tool.SchemaCompiler;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Message;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* Generates Java Web service types and skeletons from a WSRF WSDL. The types are
* generated as XMLBeans.
*
* @author Ian Springer
*/
public class Wsdl2Java
{
private static final Messages MSG = MessagesImpl.getInstance( );
/**
* DOCUMENT_ME
*/
protected static final Options CMD_LINE_OPTIONS = new Options( );
static
{
initCmdLineOptions( );
}
private static final String WEBAPP_NAME = "wsrf";
/** DOCUMENT_ME */
protected static final String VELOCITY_CONTEXT_KEY_GENERATED = "generated";
private File[] m_wsdlFiles;
private Wsdl2JavaOptions m_options;
private Map m_portTypeInfoMap = new HashMap( );
private WSDLReader m_wsdlReader;
private File m_outputDir;
private File[] m_classpath;
private File m_xmlbeansDir;
/**
* Creates a new {@link Wsdl2Java} object.
*
* @param wsdlFiles DOCUMENT_ME
* @param outputDir DOCUMENT_ME
* @param classpathFiles
* @param options DOCUMENT_ME
*/
public Wsdl2Java( File[] wsdlFiles,
File outputDir,
File[] classpathFiles,
Wsdl2JavaOptions options )
throws Exception
{
m_wsdlFiles = wsdlFiles;
if ( m_wsdlFiles.length == 0 )
{
System.out.println( MSG.getMessage( Keys.WARN_EMPTY_WSDLS ) );
}
for ( int i = 0; i < wsdlFiles.length; i++ )
{
File wsdlFile = wsdlFiles[i];
if ( !wsdlFile.getName( ).endsWith( ".wsdl" ) )
{
System.out.println( MSG.getMessage( Keys.ERROR_ONLY_WSDLS,
wsdlFile.getName( ) ) );
System.exit( 0 );
}
}
m_outputDir = outputDir;
m_xmlbeansDir = new File( m_outputDir, ".xmlbeans" );
m_classpath = classpathFiles;
validateClasspath( );
m_options = ( options != null ) ? options : new Wsdl2JavaOptions( );
m_wsdlReader = WSDLFactory.newInstance( ).newWSDLReader( );
initVelocity( );
initPortTypeInfoMap( );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Wsdl2JavaOptions getOptions( )
{
return m_options;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public File getOutputDir( )
{
return m_outputDir;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public File[] getWsdlFiles( )
{
return m_wsdlFiles;
}
/**
* DOCUMENT_ME
*
* @throws Exception DOCUMENT_ME
*/
public void generate( )
throws Exception
{
for ( int i = 0; i < m_wsdlFiles.length; i++ )
{
processWsdlFile( m_wsdlFiles[i] );
}
}
/**
* DOCUMENT_ME
*
* @param args DOCUMENT_ME
* @throws ParseException DOCUMENT_ME
*/
public static void main( String[] args )
throws ParseException
{
CommandLine cmdLine = new PosixParser( ).parse( CMD_LINE_OPTIONS, args, true );
checkForRequiredOption( cmdLine, Opts.OUTPUT_DIR );
checkForRequiredOption( cmdLine, Opts.CLASSPATH );
File outputDir = new File( cmdLine.getOptionValue( Opts.OUTPUT_DIR ) );
File[] classpathFiles = toFileArray( cmdLine.getOptionValue( Opts.CLASSPATH ) );
Wsdl2JavaOptions options = new Wsdl2Java.Wsdl2JavaOptions( );
if ( cmdLine.hasOption( Opts.VERBOSE ) )
{
options.setVerbose( Boolean.valueOf( cmdLine.getOptionValue( Opts.VERBOSE ) ).booleanValue( ) );
}
File[] wsdlFiles = new File[cmdLine.getArgs( ).length];
for ( int i = 0; i < cmdLine.getArgs( ).length; i++ )
{
wsdlFiles[i] = new File( cmdLine.getArgs( )[i] );
}
try
{
System.out.println( MSG.getMessage( Keys.WSDL4J_PASSED_ARGUMENTS,
Integer.toString( wsdlFiles.length ),
outputDir ) );
new Wsdl2Java( wsdlFiles, outputDir, classpathFiles, options ).generate( );
}
catch ( Exception e )
{
e.printStackTrace( );
System.exit( 1 );
}
}
/**
* DOCUMENT_ME
*
* @param targetNamespace DOCUMENT_ME
* @param serviceDir DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
protected File getPackageDir( String targetNamespace,
File serviceDir )
{
String javaPackageName = GenerationUtils.getJavaPackageName( targetNamespace );
File javaDir = new File( serviceDir, "src/java" );
return new File( javaDir,
javaPackageName.replace( '.', '/' ) );
}
/**
* DOCUMENT_ME
*
* @param ptName DOCUMENT_ME
* @return DOCUMENT_ME
*/
protected PortType2JavaInfo getPortType2JavaInfo( QName ptName )
{
return (PortType2JavaInfo) m_portTypeInfoMap.get( ptName );
}
/**
* DOCUMENT_ME
*
* @param resourceDef DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
protected String getValidJavaName( ResourceDefinition resourceDef )
{
String qualifiedClassName =
NameUtil.getClassNameFromQName( new QName( resourceDef.getDefinition( ).getTargetNamespace( ),
resourceDef.getName( ) ) );
return qualifiedClassName.substring( qualifiedClassName.lastIndexOf( "." ) + 1 );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
protected String getWebbappName( )
{
return WEBAPP_NAME;
}
/**
* DOCUMENT_ME
*
* @param ptInfo DOCUMENT_ME
*/
protected void addPortType2JavaInfo( PortType2JavaInfo ptInfo )
{
m_portTypeInfoMap.put( ptInfo.getName( ),
ptInfo );
}
/**
* Builds the {@link ServiceProperties} object which is a javabean used for storing values
* which are passed to the VelocityContext for code generation.
*
* @param resourceDef The definition we are working on.
* @param wsdlFile The {@link File} representation of the wsdl file.
* @param serviceDir The {@link File} representation of the directory we are writing the service to.
* @return The ServiceProperties object.
*/
protected ServiceProperties buildServiceProperties( ResourceDefinition resourceDef,
File wsdlFile,
File serviceDir )
{
ServiceProperties props = new ServiceProperties( resourceDef );
String targetNamespace = resourceDef.getDefinition( ).getTargetNamespace( );
props.setPackageName( GenerationUtils.getJavaPackageName( targetNamespace ) );
String serviceName = resourceDef.getName( );
String javaServiceName = getValidJavaName( resourceDef );
props.setServiceName( javaServiceName );
props.setSrcDir( new File( serviceDir, "src/java" ).getAbsolutePath( ) );
props.setJarDir( new File( m_xmlbeansDir, "lib" ).getAbsolutePath( ) );
props.setJarFileName( getJarFileName( wsdlFile ) );
props.setClassesDir( new File( serviceDir, "classes" ).getAbsolutePath( ) );
props.setEndpointURL( resourceDef.getEndpointURL( ) );
props.setEndpointServiceName( serviceName );
props.setServiceImplements( ImplementsListBuilder.getServiceImplementsList( resourceDef, m_portTypeInfoMap ) );
props.setNamespace( targetNamespace );
props.setPrefix( GenerationUtils.getPrefix( targetNamespace ) );
props.setCustomMappings( GenerationUtils.getOperationInfoMap( resourceDef ) );
props.setHasProperties( resourceDef.hasProperties( ) );
props.setWebappName( getWebbappName( ) );
if ( resourceDef.hasProperties( ) )
{
QName[] propertyNames = resourceDef.getPropertyNames( );
Map propMap = new HashMap( );
for ( int i = 0; i < propertyNames.length; i++ )
{
QName propertyName = propertyNames[i];
String propName = getJavaConstantName( propertyName, propMap );
propMap.put( propName, propertyName );
}
props.setPropertyMap( propMap );
props.setCustomPropertyNames( resourceDef.getCustomPropertyNames( ) );
}
if ( resourceDef.implementsResourceCapability( MetadataExchangePortType.NAME ) )
{
props.setHasMetadata( true );
}
// define the names of the resource props that we initialize for the user...
if ( hasScheduledResourceTerminationPortType( resourceDef ) )
{
props.addImplementedProperty( org.apache.ws.resource.lifetime.v2004_06.porttype.ScheduledResourceTerminationPortType.PROP_QNAME_TERMINATION_TIME );
props.addImplementedProperty( org.apache.ws.resource.lifetime.v2004_06.porttype.ScheduledResourceTerminationPortType.PROP_QNAME_CURRENT_TIME );
props.addImplementedProperty( org.apache.ws.resource.lifetime.v2004_11.porttype.ScheduledResourceTerminationPortType.PROP_QNAME_TERMINATION_TIME );
props.addImplementedProperty( org.apache.ws.resource.lifetime.v2004_11.porttype.ScheduledResourceTerminationPortType.PROP_QNAME_CURRENT_TIME );
}
props.setResourceImplements( ImplementsListBuilder.getResourceImplementsList( resourceDef, m_portTypeInfoMap ) );
QName propertiesDocumentName = resourceDef.getPropertiesDocumentName( );
if ( propertiesDocumentName != null )
{
props.setPropertyDocumentName( XmlBeanNameUtils.getDocumentElementXmlBeanClassName( propertiesDocumentName ) );
}
props.setWsdlName( wsdlFile.getName( ) );
props.setResourcekey( new QName( targetNamespace, "ResourceIdentifier" ) );
Iterator ptNameIter = resourceDef.getImplementedResourceCapabilities( ).keySet( ).iterator( );
while ( ptNameIter.hasNext( ) )
{
QName ptName = (QName) ptNameIter.next( );
PortType2JavaInfo ptInfo = (PortType2JavaInfo) m_portTypeInfoMap.get( ptName );
if ( ptInfo != null )
{
if ( ptInfo.getResourceTemplateFileName( ) != null )
{
props.addResourceIncludeFile( ptInfo.getResourceTemplateFileName( ) );
}
if ( ptInfo.getResourceInitMethodIncludeLocation( ) != null )
{
props.addResourceInitIncludeLocation( ptInfo.getResourceInitMethodIncludeLocation( ) );
}
if ( ptInfo.getAbstractResourceInitMethodIncludeLocation( ) != null )
{
props.addAbstractResourceInitIncludeLocation( ptInfo.getAbstractResourceInitMethodIncludeLocation( ) );
}
if ( ptInfo.getServiceTemplateFileName( ) != null )
{
props.addServiceIncludeFile( ptInfo.getServiceTemplateFileName( ) );
}
}
else
{
System.err.println( "\n\nUnable to find a port type info for the implemented capability: " + ptName
+ "!\n\n" );
}
}
if ( isDraft01Specific( resourceDef ) )
{
props.setNamespaceVersionHolder( org.apache.ws.resource.properties.v2004_06.impl.NamespaceVersionHolderImpl.class );
}
else if ( isDraft05Specific( resourceDef ) )
{
props.setNamespaceVersionHolder( org.apache.ws.resource.properties.v2004_11.impl.NamespaceVersionHolderImpl.class );
}
/*
* These props are for JIRA WSRF-4 and could be added to context obj
* The question is whether the service name here should be the real wsdl
* service name or the service name as we use it...
*/
String portName = resourceDef.getPort( ).getName( );
props.setPortName( portName );
QName portTypeQName = resourceDef.getPortType( ).getQName( );
props.setPortTypeQName( portTypeQName );
QName serviceQname = new QName( targetNamespace, serviceName );
props.setServiceQName( serviceQname );
props.setWsdlServiceName( resourceDef.getWsdlServiceName( ) );
props.setServiceMethodMap( resourceDef.getAllOperations( ) );
return props;
}
/**
*
* @param context
* @param templateLocation
* @param outputFile
* @throws Exception
*/
protected void processTemplate( VelocityContext context,
String templateLocation,
File outputFile )
throws Exception
{
/*
* get the Template object. This is the parsed version of your
* template input file. Note that getTemplate() can throw
* ResourceNotFoundException : if it doesn't find the template
* ParseErrorException : if there is something wrong with the VTL
* Exception : if something else goes wrong (this is generally
* indicative of a serious problem...)
*/
try
{
Template template = Velocity.getTemplate( templateLocation );
/*
* Now have the template engine process your template using the
* data placed into the context. Think of it as a 'merge'
* of the template and the data to produce the output stream.
*/
outputFile.getParentFile().mkdirs();
FileWriter writer = new FileWriter( outputFile );
if ( template != null )
{
template.merge( context, writer );
}
writer.close( );
}
catch ( Exception e )
{
System.err.println( "Error processing template " + templateLocation );
e.printStackTrace( );
}
}
/**
*
* @param resourceDef
* @param wsdlFile
* @param serviceDir
* @throws Exception
*/
protected void processTemplates( ResourceDefinition resourceDef,
File wsdlFile,
File serviceDir )
throws Exception
{
String capitalizedServiceName = getValidJavaName( resourceDef );
try
{
VelocityContext context = new VelocityContext( );
ServiceProperties props = buildServiceProperties( resourceDef, wsdlFile, serviceDir );
context.put( VELOCITY_CONTEXT_KEY_GENERATED, props );
updateVelocityContext( context, resourceDef );
//generate files
File packageDir = getPackageDir( resourceDef.getDefinition( ).getTargetNamespace( ),
serviceDir );
packageDir.mkdirs( );
File outputFile = new File( packageDir, "Abstract" + capitalizedServiceName + "Service.java" );
processTemplate( context, "templates/AbstractService.vm", outputFile );
outputFile = new File( packageDir, capitalizedServiceName + "Service.java" );
if ( !outputFile.exists( ) )
{
processTemplate( context, "templates/Service.vm", outputFile );
}
generateFaultClasses( context, props, packageDir );
outputFile = new File( packageDir, "Abstract" + capitalizedServiceName + "Resource.java" );
processTemplate( context, "templates/AbstractResource.vm", outputFile );
outputFile = new File( packageDir, capitalizedServiceName + "Resource.java" );
if ( !outputFile.exists( ) )
{
processTemplate( context, "templates/Resource.vm", outputFile );
}
outputFile = new File( packageDir, "Abstract" + capitalizedServiceName + "Home.java" );
processTemplate( context, "templates/AbstractHome.vm", outputFile );
outputFile = new File( packageDir, capitalizedServiceName + "Home.java" );
if ( !outputFile.exists( ) )
{
processTemplate( context, "templates/Home.vm", outputFile );
}
if ( resourceDef.hasProperties( ) )
{
outputFile = new File( packageDir, capitalizedServiceName + "PropertyQNames.java" );
processTemplate( context, "templates/PropertyQNames.vm", outputFile );
}
outputFile = new File( packageDir, capitalizedServiceName + "_deploy.wsdd" );
processTemplate( context, "templates/deploy.wsdd.vm", outputFile );
outputFile = new File( packageDir, capitalizedServiceName + "_wsrf-config.xml" );
processTemplate( context, "templates/wsrf-config.xml.vm", outputFile );
outputFile = new File( packageDir, capitalizedServiceName + "CustomOperationsPortType.java" );
processTemplate( context, "templates/CustomOperationsPortType.vm", outputFile );
outputFile = new File( serviceDir, "build.xml" );
processTemplate( context, "templates/build.xml.vm", outputFile );
outputFile = new File( serviceDir, "build.properties" );
if ( !outputFile.exists( ) )
{
processTemplate( context, "templates/build.properties.vm", outputFile );
}
/*
//jsr109 artifacts
outputFile = new File( packageDir, "web.xml" );
processTemplate( context, "templates/jsr109/web.vm", outputFile );
outputFile = new File( packageDir, "webservices.xml" );
processTemplate( context, "templates/jsr109/webservices.vm", outputFile );
outputFile = new File( packageDir, capitalizedServiceName + "_jaxrpc-mapping.xml" );
processTemplate( context, "templates/jsr109/jaxrpc-mapping.vm", outputFile );
*/
}
catch ( Exception e )
{
e.printStackTrace( );
}
}
/**
* Provides a hook for adding to the Velocity Context.
*
* @param context
* @return VelocityContext
*/
protected VelocityContext updateVelocityContext( VelocityContext context,
ResourceDefinition resourceDef )
{
//dummy endpoint vars for jsr109...
context.put( "jsr109EndpointClassName",
DummyEndpointImpl.class.getName( ) );
context.put( "jsr109EndpointInterfaceName",
DummyEndpoint.class.getName( ) );
context.put( "jsr109EndpointDummyJavaOperation",
DummyEndpoint.class.getMethods( )[0].getName( ) );
//handler var for jsr109
context.put( "resourceHandlerClassName",
ResourceHandler.class.getName( ) );
return context;
}
/**
* DOCUMENT_ME
*
* @param classpath DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
static File[] toFileArray( String classpath )
{
List classpathItems = new ArrayList( );
for ( StringTokenizer tokenizer = new StringTokenizer( classpath, File.pathSeparator );
tokenizer.hasMoreTokens( ); )
{
classpathItems.add( new File( tokenizer.nextToken( ) ) );
}
return (File[]) classpathItems.toArray( new File[0] );
}
private static void checkForRequiredOption( CommandLine cmdLine,
String opt )
{
if ( !cmdLine.hasOption( opt ) )
{
System.err.println( MSG.getMessage( Keys.OPT_REQUIRED, opt ) );
System.exit( 1 );
}
}
private static void initCmdLineOptions( )
{
CMD_LINE_OPTIONS.addOption( Opts.OUTPUT_DIR,
LongOpts.OUTPUT_DIR,
true,
MSG.getMessage( Keys.OPT_OUTPUT_DIR_FOR_GEN_SRC ) );
CMD_LINE_OPTIONS.addOption( Opts.CLASSPATH,
LongOpts.CLASSPATH,
true,
MSG.getMessage( Keys.OPT_CLASSPATH_SENT_TO_XMLBEANS ) );
CMD_LINE_OPTIONS.addOption( Opts.VERBOSE,
LongOpts.VERBOSE,
false,
MSG.getMessage( Keys.OPT_ENABLE_VERBOSE ) );
}
/**
* Determines if the passed in QName is for a type which extends
* BaseFault.
*
* @param faultName
* @param type
* @return true if the "type" extends BaseFault.
*/
private boolean isBaseFaultExtension( QName faultName,
boolean type )
throws ClassNotFoundException,
IllegalAccessException,
InvocationTargetException,
NoSuchMethodException
{
String xmlbeanFaultClassName = null;
Class faultClass = null;
URLClassLoader generatedXmlBeanClassloader = getGeneratedXmlBeanClassloader( );
if ( type )
{
xmlbeanFaultClassName = NameUtil.getClassNameFromQName( faultName );
//type to get an instance of the class
faultClass = generatedXmlBeanClassloader.loadClass( xmlbeanFaultClassName );
}
else
{
//attempt to get the generated "Document" class name
xmlbeanFaultClassName =
XmlBeanNameUtils.getDocumentElementXmlBeanFactoryClassName( new QName( faultName.getNamespaceURI( ),
faultName.getLocalPart( ) ) );
//try to load the document class
Class xmlbeanGeneratedClass = generatedXmlBeanClassloader.loadClass( xmlbeanFaultClassName );
//invoke newInstance in the Xmlbean's Factory class
Method method = xmlbeanGeneratedClass.getMethod( "newInstance", null );
Object o = method.invoke( xmlbeanGeneratedClass, null );
//invoke the addNew... method on the object to get its type
xmlbeanGeneratedClass = o.getClass( );
method = xmlbeanGeneratedClass.getMethod( "addNew" + faultName.getLocalPart( ), null );
//get the types's Class
faultClass = method.invoke( o, null ).getClass( );
}
//determine if the class is assignable from any known versions of BaseType
return ( org.oasisOpen.docs.wsrf.x2004.x06.wsrfWSBaseFaults12Draft01.BaseFaultType.class.isAssignableFrom( faultClass )
|| org.oasisOpen.docs.wsrf.x2004.x11.wsrfWSBaseFaults12Draft03.BaseFaultType.class.isAssignableFrom( faultClass ) );
}
private boolean isDraft01Specific( ResourceDefinition resourceDef )
{
return resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_06.porttype.GetMultipleResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_06.porttype.GetResourcePropertyPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_06.porttype.QueryResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_06.porttype.SetResourcePropertiesPortType.NAME );
}
private boolean isDraft05Specific( ResourceDefinition resourceDef )
{
return resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.GetMultipleResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.GetResourcePropertyDocumentPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.DeleteResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.GetResourcePropertyPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.InsertResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.QueryResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.SetResourcePropertiesPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.properties.v2004_11.porttype.UpdateResourcePropertiesPortType.NAME );
}
private URLClassLoader getGeneratedXmlBeanClassloader( )
{
File libDir = new File( m_xmlbeansDir, "lib" );
File[] jarFiles =
libDir.listFiles( new FilenameFilter( )
{
public boolean accept( File dir,
String name )
{
return name.endsWith( ".jar" );
}
} );
URL[] urls = new URL[jarFiles.length];
for ( int i = 0; i < jarFiles.length; i++ )
{
try
{
urls[i] = jarFiles[i].toURL( );
}
catch ( MalformedURLException murle )
{
throw new RuntimeException( "Unable to load XMLBeans-generated jars and convert to URLs. Cause: "
+ murle, murle );
}
}
return new URLClassLoader( urls,
this.getClass( ).getClassLoader( ) );
}
private String getJarFileName( File wsdlFile )
{
String wsdlFileName = wsdlFile.getName( );
String baseName = wsdlFileName.substring( 0,
wsdlFileName.lastIndexOf( "." ) );
return baseName + "-xbeans.jar";
}
private String getJavaConstantName( QName propertyName,
Map propMap )
{
String constName = propertyName.getLocalPart( ).toUpperCase( );
for ( int count = 2; propMap.containsKey( constName ); count++ )
{
constName += count;
}
return constName;
}
private File getTempDir( )
{
String userTempDir = System.getProperty( "java.io.tmpdir" );
File userDir = new File( userTempDir );
userDir.mkdirs( );
File tempClassesDir = new File( userDir, "tmp" + new Date( ).getTime( ) );
tempClassesDir.mkdir( );
return tempClassesDir;
}
private void copyWsdlFile( File wsdlFile,
File serviceDir )
throws IOException
{
File javaDir = new File( serviceDir, "src" );
File wsdlDir = new File( javaDir, "wsdl" );
wsdlDir.mkdirs( );
FileUtils.copyFile( wsdlFile,
new File( wsdlDir,
wsdlFile.getName( ) ) );
}
private void generateFaultClasses( VelocityContext context,
ServiceProperties props,
File packageDir )
throws Exception
{
File outputFile;
Iterator customOperations = props.getCustomMappings( ).values( ).iterator( );
while ( customOperations.hasNext( ) )
{
OperationInfo oparationInfo = (OperationInfo) customOperations.next( );
//need to determine if fault is instanceof BaseFault
Iterator faultIterator = oparationInfo.getFaults( ).values( ).iterator( );
while ( faultIterator.hasNext( ) )
{
Fault fault = (Fault) faultIterator.next( );
Message message = fault.getMessage( );
Map parts = message.getParts( );
if ( parts.size( ) != 1 )
{
throw new Exception( "WSDL fault message should have exactly one part." );
}
Part part = (Part) parts.values( ).iterator( ).next( );
QName faultName = part.getTypeName( );
boolean isType = true;
if ( faultName == null )
{
faultName = part.getElementName( );
isType = false;
}
if ( faultName == null )
{
throw new Exception( "WSDL fault message part should have either an element or a type." );
}
String faultClassName = NameUtil.getClassNameFromQName( faultName );
faultClassName = faultClassName.substring( faultClassName.lastIndexOf( "." ) + 1 );
QName newFaultName = new QName( faultName.getNamespaceURI( ),
faultClassName );
String exceptionFaultName = faultClassName + "Exception";
//ok here's the file we'll generate
outputFile = new File( packageDir, exceptionFaultName + ".java" );
context.put( "faultName", exceptionFaultName );
if ( !outputFile.exists( ) )
{
try
{
if ( isBaseFaultExtension( newFaultName, isType ) )
{
processTemplate( context, "templates/BaseFaultExtension.vm", outputFile );
}
else
{
processTemplate( context, "templates/CustomFault.vm", outputFile );
}
}
catch ( Exception e )
{
throw new Exception( "Unable to generate WSDL fault. Cause: " + e, e );
}
}
}
}
}
private void generateXmlBeans( File wsdlFile )
throws Exception
{
System.out.println( "Generating XMLBeans for WSDL file \"" + wsdlFile + "\"..." );
SchemaCompiler.Parameters scompParams = new SchemaCompiler.Parameters( );
scompParams.setSrcDir( new File( m_xmlbeansDir, "src" ) );
File tempClassesDir = getTempDir( );
scompParams.setClassesDir( tempClassesDir );
scompParams.setWsdlFiles( new File[]
{
wsdlFile
} );
String xmlbeansJarFileName = getJarFileName( wsdlFile );
File[] classpath = removeJarFromClasspathArray( xmlbeansJarFileName, m_classpath );
scompParams.setClasspath( classpath );
scompParams.setDownload( true ); // download remote xsd inputs/imports
scompParams.setDebug( true ); // compile w/ debug symbols
scompParams.setVerbose( m_options.isVerbose( ) );
scompParams.setQuiet( !m_options.isVerbose( ) );
final boolean beNoisy = true;
XmlErrorPrinter xErrorListener = new XmlErrorPrinter( beNoisy, null );
scompParams.setErrorListener( xErrorListener );
File jarDir = new File( m_xmlbeansDir, "lib" );
jarDir.mkdirs( );
scompParams.setOutputJar( new File( jarDir, xmlbeansJarFileName ) );
try
{
if ( !SchemaCompiler.compile( scompParams ) )
{
throw new Exception( xErrorListener.toString( ) );
}
}
finally
{
//delete the temp directory
FileUtils.deleteDirectory( tempClassesDir );
}
}
private boolean hasScheduledResourceTerminationPortType( ResourceDefinition resourceDef )
{
return resourceDef.implementsResourceCapability( org.apache.ws.resource.lifetime.v2004_06.porttype.ScheduledResourceTerminationPortType.NAME )
|| resourceDef.implementsResourceCapability( org.apache.ws.resource.lifetime.v2004_11.porttype.ScheduledResourceTerminationPortType.NAME );
}
private void initPortTypeInfoMap( )
{
// WSRF 2004/06
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_06.GetResourcePropertyPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_06.GetMultipleResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_06.SetResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_06.QueryResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_06.ImmediateResourceTerminationPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_06.ScheduledResourceTerminationPortType2JavaInfo( ) );
// WSRF 2004/11
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.GetResourcePropertyPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.GetMultipleResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.SetResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.QueryResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.ImmediateResourceTerminationPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.ScheduledResourceTerminationPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.InsertResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.UpdateResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.DeleteResourcePropertiesPortType2JavaInfo( ) );
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_11.GetResourcePropertyDocumentPortType2JavaInfo( ) );
// WSMEX 2004/09
addPortType2JavaInfo( new org.apache.ws.resource.tool.porttype.v2004_09.MetadataExchangePortType2JavaInfo( ) );
}
private void initVelocity( )
throws Exception
{
// configure to use Commons Logging for logging
Velocity.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
CommonsLogLogSystem.class.getName( ) );
// don't log warnings for invalid variable references
Velocity.setProperty( RuntimeConstants.RUNTIME_LOG_REFERENCE_LOG_INVALID, "false" );
// don't load any global macro libraries (override default of "VM_global_library.vm")
Velocity.setProperty( RuntimeConstants.VM_LIBRARY, "" );
// configure to use classpath-based resource loader
Velocity.addProperty( RuntimeConstants.RESOURCE_LOADER, "classpath" );
String resourceLoaderBaseKey = "classpath." + RuntimeConstants.RESOURCE_LOADER + ".";
Velocity.setProperty( resourceLoaderBaseKey + "class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
Velocity.setProperty( resourceLoaderBaseKey + "cache", "false" );
Velocity.setProperty( resourceLoaderBaseKey + "modificationCheckInterval", "2" );
Velocity.init( );
}
private void processWsdlFile( File wsdlFile )
throws Exception
{
System.out.println( "Processing WSDL file \"" + wsdlFile + "\"..." );
Definition def = m_wsdlReader.readWSDL( wsdlFile.getPath( ) );
if ( WsrfWsdlUtils.getSchemaElements( def ).length != 0 )
{
generateXmlBeans( wsdlFile );
}
Iterator serviceIter = def.getServices( ).values( ).iterator( );
while ( serviceIter.hasNext( ) )
{
Service service = (Service) serviceIter.next( );
Iterator iterator = service.getPorts( ).values( ).iterator( );
while ( iterator.hasNext( ) )
{
Port port = (Port) iterator.next( );
ResourceDefinition resourceDef =
new ResourceDefinitionImpl( def,
service.getQName( ), port,
wsdlFile.toURL( ) );
File serviceDir = new File( m_outputDir,
resourceDef.getName( ) );
System.out.println( "Processing WSRF WSDL port \"" + resourceDef.getName( ) + "\"..." );
processTemplates( resourceDef, wsdlFile, serviceDir );
copyWsdlFile( wsdlFile, serviceDir );
}
}
}
/**
* This method is used to remove an existing xmlbeans jar of the same name from the
* array of files passed to scomp. This will avoid the potential deletion of the
* previously generated jar file and scomps lack of regenerating classes for existing jars.
* <p/>
* This will ensure scomp generates the jar for the given xbeans jar name.
*
* @param xmlbeansJarFileName
* @param classpath
*/
private File[] removeJarFromClasspathArray( String xmlbeansJarFileName,
File[] classpath )
{
List fileList = new ArrayList( );
for ( int i = 0; i < classpath.length; i++ )
{
File file = classpath[i];
if ( !xmlbeansJarFileName.equals( file.getName( ) ) )
{
fileList.add( file );
}
else
{
System.out.println( "Found existing generated xmlbean jar in the classpath at location: "
+ file.toString( )
+ " ...This will be removed from the classpath sent to Scomp in order "
+ "to regenerate all imports." );
}
}
return (File[]) fileList.toArray( new File[0] );
}
private URL[] toURLs( File[] files )
throws MalformedURLException
{
URL[] urls = new URL[files.length];
for ( int i = 0; i < files.length; i++ )
{
urls[i] = files[i].toURL( );
}
return urls;
}
private void validateClasspath( )
throws MalformedURLException
{
URLClassLoader cpClassLoader = new URLClassLoader( toURLs( m_classpath ),
null );
try
{
cpClassLoader.loadClass( XmlObject.class.getName( ) );
}
catch ( ClassNotFoundException cnfe )
{
throw new IllegalStateException( "Specified classpath must contain the XMLBeans runtime jar (e.g. xbean-v1HEAD-SNAPSHOT-20041129.jar)" );
}
try
{
cpClassLoader.loadClass( org.oasisOpen.docs.wsrf.x2004.x06.wsrfWSResourceProperties12Draft01.GetResourcePropertyDocument.class
.getName( ) );
}
catch ( ClassNotFoundException cnfe )
{
throw new IllegalStateException( "Specified classpath must contain the WSRF generated XMLBeans jar (e.g. wsrf-xbeans-SNAPSHOT.jar)" );
}
}
/**
* DOCUMENT_ME
*
* @author $author$
* @version $Revision: 1.8 $
*/
static interface LongOpts
{
/**
* DOCUMENT_ME
*/
String OUTPUT_DIR = "outputDir";
/**
* DOCUMENT_ME
*/
String VERBOSE = "verbose";
/**
* DOCUMENT_ME
*/
String CLASSPATH = "classpath";
}
/**
* DOCUMENT_ME
*
* @author $author$
* @version $Revision: 1.8 $
*/
static interface Opts
{
/**
* DOCUMENT_ME
*/
String OUTPUT_DIR = "o";
/**
* DOCUMENT_ME
*/
String VERBOSE = "v";
/**
* DOCUMENT_ME
*/
String CLASSPATH = "C";
}
/**
* DOCUMENT_ME
*
* @author $author$
* @version $Revision: 1.8 $
*/
public static class Wsdl2JavaOptions
{
private boolean m_verbose;
/**
* Enable/disable verbose output.
*
* @param verbose option indicating whether or not to enable verbose output
*/
public void setVerbose( boolean verbose )
{
m_verbose = verbose;
}
/**
* Returns true if verbose output is enabled, or false otherwise.
*
* @return true if verbose output is enabled, or false otherwise
*/
public boolean isVerbose( )
{
return m_verbose;
}
}
}