001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.tools.ws.wscompile;
038:
039: import com.sun.codemodel.JCodeModel;
040: import com.sun.tools.ws.resources.ConfigurationMessages;
041: import com.sun.tools.ws.resources.WscompileMessages;
042: import com.sun.tools.ws.util.ForkEntityResolver;
043: import com.sun.tools.ws.wsdl.document.jaxws.JAXWSBindingsConstants;
044: import com.sun.tools.ws.wsdl.document.schema.SchemaConstants;
045: import com.sun.tools.xjc.api.SchemaCompiler;
046: import com.sun.tools.xjc.api.SpecVersion;
047: import com.sun.tools.xjc.api.XJC;
048: import com.sun.tools.xjc.reader.Util;
049: import com.sun.xml.ws.api.streaming.XMLStreamReaderFactory;
050: import com.sun.xml.ws.streaming.XMLStreamReaderUtil;
051: import com.sun.xml.ws.util.JAXWSUtils;
052: import com.sun.xml.ws.util.xml.XmlUtil;
053: import org.w3c.dom.Element;
054: import org.xml.sax.EntityResolver;
055: import org.xml.sax.InputSource;
056: import org.xml.sax.helpers.LocatorImpl;
057:
058: import javax.xml.namespace.QName;
059: import javax.xml.stream.XMLStreamReader;
060: import java.io.File;
061: import java.io.IOException;
062: import java.net.MalformedURLException;
063: import java.net.URL;
064: import java.util.ArrayList;
065: import java.util.List;
066:
067: /**
068: * @author Vivek Pandey
069: */
070: public class WsimportOptions extends Options {
071: /**
072: * -wsdlLocation
073: */
074: public String wsdlLocation;
075:
076: /**
077: * Actually stores {@link com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver}, but the field
078: * type is made to {@link org.xml.sax.EntityResolver} so that XJC can be
079: * used even if resolver.jar is not available in the classpath.
080: */
081: public EntityResolver entityResolver = null;
082:
083: /**
084: * The -p option that should control the default Java package that
085: * will contain the generated code. Null if unspecified.
086: */
087: public String defaultPackage = null;
088:
089: /**
090: * JAXB's {@link SchemaCompiler} to be used for handling the schema portion.
091: * This object is also configured through options.
092: */
093: private SchemaCompiler schemaCompiler = XJC.createSchemaCompiler();
094:
095: public JCodeModel getCodeModel() {
096: if (codeModel == null)
097: codeModel = new JCodeModel();
098: return codeModel;
099: }
100:
101: public SchemaCompiler getSchemaCompiler() {
102: schemaCompiler.setTargetVersion(SpecVersion.parse(target
103: .getVersion()));
104: schemaCompiler.setEntityResolver(entityResolver);
105: return schemaCompiler;
106: }
107:
108: public void setCodeModel(JCodeModel codeModel) {
109: this .codeModel = codeModel;
110: }
111:
112: private JCodeModel codeModel;
113:
114: /** -Xno-addressing-databinding option to disable addressing namespace data binding. This is
115: * experimental switch and will be working as a temporary workaround till
116: * jaxb can provide a better way to selelctively disable compiling of an
117: * schema component.
118: * **/
119: public boolean noAddressingBbinding;
120:
121: @Override
122: public int parseArguments(String[] args, int i)
123: throws BadCommandLineException {
124: int j = super .parseArguments(args, i);
125: if (j > 0)
126: return j; // understood by the super class
127:
128: if (args[i].equals("-b")) {
129: addBindings(requireArgument("-b", args, ++i));
130: return 2;
131: } else if (args[i].equals("-wsdllocation")) {
132: wsdlLocation = requireArgument("-wsdllocation", args, ++i);
133: return 2;
134: } else if (args[i].equals("-p")) {
135: defaultPackage = requireArgument("-p", args, ++i);
136: return 2;
137: } else if (args[i].equals("-catalog")) {
138: String catalog = requireArgument("-catalog", args, ++i);
139: try {
140: if (entityResolver == null) {
141: if (catalog != null && catalog.length() > 0)
142: entityResolver = XmlUtil
143: .createEntityResolver(JAXWSUtils
144: .getFileOrURL(JAXWSUtils
145: .absolutize(Util
146: .escapeSpace(catalog))));
147: } else if (catalog != null && catalog.length() > 0) {
148: EntityResolver er = XmlUtil
149: .createEntityResolver(JAXWSUtils
150: .getFileOrURL(JAXWSUtils
151: .absolutize(Util
152: .escapeSpace(catalog))));
153: entityResolver = new ForkEntityResolver(er,
154: entityResolver);
155: }
156: } catch (IOException e) {
157: throw new BadCommandLineException(WscompileMessages
158: .WSIMPORT_FAILED_TO_PARSE(catalog, e
159: .getMessage()));
160: }
161: return 2;
162: } else if (args[i].startsWith("-httpproxy:")) {
163: String value = args[i].substring(11);
164: if (value.length() == 0) {
165: throw new BadCommandLineException(WscompileMessages
166: .WSCOMPILE_INVALID_OPTION(args[i]));
167: }
168: int index = value.indexOf(':');
169: if (index == -1) {
170: System.setProperty("proxySet", "true");
171: System.setProperty("proxyHost", value);
172: System.setProperty("proxyPort", "8080");
173: } else {
174: System.setProperty("proxySet", "true");
175: System.setProperty("proxyHost", value.substring(0,
176: index));
177: System.setProperty("proxyPort", value
178: .substring(index + 1));
179: }
180: return 1;
181: } else if (args[i].equals("-Xno-addressing-databinding")) {
182: noAddressingBbinding = true;
183: return 1;
184: } else if (args[i].startsWith("-B")) {
185: // JAXB option pass through.
186: String[] subCmd = new String[args.length - i];
187: System.arraycopy(args, i, subCmd, 0, subCmd.length);
188: subCmd[0] = subCmd[0].substring(2); // trim off the first "-B"
189:
190: com.sun.tools.xjc.Options jaxbOptions = schemaCompiler
191: .getOptions();
192: try {
193: int r = jaxbOptions.parseArgument(subCmd, 0);
194: if (r == 0) {
195: //Driver.usage(jaxbOptions,false);
196: throw new BadCommandLineException(WscompileMessages
197: .WSIMPORT_NO_SUCH_JAXB_OPTION(subCmd[0]));
198: }
199: return r;
200: } catch (com.sun.tools.xjc.BadCommandLineException e) {
201: //Driver.usage(jaxbOptions,false);
202: throw new BadCommandLineException(e.getMessage(), e);
203: }
204: }
205:
206: return 0; // what's this option?
207: }
208:
209: public void validate() throws BadCommandLineException {
210: if (wsdls.isEmpty()) {
211: throw new BadCommandLineException(WscompileMessages
212: .WSIMPORT_MISSING_FILE());
213: }
214: if (wsdlLocation == null) {
215: wsdlLocation = wsdls.get(0).getSystemId();
216: }
217: }
218:
219: @Override
220: protected void addFile(String arg) throws BadCommandLineException {
221: addFile(arg, wsdls, "*.wsdl");
222: }
223:
224: private final List<InputSource> wsdls = new ArrayList<InputSource>();
225: private final List<InputSource> schemas = new ArrayList<InputSource>();
226: private final List<InputSource> bindingFiles = new ArrayList<InputSource>();
227: private final List<InputSource> jaxwsCustomBindings = new ArrayList<InputSource>();
228: private final List<InputSource> jaxbCustomBindings = new ArrayList<InputSource>();
229: private final List<Element> handlerConfigs = new ArrayList<Element>();
230:
231: /**
232: * There is supposed to be one handler chain per generated SEI.
233: * TODO: There is possible bug, how to associate a @HandlerChain
234: * with each port on the generated SEI. For now lets preserve the JAXWS 2.0 FCS
235: * behaviour and generate only one @HandlerChain on the SEI
236: */
237: public Element getHandlerChainConfiguration() {
238: if (handlerConfigs.size() > 0)
239: return handlerConfigs.get(0);
240: return null;
241: }
242:
243: public void addHandlerChainConfiguration(Element config) {
244: handlerConfigs.add(config);
245: }
246:
247: public InputSource[] getWSDLs() {
248: return wsdls.toArray(new InputSource[wsdls.size()]);
249: }
250:
251: public InputSource[] getSchemas() {
252: return schemas.toArray(new InputSource[schemas.size()]);
253: }
254:
255: public InputSource[] getWSDLBindings() {
256: return jaxwsCustomBindings
257: .toArray(new InputSource[jaxwsCustomBindings.size()]);
258: }
259:
260: public InputSource[] getSchemaBindings() {
261: return jaxbCustomBindings
262: .toArray(new InputSource[jaxbCustomBindings.size()]);
263: }
264:
265: public void addWSDL(File source) {
266: addWSDL(fileToInputSource(source));
267: }
268:
269: public void addWSDL(InputSource is) {
270: wsdls.add(absolutize(is));
271: }
272:
273: public void addSchema(File source) {
274: addSchema(fileToInputSource(source));
275: }
276:
277: public void addSchema(InputSource is) {
278: schemas.add(is);
279: }
280:
281: private InputSource fileToInputSource(File source) {
282: try {
283: String url = source.toURL().toExternalForm();
284: return new InputSource(Util.escapeSpace(url));
285: } catch (MalformedURLException e) {
286: return new InputSource(source.getPath());
287: }
288: }
289:
290: /**
291: * Recursively scan directories and add all XSD files in it.
292: */
293: public void addGrammarRecursive(File dir) {
294: addRecursive(dir, ".wsdl", wsdls);
295: addRecursive(dir, ".xsd", schemas);
296: }
297:
298: /**
299: * Adds a new input schema.
300: */
301: public void addWSDLBindFile(InputSource is) {
302: jaxwsCustomBindings.add(absolutize(is));
303: }
304:
305: public void addSchemmaBindFile(InputSource is) {
306: jaxbCustomBindings.add(absolutize(is));
307: }
308:
309: private void addRecursive(File dir, String suffix,
310: List<InputSource> result) {
311: File[] files = dir.listFiles();
312: if (files == null)
313: return; // work defensively
314:
315: for (File f : files) {
316: if (f.isDirectory())
317: addRecursive(f, suffix, result);
318: else if (f.getPath().endsWith(suffix))
319: result.add(absolutize(fileToInputSource(f)));
320: }
321: }
322:
323: private InputSource absolutize(InputSource is) {
324: // absolutize all the system IDs in the input,
325: // so that we can map system IDs to DOM trees.
326: try {
327: URL baseURL = new File(".").getCanonicalFile().toURL();
328: is.setSystemId(new URL(baseURL, is.getSystemId())
329: .toExternalForm());
330: } catch (IOException e) {
331: // ignore
332: }
333: return is;
334: }
335:
336: public void addBindings(String name) throws BadCommandLineException {
337: addFile(name, bindingFiles, null);
338: }
339:
340: /**
341: * Parses a token to a file (or a set of files)
342: * and add them as {@link InputSource} to the specified list.
343: *
344: * @param suffix If the given token is a directory name, we do a recusive search
345: * and find all files that have the given suffix.
346: */
347: private void addFile(String name, List<InputSource> target,
348: String suffix) throws BadCommandLineException {
349: Object src;
350: try {
351: src = Util.getFileOrURL(name);
352: } catch (IOException e) {
353: throw new BadCommandLineException(WscompileMessages
354: .WSIMPORT_NOT_A_FILE_NOR_URL(name));
355: }
356: if (src instanceof URL) {
357: target.add(absolutize(new InputSource(Util
358: .escapeSpace(((URL) src).toExternalForm()))));
359: } else {
360: File fsrc = (File) src;
361: if (fsrc.isDirectory()) {
362: addRecursive(fsrc, suffix, target);
363: } else {
364: target.add(absolutize(fileToInputSource(fsrc)));
365: }
366: }
367: }
368:
369: /**
370: * Exposing it as a public method to allow external tools such as NB to read from wsdl model and work on it.
371: * TODO: WSDL model needs to be exposed - basically at tool time we need to use the runtimw wsdl model
372: *
373: * Binding files could be jaxws or jaxb. This method identifies jaxws and jaxb binding files and keeps them separately. jaxb binding files are given separately
374: * to JAXB in {@link com.sun.tools.ws.processor.modeler.wsdl.JAXBModelBuilder}
375: *
376: * @param receiver {@link ErrorReceiver}
377: */
378: public final void parseBindings(ErrorReceiver receiver) {
379: for (InputSource is : bindingFiles) {
380: XMLStreamReader reader = XMLStreamReaderFactory.create(is,
381: true);
382: XMLStreamReaderUtil.nextElementContent(reader);
383: if (reader.getName().equals(
384: JAXWSBindingsConstants.JAXWS_BINDINGS)) {
385: jaxwsCustomBindings.add(is);
386: } else if (reader.getName().equals(
387: JAXWSBindingsConstants.JAXB_BINDINGS)
388: || reader.getName()
389: .equals(
390: new QName(SchemaConstants.NS_XSD,
391: "schema"))) {
392: jaxbCustomBindings.add(is);
393: } else {
394: LocatorImpl locator = new LocatorImpl();
395: locator.setSystemId(reader.getLocation().getSystemId());
396: locator.setPublicId(reader.getLocation().getPublicId());
397: locator.setLineNumber(reader.getLocation()
398: .getLineNumber());
399: locator.setColumnNumber(reader.getLocation()
400: .getColumnNumber());
401: receiver.warning(locator, ConfigurationMessages
402: .CONFIGURATION_NOT_BINDING_FILE(is
403: .getSystemId()));
404: }
405: }
406: }
407:
408: }
|