001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.wsdl.codegen;
021:
022: import org.apache.axis2.AxisFault;
023: import org.apache.axis2.description.WSDL11ToAllAxisServicesBuilder;
024: import org.apache.axis2.description.WSDL11ToAxisServiceBuilder;
025: import org.apache.axis2.description.WSDL20ToAxisServiceBuilder;
026: import org.apache.axis2.util.CommandLineOption;
027: import org.apache.axis2.util.CommandLineOptionConstants;
028: import org.apache.axis2.util.CommandLineOptionParser;
029: import org.apache.axis2.util.XMLUtils;
030: import org.apache.axis2.wsdl.codegen.emitter.Emitter;
031: import org.apache.axis2.wsdl.codegen.extension.CodeGenExtension;
032: import org.apache.axis2.wsdl.databinding.TypeMapper;
033: import org.apache.axis2.wsdl.i18n.CodegenMessages;
034: import org.apache.axis2.wsdl.util.ConfigPropertyFileLoader;
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.w3c.dom.Document;
038: import org.xml.sax.SAXException;
039: import org.xml.sax.InputSource;
040:
041: import javax.wsdl.Definition;
042: import javax.wsdl.WSDLException;
043: import javax.wsdl.factory.WSDLFactory;
044: import javax.wsdl.xml.WSDLReader;
045: import javax.wsdl.xml.WSDLLocator;
046: import javax.xml.namespace.QName;
047: import javax.xml.parsers.ParserConfigurationException;
048: import java.io.File;
049: import java.io.IOException;
050: import java.net.MalformedURLException;
051: import java.net.URL;
052: import java.net.URI;
053: import java.net.URISyntaxException;
054: import java.util.ArrayList;
055: import java.util.List;
056: import java.util.Map;
057:
058: public class CodeGenerationEngine {
059:
060: private static final Log log = LogFactory
061: .getLog(CodeGenerationEngine.class);
062:
063: /** Array List for pre-extensions. Extensions that run before the emitter */
064: private List preExtensions = new ArrayList();
065: /** Array List for post-extensions. Extensions that run after the codegens */
066: private List postExtensions = new ArrayList();
067:
068: /** Codegen configuration reference */
069: private CodeGenConfiguration configuration;
070:
071: /**
072: * @param configuration
073: * @throws CodeGenerationException
074: */
075: public CodeGenerationEngine(CodeGenConfiguration configuration)
076: throws CodeGenerationException {
077: this .configuration = configuration;
078: loadExtensions();
079: }
080:
081: /**
082: * @param parser
083: * @throws CodeGenerationException
084: */
085: public CodeGenerationEngine(CommandLineOptionParser parser)
086: throws CodeGenerationException {
087: Map allOptions = parser.getAllOptions();
088: String wsdlUri;
089: try {
090:
091: CommandLineOption option = (CommandLineOption) allOptions
092: .get(CommandLineOptionConstants.WSDL2JavaConstants.WSDL_LOCATION_URI_OPTION);
093: wsdlUri = option.getOptionValue();
094: configuration = new CodeGenConfiguration(allOptions);
095:
096: if (CommandLineOptionConstants.WSDL2JavaConstants.WSDL_VERSION_2
097: .equals(configuration.getWSDLVersion())) {
098: WSDL20ToAxisServiceBuilder builder = new WSDL20ToAxisServiceBuilder(
099: wsdlUri, configuration.getServiceName(),
100: configuration.getPortName());
101: builder.setCodegen(true);
102: configuration.addAxisService(builder.populateService());
103:
104: } else {
105: //It'll be WSDL 1.1
106: Definition wsdl4jDef = readInTheWSDLFile(wsdlUri);
107:
108: // we save the original wsdl definition to write it to the resource folder later
109: // this is required only if it has imports
110: Map imports = wsdl4jDef.getImports();
111: if ((imports != null) && (imports.size() > 0)) {
112: configuration
113: .setWsdlDefinition(readInTheWSDLFile(wsdlUri));
114: } else {
115: configuration.setWsdlDefinition(wsdl4jDef);
116: }
117:
118: // we generate the code for one service and one port if the
119: // user has specified them.
120: // otherwise generate the code for every service.
121: // TODO: find out a permanant solution for this.
122: QName serviceQname = null;
123:
124: if (configuration.getServiceName() != null) {
125: serviceQname = new QName(wsdl4jDef
126: .getTargetNamespace(), configuration
127: .getServiceName());
128: }
129:
130: WSDL11ToAxisServiceBuilder builder = null;
131: // jibx currently does not support multiservice
132: if ((serviceQname != null)
133: || (configuration.getDatabindingType()
134: .equals("jibx"))) {
135: builder = new WSDL11ToAxisServiceBuilder(wsdl4jDef,
136: serviceQname, configuration.getPortName(),
137: configuration.isAllPorts());
138: builder.setCodegen(true);
139: configuration.addAxisService(builder
140: .populateService());
141: } else {
142: builder = new WSDL11ToAllAxisServicesBuilder(
143: wsdl4jDef, configuration.getPortName());
144: builder.setCodegen(true);
145: builder.setAllPorts(configuration.isAllPorts());
146: configuration
147: .setAxisServices(((WSDL11ToAllAxisServicesBuilder) builder)
148: .populateAllServices());
149: }
150: }
151: configuration.setBaseURI(getBaseURI(wsdlUri));
152: } catch (AxisFault axisFault) {
153: throw new CodeGenerationException(CodegenMessages
154: .getMessage("engine.wsdlParsingException"),
155: axisFault);
156: } catch (WSDLException e) {
157: throw new CodeGenerationException(CodegenMessages
158: .getMessage("engine.wsdlParsingException"), e);
159: } catch (Exception e) {
160: throw new CodeGenerationException(CodegenMessages
161: .getMessage("engine.wsdlParsingException"), e);
162: }
163:
164: loadExtensions();
165: }
166:
167: /**
168: * Loads the relevant preExtensions
169: *
170: * @throws CodeGenerationException
171: */
172: private void loadExtensions() throws CodeGenerationException {
173: //load pre extensions
174: String[] extensions = ConfigPropertyFileLoader
175: .getExtensionClassNames();
176: if (extensions != null) {
177: for (int i = 0; i < extensions.length; i++) {
178: //load the Extension class
179: addPreExtension((CodeGenExtension) getObjectFromClassName(extensions[i]
180: .trim()));
181: }
182: }
183:
184: //load post extensions
185: String[] postExtensions = ConfigPropertyFileLoader
186: .getPostExtensionClassNames();
187: if (postExtensions != null) {
188: for (int i = 0; i < postExtensions.length; i++) {
189: //load the Extension class
190: addPostExtension((CodeGenExtension) getObjectFromClassName(postExtensions[i]
191: .trim()));
192: }
193: }
194:
195: }
196:
197: /**
198: * Adds a given extension to the list
199: *
200: * @param ext
201: */
202: private void addPreExtension(CodeGenExtension ext) {
203: if (ext != null) {
204: preExtensions.add(ext);
205: }
206: }
207:
208: /**
209: * Adds a given extension to the list
210: *
211: * @param ext
212: */
213: private void addPostExtension(CodeGenExtension ext) {
214: if (ext != null) {
215: postExtensions.add(ext);
216: }
217: }
218:
219: /**
220: * Generate the code!!
221: *
222: * @throws CodeGenerationException
223: */
224: public void generate() throws CodeGenerationException {
225: try {
226: //engage the pre-extensions
227: for (int i = 0; i < preExtensions.size(); i++) {
228: ((CodeGenExtension) preExtensions.get(i))
229: .engage(configuration);
230: }
231:
232: Emitter emitter;
233:
234: TypeMapper mapper = configuration.getTypeMapper();
235: if (mapper == null) {
236: // this check is redundant here. The default databinding extension should
237: // have already figured this out and thrown an error message. However in case the
238: // users decides to mess with the config it is safe to keep this check in order to throw
239: // a meaningful error message
240: throw new CodeGenerationException(
241: CodegenMessages
242: .getMessage("engine.noProperDatabindingException"));
243: }
244:
245: //Find and invoke the emitter by reflection
246: Map emitterMap = ConfigPropertyFileLoader
247: .getLanguageEmitterMap();
248: String className = (String) emitterMap.get(configuration
249: .getOutputLanguage());
250: if (className != null) {
251: emitter = (Emitter) getObjectFromClassName(className);
252: emitter.setCodeGenConfiguration(configuration);
253: emitter.setMapper(mapper);
254: } else {
255: throw new Exception(CodegenMessages
256: .getMessage("engine.emitterMissing"));
257: }
258:
259: //invoke the necessary methods in the emitter
260: if (configuration.isServerSide()) {
261: emitter.emitSkeleton();
262: // if the users want both client and server, it would be in the
263: // generate all option
264: if (configuration.isGenerateAll()) {
265: emitter.emitStub();
266: }
267: } else {
268: emitter.emitStub();
269: }
270:
271: //engage the post-extensions
272: for (int i = 0; i < postExtensions.size(); i++) {
273: ((CodeGenExtension) postExtensions.get(i))
274: .engage(configuration);
275: }
276:
277: } catch (ClassCastException e) {
278: throw new CodeGenerationException(CodegenMessages
279: .getMessage("engine.wrongEmitter"), e);
280: } catch (Exception e) {
281: throw new CodeGenerationException(e);
282: }
283:
284: }
285:
286: /**
287: * Read the WSDL file
288: *
289: * @param uri
290: * @throws WSDLException
291: */
292: public Definition readInTheWSDLFile(final String uri)
293: throws WSDLException {
294:
295: WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
296: reader.setFeature("javax.wsdl.importDocuments", true);
297:
298: Document doc;
299: try {
300: doc = XMLUtils.newDocument(uri);
301: return reader.readWSDL(getBaseURI(uri), doc);
302: } catch (ParserConfigurationException e) {
303: throw new WSDLException(WSDLException.PARSER_ERROR,
304: "Parser Configuration Error", e);
305: } catch (SAXException e) {
306: throw new WSDLException(WSDLException.PARSER_ERROR,
307: "Parser SAX Error", e);
308:
309: } catch (IOException e) {
310: throw new WSDLException(WSDLException.INVALID_WSDL,
311: "IO Error", e);
312: } catch (URISyntaxException e) {
313: throw new WSDLException(WSDLException.OTHER_ERROR,
314: "URI Syntax Error", e);
315: }
316: }
317:
318: /**
319: * gets a object from the class
320: *
321: * @param className
322: */
323: private Object getObjectFromClassName(String className)
324: throws CodeGenerationException {
325: try {
326: Class extensionClass = getClass().getClassLoader()
327: .loadClass(className);
328: return extensionClass.newInstance();
329: } catch (ClassNotFoundException e) {
330: log.debug(CodegenMessages
331: .getMessage("engine.extensionLoadProblem"), e);
332: return null;
333: } catch (InstantiationException e) {
334: throw new CodeGenerationException(
335: CodegenMessages
336: .getMessage("engine.extensionInstantiationProblem"),
337: e);
338: } catch (IllegalAccessException e) {
339: throw new CodeGenerationException(CodegenMessages
340: .getMessage("engine.illegalExtension"), e);
341: } catch (NoClassDefFoundError e) {
342: log.debug(CodegenMessages
343: .getMessage("engine.extensionLoadProblem"), e);
344: return null;
345: } catch (Exception e) {
346: throw new CodeGenerationException(e);
347: }
348:
349: }
350:
351: /**
352: * calculates the base URI Needs improvement but works fine for now ;)
353: *
354: * @param currentURI
355: */
356: private String getBaseURI(String currentURI)
357: throws URISyntaxException, IOException {
358: File file = new File(currentURI);
359: if (file.exists()) {
360: return file.getCanonicalFile().getParentFile().toURI()
361: .toString();
362: }
363: String uriFragment = currentURI.substring(0, currentURI
364: .lastIndexOf("/"));
365: return uriFragment + (uriFragment.endsWith("/") ? "" : "/");
366: }
367: }
|