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
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.websvc.wsdl.config;
043:
044: import java.util.*;
045: import org.netbeans.modules.websvc.jaxrpc.PortInformation;
046: import org.netbeans.modules.websvc.jaxrpc.Utilities;
047: import org.xml.sax.Attributes;
048: import org.xml.sax.SAXException;
049: import org.xml.sax.SAXParseException;
050: import org.xml.sax.helpers.DefaultHandler;
051:
052: /**
053: *
054: * @author Peter Williams
055: */
056: public class PortInformationHandler extends DefaultHandler implements
057: PortInformation {
058:
059: private static final String W3C_WSDL_SCHEMA = "http://schemas.xmlsoap.org/wsdl";
060: private static final String W3C_WSDL_SCHEMA_SLASH = "http://schemas.xmlsoap.org/wsdl/";
061: private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
062:
063: /* Currently, binding types are determined by the URI used for the binding subnode of
064: * the wsdl:binding element. E.g. soap:binding, http:binding, etc.
065: *
066: * Use the following constants to interpret the result of PortInfo.getBindingType()
067: */
068: private static final String SOAP_BINDING = "http://schemas.xmlsoap.org/wsdl/soap";
069: private static final String SOAP_BINDING_SLASH = "http://schemas.xmlsoap.org/wsdl/soap/";
070:
071: // Data collection results
072: private Map/*serviceName, ServiceInfo*/serviceMap;
073: private String targetNamespace;
074:
075: // Intermediate storage
076: private List/*PortInfo*/entirePortList;
077: private List/*PortInfo*/bindingPortList;
078: private List/*String*/wsdlImports;
079: private String currentServiceName;
080: private PortInfo bindingPort;
081: private Set wscompileFeatures;
082: private boolean serviceNameConflict;
083:
084: public PortInformationHandler() {
085: serviceMap = new LinkedHashMap(5);
086: entirePortList = new ArrayList();
087: bindingPortList = new ArrayList();
088: wsdlImports = new ArrayList();
089: initWscompileFeatures();
090: }
091:
092: public PortInformationHandler(String targetNamespace,
093: Map serviceMap, List entirePortList, List bindingPortList,
094: List wsdlImports) {
095: this .targetNamespace = targetNamespace;
096: this .serviceMap = serviceMap;
097: this .entirePortList = entirePortList;
098: this .bindingPortList = bindingPortList;
099: this .wsdlImports = wsdlImports;
100: initWscompileFeatures();
101: }
102:
103: private void initWscompileFeatures() {
104: wscompileFeatures = new HashSet(5);
105: wscompileFeatures.add("wsi");
106: wscompileFeatures.add("strict");
107: }
108:
109: public void startElement(String uri, String localname,
110: String qname, Attributes attributes) throws SAXException {
111: if (W3C_WSDL_SCHEMA.equals(uri)
112: || W3C_WSDL_SCHEMA_SLASH.equals(uri)) {
113: if ("portType".equals(localname)) { // NOI18N
114: PortInfo key = new PortInfo();
115: key.setPortType(attributes.getValue("name")); // NOI18N
116:
117: PortInfo pi = (PortInfo) getPortInfoByKey(key);
118: if (pi == null) {
119: entirePortList.add(key);
120: }
121: } else if ("binding".equals(localname)) { // NOI18N
122: PortInfo key = new PortInfo();
123: key.setBinding(attributes.getValue("name")); // NOI18N
124: key.setPortType(getLocalPart(attributes
125: .getValue("type"))); // NOI18N
126:
127: PortInfo pi = (PortInfo) getPortInfoByKey(key);
128: if (pi == null) {
129: entirePortList.add(key);
130: } else {
131: if (pi.getBinding() == null) {
132: pi.setBinding(key.getBinding());
133: }
134: if (pi.getPortType() == null) {
135: pi.setPortType(key.getPortType());
136: }
137: }
138: bindingPort = pi;
139: bindingPortList.add(bindingPort);
140: } else if ("port".equals(localname)) { // NOI18N
141: PortInfo key = new PortInfo();
142: key.setPort(attributes.getValue("name")); // NOI18N
143: key.setBinding(getLocalPart(attributes
144: .getValue("binding"))); // NOI18N
145:
146: PortInfo pi = (PortInfo) getPortInfoByKey(key);
147: if (pi == null) {
148: entirePortList.add(key);
149: pi = key;
150: } else {
151: if (pi.getPort() == null) {
152: pi.setPort(key.getPort());
153: }
154: if (pi.getBinding() == null) {
155: pi.setBinding(key.getBinding());
156: }
157: }
158:
159: assert currentServiceName != null;
160:
161: ServiceInfo serviceInfo = (ServiceInfo) serviceMap
162: .get(currentServiceName);
163: if (serviceInfo == null) {
164: serviceInfo = new ServiceInfo(currentServiceName);
165: serviceMap.put(currentServiceName, serviceInfo);
166: }
167:
168: List servicePorts = serviceInfo.getPorts();
169: servicePorts.add(pi);
170: } else if ("service".equals(localname)) { // NOI18N
171: currentServiceName = attributes.getValue("name"); // NOI18N
172: if (currentServiceName != null) {
173: currentServiceName = Utilities
174: .removeSpacesFromServiceName(currentServiceName);
175: }
176: } else if ("definitions".equals(localname)) { // NOI18N
177: targetNamespace = attributes
178: .getValue("targetNamespace"); //NOI18N
179: } else if ("import".equals(localname)) { // NOI18N
180: String location = attributes.getValue("location"); // NOI18N
181: if (location != null)
182: wsdlImports.add(location);
183: }
184: } else if (bindingPort != null && "binding".equals(localname)) {
185: bindingPort.setBindingType(normalizeUri(uri));
186: if (SOAP_BINDING.equals(uri)
187: || SOAP_BINDING_SLASH.equals(uri)) {
188: String style = attributes.getValue("style"); //NOI18N
189: if (style != null
190: && ("rpc".equals(style) || style
191: .endsWith(":rpc"))) { //NOI18N
192: wscompileFeatures.remove("strict"); //NOI18N
193: wscompileFeatures.add("rpcliteral"); //NOI18N
194: }
195: }
196: } else if (W3C_XML_SCHEMA.equals(uri)) {
197: if ("element".equals(localname)) {
198: String elementType = attributes.getValue("type"); //NOI18N
199: if (elementType != null
200: && ("anyType".equals(elementType) || elementType
201: .endsWith(":anyType"))) { //NOI18N
202: wscompileFeatures.add("nodatabinding"); //NOI18N
203: }
204: } else if ("import".equals(localname)) {
205: if (attributes.getValue("schemaLocation") == null
206: && attributes.getValue("namespace") != null) { //NOI18N
207: wscompileFeatures.add("searchschema"); //NOI18N
208: }
209: }
210: }
211: }
212:
213: public Map getServices() {
214: return serviceMap;
215: }
216:
217: public void endElement(String uri, String localname, String qname)
218: throws SAXException {
219: if (W3C_WSDL_SCHEMA.equals(uri)
220: || W3C_WSDL_SCHEMA_SLASH.equals(uri)) {
221: if ("binding".equals(localname)) {
222: bindingPort = null;
223: } else if ("service".equals(localname)) { //NOI18N
224: if (currentServiceName != null) {
225: PortInformation.ServiceInfo si = getServiceInfo(currentServiceName);
226: if (si != null) {
227: List ports = si.getPorts();
228: for (Iterator it = ports.iterator(); it
229: .hasNext();) {
230: PortInformation.PortInfo pi = (PortInformation.PortInfo) it
231: .next();
232: if (currentServiceName.equals(pi
233: .getPortType())) {
234: serviceNameConflict = true;
235: break;
236: }
237: }
238:
239: }
240: }
241: currentServiceName = null;
242: }
243: }
244: }
245:
246: public boolean isServiceNameConflict() {
247: return serviceNameConflict;
248: }
249:
250: public String[] getServiceNames() {
251: Set keys = serviceMap.keySet();
252: return (String[]) keys.toArray(new String[keys.size()]);
253: }
254:
255: public PortInformation.ServiceInfo getServiceInfo(String serviceName) {
256: // !PW FIXME this is another place where case sensitivity of service names
257: // is biting me. websvc/registry forces first character of service name
258: // to uppercase (done inside JAXRPC/wscompile, so difficult to resolve).
259: // That is likely where the key will come from. However, we have stored
260: // the true case sensitive service name here. So to resolve matching
261: // problems, for now, search on key, if not found, iterate service map,
262: // doing case insensitive comparisons to find a match.
263: // return (ServiceInfo) serviceMap.get(serviceName);
264: ServiceInfo result = (ServiceInfo) serviceMap.get(serviceName);
265: if (result == null) {
266: Iterator iter = serviceMap.values().iterator();
267: while (iter.hasNext()) {
268: ServiceInfo si = (ServiceInfo) iter.next();
269: if (serviceName.equalsIgnoreCase(si.getServiceName())) {
270: result = si;
271: break;
272: }
273: }
274: }
275: return result;
276: }
277:
278: public List getBindings() {
279: return bindingPortList;
280: }
281:
282: public List getImportedSchemas() {
283: return wsdlImports;
284: }
285:
286: public String getTargetNamespace() {
287: return targetNamespace;
288: }
289:
290: public List getEntirePortList() {
291: return entirePortList;
292: }
293:
294: public Set getWscompileFeatures() {
295: return wscompileFeatures;
296: }
297:
298: /** If there is a trailing backslash on the uri, remove it.
299: */
300: private String normalizeUri(String uri) {
301: String result = uri;
302:
303: if (uri.charAt(uri.length() - 1) == '/') {
304: result = uri.substring(0, uri.length() - 1);
305: }
306:
307: return result;
308: }
309:
310: private PortInformation.PortInfo getPortInfoByKey(PortInfo key) {
311: PortInfo result = null;
312: Iterator iter = entirePortList.iterator();
313:
314: while (iter.hasNext()) {
315: PortInfo pi = (PortInfo) iter.next();
316:
317: if (compareField(key.getPort(), pi.getPort())) {
318: result = pi;
319: break;
320: } else if (compareField(key.getBinding(), pi.getBinding())) {
321: result = pi;
322: break;
323: } else if (compareField(key.getPortType(), pi.getPortType())) {
324: result = pi;
325: break;
326: }
327: }
328:
329: return result;
330: }
331:
332: private boolean compareField(final String key, final String match) {
333: boolean result = false;
334:
335: if (match != null && match.equals(key)) {
336: result = true;
337: }
338:
339: return result;
340: }
341:
342: private String getLocalPart(String uri) {
343: String result = uri;
344: int index = uri.lastIndexOf(':');
345: if (index != -1) {
346: result = uri.substring(index + 1);
347: }
348: return result;
349: }
350:
351: // public void fatalError(SAXParseException exception) throws SAXException {
352: // super.fatalError(exception);
353: // }
354: //
355: // public void error(SAXParseException exception) throws SAXException {
356: // super.error(exception);
357: // }
358: //
359: // public void warning(SAXParseException exception) throws SAXException {
360: // super.warning(exception);
361: // }
362:
363: public static final class PortInfo implements
364: PortInformation.PortInfo {
365: private String portName;
366: private String bindingName;
367: private String bindingType;
368: private String portTypeName;
369:
370: public PortInfo() {
371: }
372:
373: public String getPortType() {
374: return portTypeName;
375: }
376:
377: void setPortType(String pt) {
378: portTypeName = pt;
379: }
380:
381: public String getBinding() {
382: return bindingName;
383: }
384:
385: void setBinding(String b) {
386: bindingName = b;
387: }
388:
389: public String getBindingType() {
390: return bindingType;
391: }
392:
393: void setBindingType(String bt) {
394: bindingType = bt;
395: }
396:
397: public String getPort() {
398: return portName;
399: }
400:
401: void setPort(String p) {
402: portName = p;
403: }
404:
405: public String toString() {
406: return "(" + portName + ", " + bindingName + ", "
407: + portTypeName + ")"; // NOI18N
408: }
409: }
410:
411: public static final class ServiceInfo implements
412: PortInformation.ServiceInfo {
413:
414: private String serviceName;
415: private List portList;
416:
417: public ServiceInfo(String name, List ports) {
418: init(name, ports);
419: }
420:
421: public ServiceInfo(String name) {
422: init(name, new ArrayList());
423: }
424:
425: private void init(String name, List ports) {
426: this .serviceName = name;
427: this .portList = ports;
428: }
429:
430: public String getServiceName() {
431: return serviceName;
432: }
433:
434: public List/*PortInfo*/getPorts() {
435: return portList;
436: }
437:
438: }
439: }
|