001: package org.objectweb.celtix.tools.processors.wsdl2;
002:
003: import java.io.File;
004: import java.io.IOException;
005: import java.io.Writer;
006: import java.util.ArrayList;
007: import java.util.Collection;
008: import java.util.HashMap;
009: import java.util.Iterator;
010: import java.util.List;
011: import java.util.Map;
012: import java.util.Properties;
013: import java.util.logging.Level;
014: import java.util.logging.Logger;
015:
016: import javax.wsdl.Binding;
017: import javax.wsdl.Definition;
018: import javax.wsdl.Import;
019: import javax.wsdl.Message;
020:
021: import javax.wsdl.PortType;
022: import javax.wsdl.Service;
023: import javax.wsdl.Types;
024: import javax.wsdl.WSDLException;
025:
026: import javax.wsdl.extensions.schema.Schema;
027: import javax.wsdl.extensions.schema.SchemaImport;
028: import javax.wsdl.factory.WSDLFactory;
029: import javax.wsdl.xml.WSDLReader;
030:
031: import org.w3c.dom.Element;
032: import org.w3c.dom.Node;
033: import org.w3c.dom.NodeList;
034:
035: import org.xml.sax.InputSource;
036:
037: import com.sun.tools.xjc.api.S2JJAXBModel;
038: import com.sun.tools.xjc.api.SchemaCompiler;
039: import com.sun.tools.xjc.api.XJC;
040:
041: import org.apache.velocity.app.Velocity;
042: import org.objectweb.celtix.common.logging.LogUtils;
043: import org.objectweb.celtix.common.util.StringUtils;
044: import org.objectweb.celtix.tools.common.Processor;
045: import org.objectweb.celtix.tools.common.ProcessorEnvironment;
046: import org.objectweb.celtix.tools.common.ToolConstants;
047: import org.objectweb.celtix.tools.common.ToolException;
048: import org.objectweb.celtix.tools.extensions.jaxws.CustomizationParser;
049: import org.objectweb.celtix.tools.generators.AbstractGenerator;
050: import org.objectweb.celtix.tools.processors.wsdl2.internal.ClassCollector;
051: import org.objectweb.celtix.tools.processors.wsdl2.internal.ClassNameAllocatorImpl;
052: import org.objectweb.celtix.tools.processors.wsdl2.validators.WSDL11Validator;
053: import org.objectweb.celtix.tools.utils.FileWriterUtil;
054: import org.objectweb.celtix.tools.utils.JAXBUtils;
055: import org.objectweb.celtix.tools.utils.WSDLExtensionRegister;
056:
057: public class WSDLToProcessor implements Processor,
058: com.sun.tools.xjc.api.ErrorListener {
059: protected static final Logger LOG = LogUtils
060: .getL7dLogger(WSDLToProcessor.class);
061: protected static final String WSDL_FILE_NAME_EXT = ".wsdl";
062:
063: protected Definition wsdlDefinition;
064: protected ProcessorEnvironment env;
065: protected WSDLFactory wsdlFactory;
066: protected WSDLReader wsdlReader;
067: protected S2JJAXBModel rawJaxbModel;
068: protected S2JJAXBModel rawJaxbModelGenCode;
069:
070: protected ClassCollector classColletor;
071: List<Schema> schemaList = new ArrayList<Schema>();
072: private final Map<String, AbstractGenerator> generators = new HashMap<String, AbstractGenerator>();
073: private List<Definition> importedDefinitions = new ArrayList<Definition>();
074: private List<String> schemaTargetNamespaces = new ArrayList<String>();
075:
076: protected Writer getOutputWriter(String newNameExt)
077: throws ToolException {
078: Writer writer = null;
079: String newName = null;
080: String outputDir;
081:
082: if (env.get(ToolConstants.CFG_OUTPUTFILE) != null) {
083: newName = (String) env.get(ToolConstants.CFG_OUTPUTFILE);
084: } else {
085: String oldName = (String) env
086: .get(ToolConstants.CFG_WSDLURL);
087: int position = oldName.lastIndexOf("/");
088: if (position < 0) {
089: position = oldName.lastIndexOf("\\");
090: }
091: if (position >= 0) {
092: oldName = oldName.substring(position + 1, oldName
093: .length());
094: }
095: if (oldName.toLowerCase().indexOf(WSDL_FILE_NAME_EXT) >= 0) {
096: newName = oldName.substring(0, oldName.length() - 5)
097: + newNameExt + WSDL_FILE_NAME_EXT;
098: } else {
099: newName = oldName + newNameExt;
100: }
101: }
102: if (env.get(ToolConstants.CFG_OUTPUTDIR) != null) {
103: outputDir = (String) env.get(ToolConstants.CFG_OUTPUTDIR);
104: if (!("/".equals(outputDir
105: .substring(outputDir.length() - 1)) || "\\"
106: .equals(outputDir.substring(outputDir.length() - 1)))) {
107: outputDir = outputDir + "/";
108: }
109: } else {
110: outputDir = "./";
111: }
112: FileWriterUtil fw = new FileWriterUtil(outputDir);
113: try {
114: writer = fw.getWriter("", newName);
115: } catch (IOException ioe) {
116: org.objectweb.celtix.common.i18n.Message msg = new org.objectweb.celtix.common.i18n.Message(
117: "FAIL_TO_WRITE_FILE", LOG, env
118: .get(ToolConstants.CFG_OUTPUTDIR)
119: + System.getProperty("file.seperator")
120: + newName);
121: throw new ToolException(msg, ioe);
122: }
123: return writer;
124: }
125:
126: protected void parseWSDL(String wsdlURL) throws ToolException {
127: try {
128: wsdlFactory = WSDLFactory.newInstance();
129: wsdlReader = wsdlFactory.newWSDLReader();
130: wsdlReader.setFeature("javax.wsdl.verbose", false);
131: WSDLExtensionRegister register = new WSDLExtensionRegister(
132: wsdlFactory, wsdlReader);
133: register.registerExtenstions();
134: wsdlDefinition = wsdlReader.readWSDL(wsdlURL);
135: parseImports(wsdlDefinition);
136: buildWSDLDefinition();
137: } catch (WSDLException we) {
138: org.objectweb.celtix.common.i18n.Message msg = new org.objectweb.celtix.common.i18n.Message(
139: "FAIL_TO_CREATE_WSDL_DEFINITION", LOG);
140: throw new ToolException(msg, we);
141: }
142:
143: }
144:
145: private void buildWSDLDefinition() {
146: for (Definition def : importedDefinitions) {
147: this .wsdlDefinition.addNamespace(def.getPrefix(def
148: .getTargetNamespace()), def.getTargetNamespace());
149: Object[] services = def.getServices().values().toArray();
150: for (int i = 0; i < services.length; i++) {
151: this .wsdlDefinition.addService((Service) services[i]);
152: }
153:
154: Object[] messages = def.getMessages().values().toArray();
155: for (int i = 0; i < messages.length; i++) {
156: this .wsdlDefinition.addMessage((Message) messages[i]);
157: }
158:
159: Object[] bindings = def.getBindings().values().toArray();
160: for (int i = 0; i < bindings.length; i++) {
161: this .wsdlDefinition.addBinding((Binding) bindings[i]);
162: }
163:
164: Object[] portTypes = def.getPortTypes().values().toArray();
165: for (int i = 0; i < portTypes.length; i++) {
166: this .wsdlDefinition
167: .addPortType((PortType) portTypes[i]);
168: }
169: }
170: }
171:
172: @SuppressWarnings("unchecked")
173: private void parseImports(Definition def) {
174: List<Import> importList = new ArrayList<Import>();
175: Map imports = def.getImports();
176: for (Iterator iter = imports.keySet().iterator(); iter
177: .hasNext();) {
178: String uri = (String) iter.next();
179: importList.addAll((List<Import>) imports.get(uri));
180: }
181: for (Import impt : importList) {
182: parseImports(impt.getDefinition());
183: importedDefinitions.add(impt.getDefinition());
184: }
185: }
186:
187: private String getVelocityLogFile(String logfile) {
188: String logdir = System.getProperty("user.home");
189: if (logdir == null || logdir.length() == 0) {
190: logdir = System.getProperty("user.dir");
191: }
192: return logdir + File.separator + logfile;
193: }
194:
195: private void initVelocity() throws ToolException {
196: try {
197: Properties props = new Properties();
198: String clzName = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
199: props.put("resource.loader", "class");
200: props.put("class.resource.loader.class", clzName);
201: props
202: .put("runtime.log",
203: getVelocityLogFile("velocity.log"));
204:
205: Velocity.init(props);
206: } catch (Exception e) {
207: org.objectweb.celtix.common.i18n.Message msg = new org.objectweb.celtix.common.i18n.Message(
208: "FAIL_TO_INITIALIZE_VELOCITY_ENGINE", LOG);
209: LOG.log(Level.SEVERE, msg.toString());
210: throw new ToolException(msg, e);
211: }
212: }
213:
214: private void extractSchema(Definition def) {
215: Types typesElement = def.getTypes();
216: if (typesElement != null) {
217: Iterator ite = typesElement.getExtensibilityElements()
218: .iterator();
219: while (ite.hasNext()) {
220: Object obj = ite.next();
221: if (obj instanceof Schema) {
222: Schema schema = (Schema) obj;
223: addSchema(schema);
224: }
225: }
226: }
227: }
228:
229: private void initJAXBModel() {
230: schemaTargetNamespaces.clear();
231: extractSchema(wsdlDefinition);
232: for (Definition def : importedDefinitions) {
233: extractSchema(def);
234: }
235:
236: if (schemaList.size() == 0) {
237: if (env.isVerbose()) {
238: System.err
239: .println("No schema provided in the wsdl file");
240: }
241: return;
242: }
243:
244: schemaTargetNamespaces.clear();
245:
246: buildJaxbModel();
247: }
248:
249: @SuppressWarnings("unchecked")
250: private void buildJaxbModel() {
251: SchemaCompiler schemaCompiler = XJC.createSchemaCompiler();
252: ClassNameAllocatorImpl allocator = new ClassNameAllocatorImpl(
253: classColletor);
254:
255: allocator.setPortTypes(wsdlDefinition.getPortTypes().values(),
256: env.mapPackageName(this .wsdlDefinition
257: .getTargetNamespace()));
258: schemaCompiler.setClassNameAllocator(allocator);
259: schemaCompiler.setErrorListener(this );
260:
261: SchemaCompiler schemaCompilerGenCode = schemaCompiler;
262: if (env.isExcludeNamespaceEnabled()) {
263: schemaCompilerGenCode = XJC.createSchemaCompiler();
264: schemaCompilerGenCode.setClassNameAllocator(allocator);
265: schemaCompilerGenCode.setErrorListener(this );
266: }
267: for (Schema schema : schemaList) {
268: boolean skipGenCode = false;
269:
270: Element schemaElement = schema.getElement();
271: String targetNamespace = schemaElement
272: .getAttribute("targetNamespace");
273: if (StringUtils.isEmpty(targetNamespace)) {
274: continue;
275: }
276:
277: if (env.hasExcludeNamespace(targetNamespace)
278: && env.getExcludePackageName(targetNamespace) == null) {
279: skipGenCode = true;
280: }
281: customizeSchema(schemaElement, targetNamespace);
282: String systemid = schema.getDocumentBaseURI();
283: schemaCompiler.parseSchema(systemid, schemaElement);
284: if (env.isExcludeNamespaceEnabled() && !skipGenCode) {
285: schemaCompilerGenCode.parseSchema(systemid,
286: schemaElement);
287: }
288: }
289: Collection<InputSource> jaxbBindingFiles = env
290: .getJaxbBindingFile().values();
291: for (InputSource bindingFile : jaxbBindingFiles) {
292: schemaCompiler.parseSchema(bindingFile);
293: if (env.isExcludeNamespaceEnabled()) {
294: schemaCompilerGenCode.parseSchema(bindingFile);
295: }
296: }
297: rawJaxbModel = schemaCompiler.bind();
298: if (env.isExcludeNamespaceEnabled()) {
299: rawJaxbModelGenCode = schemaCompilerGenCode.bind();
300: } else {
301: rawJaxbModelGenCode = rawJaxbModel;
302: }
303: }
304:
305: private boolean isSchemaParsed(String targetNamespace) {
306: if (!schemaTargetNamespaces.contains(targetNamespace)) {
307: schemaTargetNamespaces.add(targetNamespace);
308: return false;
309: } else {
310: return true;
311: }
312: }
313:
314: private void customizeSchema(Element schema, String targetNamespace) {
315: String userPackage = env.mapPackageName(targetNamespace);
316: if (env.hasExcludeNamespace(targetNamespace)
317: && env.getExcludePackageName(targetNamespace) != null) {
318: // generate excluded namespace types classes with specified package
319: // name
320: userPackage = env.getExcludePackageName(targetNamespace);
321: }
322: if (!isSchemaParsed(targetNamespace)
323: && !StringUtils.isEmpty(userPackage)) {
324: Node jaxbBindings = JAXBUtils.innerJaxbPackageBinding(
325: schema, userPackage);
326: schema.appendChild(jaxbBindings);
327: }
328:
329: int nodeListLen = schema.getElementsByTagNameNS(
330: ToolConstants.SCHEMA_URI, "import").getLength();
331: for (int i = 0; i < nodeListLen; i++) {
332: removeImportElement(schema);
333: }
334: }
335:
336: private void removeImportElement(Element element) {
337: NodeList nodeList = element.getElementsByTagNameNS(
338: ToolConstants.SCHEMA_URI, "import");
339: if (nodeList.getLength() > 0) {
340: Node importNode = nodeList.item(0);
341: Node schemaNode = importNode.getParentNode();
342: schemaNode.removeChild(importNode);
343: }
344: }
345:
346: private boolean isSchemaImported(Schema schema) {
347: return schemaList.contains(schema);
348: }
349:
350: @SuppressWarnings("unchecked")
351: private void addSchema(Schema schema) {
352: Map<String, List> imports = schema.getImports();
353: if (imports != null && imports.size() > 0) {
354: Collection<String> importKeys = imports.keySet();
355: for (String importNamespace : importKeys) {
356: if (!isSchemaParsed(importNamespace + "?file="
357: + schema.getDocumentBaseURI())) {
358: List<SchemaImport> schemaImports = imports
359: .get(importNamespace);
360: for (SchemaImport schemaImport : schemaImports) {
361: Schema tempImport = schemaImport
362: .getReferencedSchema();
363: if (tempImport != null
364: && !isSchemaImported(tempImport)) {
365: addSchema(tempImport);
366: }
367: }
368: }
369: }
370: }
371: if (!isSchemaImported(schema)) {
372: schemaList.add(schema);
373: }
374: }
375:
376: private void parseCustomization() {
377: CustomizationParser customizationParser = CustomizationParser
378: .getInstance();
379: customizationParser.clean();
380: if (!env.optionSet(ToolConstants.CFG_BINDING)) {
381: return;
382: }
383: customizationParser.parse(env, wsdlDefinition);
384: }
385:
386: protected void init() throws ToolException {
387: parseWSDL((String) env.get(ToolConstants.CFG_WSDLURL));
388: parseCustomization();
389: initVelocity();
390: classColletor = new ClassCollector();
391: env.put(ToolConstants.GENERATED_CLASS_COLLECTOR, classColletor);
392:
393: initJAXBModel();
394:
395: }
396:
397: public S2JJAXBModel getRawJaxbModel() {
398: return this .rawJaxbModel;
399: }
400:
401: public Definition getWSDLDefinition() {
402: return this .wsdlDefinition;
403: }
404:
405: public void addGenerator(String name, AbstractGenerator gen) {
406: generators.put(name, gen);
407: }
408:
409: public void process() throws ToolException {
410: }
411:
412: public void validateWSDL() throws ToolException {
413: if (env.validateWSDL()) {
414: WSDL11Validator validator = new WSDL11Validator(
415: this .wsdlDefinition, this .env);
416: validator.isValid();
417: }
418: }
419:
420: protected void doGeneration() throws ToolException {
421: for (String genName : generators.keySet()) {
422: AbstractGenerator gen = generators.get(genName);
423: gen.generate();
424: }
425: }
426:
427: public void setEnvironment(ProcessorEnvironment penv) {
428: this .env = penv;
429: }
430:
431: public ProcessorEnvironment getEnvironment() {
432: return this .env;
433: }
434:
435: public void error(org.xml.sax.SAXParseException exception) {
436: if (this .env.isVerbose()) {
437: exception.printStackTrace();
438: } else {
439: System.err.println("Parsing schema error: \n"
440: + exception.toString());
441: }
442: }
443:
444: public void fatalError(org.xml.sax.SAXParseException exception) {
445: if (this .env.isVerbose()) {
446: exception.printStackTrace();
447: } else {
448: System.err.println("Parsing schema fatal error: \n"
449: + exception.toString());
450: }
451: }
452:
453: public void info(org.xml.sax.SAXParseException exception) {
454: if (this .env.isVerbose()) {
455: System.err.println("Parsing schema info: "
456: + exception.toString());
457: }
458: }
459:
460: public void warning(org.xml.sax.SAXParseException exception) {
461: if (this .env.isVerbose()) {
462: System.err.println("Parsing schema warning "
463: + exception.toString());
464: }
465: }
466:
467: }
|