/*=============================================================================*
* Copyright 2006 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.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.Axis2Projectizer;
import org.apache.muse.tools.generator.projectizer.OsgiProjectizer;
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.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.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);
}
/**
* 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);
}
/**
* 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.
* @throws Exception
*/
public Wsdl2Java(File wsdlFile, File descriptorFile, boolean overwrite) throws Exception {
Document descriptorDocument = getDescriptorDocument(descriptorFile);
Document[] wsdlDocuments = getWSDLDocuments(wsdlFile, 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));
}
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 {
checkComponents();
_projectizer.projectize(
_synthesizer.synthesize(
_analyzer.analyze(_configuration)
)
);
}
/**
* Sanity-check to make sure that each of the projectizers is non-null. If it is null
* it is set to a default.
*
* Currently:
* <ul>
* <li>Default Analyzer: SimpleAnalyzer</li>
* <li>Default Synthesizer: ServerSynthesizer</li>
* <li>Default Projectizer: Axis2Projectizer</li>
* </ul>
*
* @see SimpleAnalyzer
* @see ServerSynthesizer
* @see Axis2Projectizer
*/
private void checkComponents() {
if (_synthesizer == null) {
_synthesizer = new ServerSynthesizer();
}
if (_projectizer == null) {
_projectizer = new Axis2Projectizer();
}
if (_analyzer == null) {
_analyzer = new SimpleAnalyzer();
}
}
/**
* 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);
checkBaseDescriptorArg(arguments);
boolean overwrite = checkOverwriteArg(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);
app.setAnalyzer(analyzer);
app.setSynthesizer(synthesizer);
app.setProjectizer(projectizer);
} catch (Exception e) {
handleErrorAndExit(e.getMessage(), e);
return;
}
try {
app.run();
} catch (Exception e) {
handleErrorAndExit(_MESSAGES.get("CodeGenFailed"), e);
}
}
/**
* 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.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,
OVERWRITE_FLAG,
ANALYZER_FLAG,
SYNTHESIZER_FLAG,
PROJECTIZER_FLAG,
BASE_DESCRIPTOR_FLAG,
OSGI_FLAG,
PROXY_FLAG,
QUIET_FLAG,
VERBOSE_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,
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 null 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);
}
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) {
Synthesizer synthesizer = null;
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));
}
synthesizer = (Synthesizer) loadClass(arguments.getFlagValue(SYNTHESIZER_FLAG), Synthesizer.class);
}
return synthesizer;
}
/**
* 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) {
Projectizer projectizer = null;
if (arguments.hasFlag(PROXY_FLAG)) {
return new ProxyProjectizer();
}
if(arguments.hasFlag(OSGI_FLAG)) {
return new OsgiProjectizer();
}
String projectizerArg = arguments.getFlagValue(PROJECTIZER_FLAG);
if (arguments.hasFlag(PROJECTIZER_FLAG)) {
if (projectizerArg == null) {
Object[] filler = { PROJECTIZER_FLAG };
handleErrorAndExit(_MESSAGES.get("NullProjectizer", filler));
}
projectizer = (Projectizer) loadClass(arguments.getFlagValue(PROJECTIZER_FLAG), Projectizer.class);
}
return projectizer;
}
/**
* 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;
try {
result = Class.forName(className).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(result.getClass())) {
Object[] filler = new Object[] {
className,
targetInterface.getName()
};
handleErrorAndExit(_MESSAGES.get("DoesNotImplement",filler));
}
return result;
}
}