/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*
*/
package org.apache.muse.tools.generator;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.muse.tools.generator.analyzer.Analyzer;
import org.apache.muse.tools.generator.analyzer.SimpleAnalyzer;
import org.apache.muse.tools.generator.projectizer.J2EEAxis2Projectizer;
import org.apache.muse.tools.generator.projectizer.J2EEMiniProjectizer;
import org.apache.muse.tools.generator.projectizer.OsgiAxis2Projectizer;
import org.apache.muse.tools.generator.projectizer.OsgiMiniProjectizer;
import org.apache.muse.tools.generator.projectizer.Projectizer;
import org.apache.muse.tools.generator.projectizer.ProxyProjectizer;
import org.apache.muse.tools.generator.synthesizer.ProxySynthesizer;
import org.apache.muse.tools.generator.synthesizer.ServerSynthesizer;
import org.apache.muse.tools.generator.synthesizer.Synthesizer;
import org.apache.muse.tools.generator.util.AbstractCommandLineApp;
import org.apache.muse.tools.generator.util.ConfigurationData;
import org.apache.muse.tools.generator.util.MuseRuntimeException;
import org.apache.muse.tools.generator.util.WsdlEnvironment;
import org.apache.muse.util.CommandLine;
import org.apache.muse.util.FileUtils;
import org.apache.muse.util.messages.Messages;
import org.apache.muse.util.messages.MessagesFactory;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.muse.ws.resource.metadata.MetadataDescriptor;
import org.w3c.dom.Document;
/**
*
* Wsdl2Java is a command-line utility that takes a WSDL descriptor and generates
* all the code, project and deployment files you need to actualize a
* managability endpoint.
*
* @author Andrew Eberbach (aeberbac)
*
*/
public class Wsdl2Java extends AbstractCommandLineApp implements Wsdl2JavaConstants {
private static Messages _MESSAGES = MessagesFactory.get(Wsdl2Java.class);
private Synthesizer _synthesizer;
private Projectizer _projectizer;
private Analyzer _analyzer;
private ConfigurationData _configuration;
/**
* Simplest constructor. Takes a WSDL file. Assumes that we should
* use a default Muse descriptor (which can be dumped out) and that
* existing files should NOT be overwritten.
*
* @param wsdlFile The WSDL file to analyze.
* @throws Exception
*/
public Wsdl2Java(File wsdlFile) throws Exception {
this(wsdlFile, null, false, false, null);
}
/**
* Same as the WSDL-only constructor except that here we can specify
* if we want to overwrite existing files. Also uses the built-in
* Muse skeleton descriptor.
*
* @param wsdlFile The WSDL file to analyze.
* @param overwrite Whether or not to overwrite existing files.
* @throws Exception
*/
public Wsdl2Java(File wsdlFile, boolean overwrite) throws Exception {
this(wsdlFile, null, overwrite, false, null);
}
/**
* Specify all three: WSDL file, Muse descriptor and overwrite boolean. The
* Muse descriptor can be null.
*
* @param wsdlFile The WSDL file to analyze.
* @param descriptorFile The Muse descriptor (can be null).
* @param overwrite Whether or not to overwrite existing files.
* @param generateCustomHeaders
* @throws Exception
*/
public Wsdl2Java(File wsdlFile, File descriptorFile, boolean overwrite, boolean generateCustomHeaders, File targetDirectory) throws Exception {
Document descriptorDocument = getDescriptorDocument(descriptorFile);
Document[] wsdlDocuments = null;
MetadataDescriptor[] metadataDescriptors = null;
WsdlEnvironment env = null;
//
// They can't both be null, otherwise what are we generating?
//
if(wsdlFile == null && descriptorFile == null) {
handleErrorAndExit(_MESSAGES.get("NullWSDLBuiltinDescriptor"));
}
//
// If we got a wsdlFile passed in then we are going to generate based off the wsdlFile
// and use data in the deployment descriptor (if any is avaialable) as supplemental.
// If the wsdlFie is null then we are generating from the deployment descriptor and
// we need to load all of the wsdl files it contains.
//
if(wsdlFile != null) {
env = new WsdlEnvironment(wsdlFile.getAbsoluteFile().getParentFile());
wsdlDocuments = new Document[] { getWSDLDocument(wsdlFile.getName(), env) };
metadataDescriptors = new MetadataDescriptor[] { getMetadataDescriptor(wsdlFile.getName(), env, wsdlDocuments[0]) };
} else {
env = new WsdlEnvironment(descriptorFile.getAbsoluteFile().getParentFile());
wsdlDocuments = getWSDLDocuments(descriptorFile, descriptorDocument);
metadataDescriptors = getMetadataDescriptors(descriptorFile, descriptorDocument);
}
_configuration = new ConfigurationData();
_configuration.addParameter(ConfigurationData.WSDL_DOCUMENT_LIST, wsdlDocuments);
_configuration.addParameter(ConfigurationData.DESCRIPTOR_DOCUMENT, descriptorDocument);
_configuration.addParameter(ConfigurationData.OVERWRITE, Boolean.valueOf(overwrite));
_configuration.addParameter(ConfigurationData.GENERATE_CUSTOM_HEADERS, Boolean.valueOf(generateCustomHeaders));
_configuration.addParameter(ConfigurationData.TARGET_DIRECTORY, targetDirectory);
_configuration.addParameter(ConfigurationData.METADATA_DESCRIPTOR_LIST, metadataDescriptors);
}
private Document getDescriptorDocument(File file) {
Document result = null;
if (file == null) {
InputStream inputStream = FileUtils.loadFromContext(Wsdl2Java.class,
MUSE_BASE_DESCRIPTOR);
if (inputStream == null) {
throw new RuntimeException(_MESSAGES.get("FailedLoadingBuiltinDescriptor"));
}
try {
result = XmlUtils.createDocument(inputStream);
} catch (Exception e) {
Object[] filler = getFiller(e);
throw new RuntimeException(_MESSAGES.get("FailedLoadingDescriptor", filler));
}
} else {
try {
result = XmlUtils.createDocument(file);
} catch (Exception e) {
Object[] filler = getFiller(e);
throw new RuntimeException(_MESSAGES.get("FailedLoadingDescriptor", filler));
}
}
return result;
}
/**
* Generate code using the analyser, synthesizer and projectizer. If any one
* of the three are null they are initialized here to default values.
*
* @throws Exception If anything goes wrong during code generation.
*/
public void run() throws Exception {
_projectizer.projectize(
_synthesizer.synthesize(
_analyzer.analyze(_configuration)
)
);
}
/**
* Sets the analyzer to use during code generation.
*
* @param analyzer
*/
public void setAnalyzer(Analyzer analyzer) {
_analyzer = analyzer;
}
/**
* Sets the projectizer to use during code generation.
*
* @param projectizer
*/
public void setProjectizer(Projectizer projectizer) {
_projectizer = projectizer;
}
/**
* Sets the synthesizer to use during code generation.
*
* @param synthesizer
*/
public void setSynthesizer(Synthesizer synthesizer) {
_synthesizer = synthesizer;
}
/**
* Get the current configuration data that is first passed to the analyzer
* phase. The Wsdl2Java constructor creates one of these so that
* normal users of this class don't have to worry about initializing it
* correctly. However, this method allows users to get the configuration
* data and add custom parameters to it before calling <code>run()</code>.
*
* @return Current configuration data
*/
public ConfigurationData getConfigurationData() {
return _configuration;
}
/**
* Venerable main method. We check all command line parameters and
* initialize a Wsdl2Java object before running it. If anything goes
* wrong we abort the program after printing a (hopefully) useful
* error message. This is meant to be called from the command line,
* you can also just instantiate this class with the above constructors and
* then call <code>run()</code>
*
* @param args Command line parameters
*
* @see #run()
*/
public static void main(String[] args) {
CommandLine arguments = parseParameters(args);
createLogger(arguments);
checkHelpArg(arguments);
checkVersionArg(arguments);
checkBaseDescriptorArg(arguments);
boolean overwrite = checkOverwriteArg(arguments);
boolean generateCustomHeaders = checkHeadersFlag(arguments);
File outputDirectory = checkOutputArg(arguments);
File wsdl = checkWsdlArg(arguments);
File descriptorFile = checkDescriptorArg(arguments);
Analyzer analyzer = checkAnalyzerArg(arguments);
Synthesizer synthesizer = checkSynthesizerArg(arguments);
Projectizer projectizer = checkProjectizerArg(arguments);
Wsdl2Java app = null;
try {
app = new Wsdl2Java(wsdl, descriptorFile, overwrite, generateCustomHeaders, outputDirectory);
app.setAnalyzer(analyzer);
app.setSynthesizer(synthesizer);
app.setProjectizer(projectizer);
} catch (Exception e) {
handleErrorAndExit(e.getMessage(), e);
return;
}
try {
app.run();
} catch (Exception e) {
e.printStackTrace();
handleErrorAndExit(_MESSAGES.get("CodeGenFailed"), e);
}
}
/**
* Get the output directory argument if it is present.
*
* @param arguments Command line arguments
* @return The output directory
*/
private static File checkOutputArg(CommandLine arguments) {
String outputArg = arguments.getFlagValue(OUTPUT_FLAG);
if (outputArg == null) {
return null;
}
File outputDirectory = new File(outputArg);
if(outputDirectory.exists() && !outputDirectory.isDirectory()) {
Object[] filler = {outputDirectory.getAbsoluteFile()};
handleErrorAndExit(_MESSAGES.get("NotDirectory", filler));
}
return outputDirectory;
}
/**
* Print the version and exit.
*
* @param arguments Command line arguments
*/
private static void checkVersionArg(CommandLine arguments) {
if(arguments.hasFlag(Wsdl2JavaConstants.VERSION_FLAG)) {
handleMessage(getVersion());
handleExit();
}
}
/**
* Check to see if the flag was given to generate parameters
* for customer headers.
*
* @param arguments Command line arguments
* @return True if the arguments contain the headers flag
*/
private static boolean checkHeadersFlag(CommandLine arguments) {
return arguments.hasFlag(Wsdl2JavaConstants.HEADERS_FLAG);
}
/**
* Wraps the raw command line parameters into a <code>CommandLine</code>
* which will manage finding the flags passed in on the command line.
*
* @param args Raw command line parameters
* @return Wrapped <code>CommandLine</code> of the given parameters.
*/
private static CommandLine parseParameters(String[] args) {
CommandLine arguments = new CommandLine();
arguments.saveFlagValue(ANALYZER_FLAG);
arguments.saveFlagValue(SYNTHESIZER_FLAG);
arguments.saveFlagValue(PROJECTIZER_FLAG);
arguments.saveFlagValue(WSDL_DEFINITION_FLAG);
arguments.saveFlagValue(DESCRIPTOR_FLAG);
arguments.saveFlagValue(BASE_DESCRIPTOR_FLAG);
arguments.saveFlagValue(OUTPUT_FLAG);
arguments.saveFlagValue(J2EE_FLAG);
arguments.saveFlagValue(OSGI_FLAG);
arguments.parse(args);
return arguments;
}
/**
* Check to see if the user provided the help parameters
* and display the appropriate help message (basic or advanced).
*
* @param arguments Command line arguments
*/
private static void checkHelpArg(CommandLine arguments) {
if(arguments.hasFlag(HELP_ADVANCED_FLAG)) {
Object filler[] = new Object[] {
WSDL_DEFINITION_FLAG,
DESCRIPTOR_FLAG,
WSDL_DEFINITION_FLAG,
DESCRIPTOR_FLAG,
J2EE_FLAG,
OSGI_FLAG,
PROXY_FLAG,
AXIS2_TYPE,
MINI_TYPE,
OUTPUT_FLAG,
OVERWRITE_FLAG,
ANALYZER_FLAG,
SYNTHESIZER_FLAG,
PROJECTIZER_FLAG,
BASE_DESCRIPTOR_FLAG,
HEADERS_FLAG,
QUIET_FLAG,
VERBOSE_FLAG,
VERSION_FLAG,
HELP_FLAG,
HELP_ADVANCED_FLAG,
};
handleMessage(_MESSAGES.get("Wsdl2JavaHelpAdvanced",filler, false));
handleExit();
}
if(arguments.hasFlag(HELP_FLAG) || hasNoArguments(arguments)) {
Object filler[] = new Object[] {
WSDL_DEFINITION_FLAG,
WSDL_DEFINITION_FLAG,
J2EE_FLAG,
OSGI_FLAG,
PROXY_FLAG,
AXIS2_TYPE,
MINI_TYPE,
OUTPUT_FLAG,
OVERWRITE_FLAG,
HELP_FLAG,
HELP_ADVANCED_FLAG
};
handleMessage(_MESSAGES.get("Wsdl2JavaHelp",filler, false));
handleExit();
}
}
/**
* Check to see if the user requested to have the skeleton
* descriptor that lives with this class dumped to a given file.
*
* @param arguments Command line arguments
*/
private static void checkBaseDescriptorArg(CommandLine arguments) {
boolean overwrite = checkOverwriteArg(arguments);
String baseDescriptorArg = arguments.getFlagValue(BASE_DESCRIPTOR_FLAG);
if (arguments.hasFlag(BASE_DESCRIPTOR_FLAG)) {
if (baseDescriptorArg == null) {
Object[] filler = { BASE_DESCRIPTOR_FLAG };
handleErrorAndExit(_MESSAGES.get("NoBaseDescriptorOutput", filler, false));
} else {
File target = new File(baseDescriptorArg);
if (!target.exists() || overwrite) {
Object[] filler = new Object[] {
target.getAbsolutePath()
};
handleMessage(_MESSAGES.get("WritingTo", filler, false));
try {
InputStream baseDescriptor = FileUtils.loadFromContext(Wsdl2Java.class, MUSE_BASE_DESCRIPTOR);
FileUtils.copyFile(baseDescriptor, target);
} catch (IOException e) {
handleErrorAndExit(_MESSAGES.get("CopyingBaseDescriptorFailed"), e);
}
handleMessage(_MESSAGES.get("WritingComplete", false));
} else {
Object[] filler = new Object[] {
target.getAbsolutePath(),
OVERWRITE_FLAG
};
handleMessage(_MESSAGES.get("ExistingFound", filler, false));
}
}
handleExit();
}
}
/**
* Checl to see if the arguments have a WSDL flag. Also
* make sure that the WSDL file exists.
*
* @param arguments The command line arguments
* @return A <code>File</code> pointing to the wsdl file or null if no flag was specified
*/
private static File checkWsdlArg(CommandLine arguments) {
String wsdlArg = arguments.getFlagValue(WSDL_DEFINITION_FLAG);
if (wsdlArg == null) {
return null;
}
File wsdlFile = new File(wsdlArg);
if (!wsdlFile.exists()) {
Object[] filler = {wsdlFile.getAbsolutePath()};
handleErrorAndExit(_MESSAGES.get("WsdlNotFound",filler));
}
return wsdlFile;
}
/**
* Check to see if the a descriptor is being passed to
* the code generation. Also make sure that
* the descriptor exists.
*
* @param arguments The command line arguments
* @return A <code>File</code> pointing to the descriptor or null if
* the flag was not specified.
*/
private static File checkDescriptorArg(CommandLine arguments) {
File descriptorFile = null;
String descriptorArg = arguments.getFlagValue(DESCRIPTOR_FLAG);
if (arguments.hasFlag(DESCRIPTOR_FLAG)) {
if (descriptorArg == null) {
Object[] filler = { DESCRIPTOR_FLAG };
handleErrorAndExit(_MESSAGES.get("NullDescriptor",filler));
}
descriptorFile = new File(descriptorArg);
if (!descriptorFile.exists()) {
Object[] filler = { descriptorFile.getAbsolutePath() };
handleErrorAndExit(_MESSAGES.get("DescriptorNotFound", filler));
}
}
return descriptorFile;
}
/**
* Check to see if the user has specified a class to use as the
* Analyzer. This class name must be fully qualified and must
* be on the classpath. Of course, it must implement <code>Analyzer</code>.
*
* @param arguments The command line arguments
* @return An <code>Analzyer</code> or SimpleAnalyzer if the flag was absent
*
* @see Analyzer
*/
private static Analyzer checkAnalyzerArg(CommandLine arguments) {
Analyzer analyzer = null;
String analyzerArg = arguments.getFlagValue(ANALYZER_FLAG);
if (arguments.hasFlag(ANALYZER_FLAG)) {
if (analyzerArg == null) {
Object[] filler = { ANALYZER_FLAG };
handleErrorAndExit(_MESSAGES.get("NullAnalyzer",filler));
}
analyzer = (Analyzer) loadClass(arguments.getFlagValue(ANALYZER_FLAG), Analyzer.class);
} else {
return new SimpleAnalyzer();
}
return analyzer;
}
/**
* Check to see if the user has specified a class to use as the
* Synthesizer. This class name must be fully qualified and must
* be on the classpath. Of course, it must implement <code>Synthesizer</code>.
*
* @param arguments The command line arguments
* @return A <code>Synthesizer</code> or null if the flag was absent
*
* @see Synthesizer
*/
private static Synthesizer checkSynthesizerArg(CommandLine arguments) {
if (arguments.hasFlag(PROXY_FLAG)) {
return new ProxySynthesizer();
}
String generatorArg = arguments.getFlagValue(SYNTHESIZER_FLAG);
if (arguments.hasFlag(SYNTHESIZER_FLAG)) {
if (generatorArg == null) {
Object[] filler = { SYNTHESIZER_FLAG };
handleErrorAndExit(_MESSAGES.get("NullSynthesizer", filler));
}
return (Synthesizer) loadClass(arguments.getFlagValue(SYNTHESIZER_FLAG), Synthesizer.class);
}
return new ServerSynthesizer();
}
/**
* Check to see if the user has specified a class to use as the
* Projectizer. This class name must be fully qualified and must
* be on the classpath. Of course, it must implement <code>Projectizer</code>.
*
* @param arguments The command line arguments
* @return A <code>Projectizer</code> or null if the flag was absent
*
* @see Projectizer
*/
private static Projectizer checkProjectizerArg(CommandLine arguments) {
if (arguments.hasFlag(PROXY_FLAG)) {
return new ProxyProjectizer();
}
if(arguments.hasFlag(J2EE_FLAG)) {
String type = arguments.getFlagValue(J2EE_FLAG);
if(type == null) {
Object[] filler = { HELP_FLAG };
throw new MuseRuntimeException("InvalidArgs",_MESSAGES.get("InvalidArgs", filler));
} else if(type.equals(MINI_TYPE)) {
return new J2EEMiniProjectizer();
} else if(type.equals(AXIS2_TYPE)){
return new J2EEAxis2Projectizer();
} else {
Object[] filler = { HELP_FLAG };
throw new MuseRuntimeException("InvalidArgs",_MESSAGES.get("InvalidArgs", filler));
}
}
if(arguments.hasFlag(OSGI_FLAG)) {
String type = arguments.getFlagValue(OSGI_FLAG);
if(type == null) {
Object[] filler = { HELP_FLAG };
throw new MuseRuntimeException("InvalidArgs",_MESSAGES.get("InvalidArgs", filler));
} else if(type.equals(MINI_TYPE)) {
return new OsgiMiniProjectizer();
} else if(type.equals(AXIS2_TYPE)){
return new OsgiAxis2Projectizer();
} else {
Object[] filler = { HELP_FLAG };
throw new MuseRuntimeException("InvalidArgs",_MESSAGES.get("InvalidArgs", filler));
}
}
String projectizerArg = arguments.getFlagValue(PROJECTIZER_FLAG);
if (arguments.hasFlag(PROJECTIZER_FLAG)) {
if (projectizerArg == null) {
Object[] filler = { PROJECTIZER_FLAG };
handleErrorAndExit(_MESSAGES.get("NullProjectizer", filler));
}
return (Projectizer) loadClass(arguments.getFlagValue(PROJECTIZER_FLAG), Projectizer.class);
}
Object[] filler = { HELP_FLAG };
throw new MuseRuntimeException("InvalidArgs",_MESSAGES.get("InvalidArgs", filler));
}
/**
* Given a fully-qualified class name try to instantiate it and
* make sure it conforms to the given interface.
*
* @param className The class that should be instantiated
* @param targetInterface The interface to which the class must conform
*
* @return An instantiation of the given class
*/
private static Object loadClass(String className, Class targetInterface) {
if (className == null) {
return null;
}
Object result = null;
Class resultClass = null;
try {
resultClass = Class.forName(className);
result = resultClass.newInstance();
} catch (InstantiationException e) {
Object[] filler = new Object[] {
className
};
handleErrorAndExit(_MESSAGES.get("InstantiateFailed",filler),e);
} catch (IllegalAccessException e) {
Object[] filler = new Object[] {
className
};
handleErrorAndExit(_MESSAGES.get("InstantiateFailed",filler),e);
} catch (ClassNotFoundException e) {
Object[] filler = new Object[] {
className
};
handleErrorAndExit(_MESSAGES.get("ClassNotFound",filler),e);
}
if(!targetInterface.isAssignableFrom(resultClass)) {
Object[] filler = new Object[] {
className,
targetInterface.getName()
};
handleErrorAndExit(_MESSAGES.get("DoesNotImplement",filler));
}
return result;
}
}