001: /*
002: * Copyright (c) 1998-2007 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.soap.reflect;
031:
032: import com.caucho.jaxb.JAXBContextImpl;
033: import com.caucho.jaxb.JAXBUtil;
034: import com.caucho.soap.jaxws.JAXWSUtil;
035: import com.caucho.soap.skeleton.DirectSkeleton;
036: import com.caucho.soap.skeleton.AbstractAction;
037: import com.caucho.soap.wsdl.WSDLDefinitions;
038: import com.caucho.util.L10N;
039:
040: import org.w3c.dom.Node;
041:
042: import javax.jws.WebMethod;
043: import javax.jws.WebService;
044: import javax.xml.bind.JAXBException;
045: import javax.xml.bind.Marshaller;
046: import javax.xml.bind.Unmarshaller;
047: import javax.xml.stream.XMLOutputFactory;
048: import javax.xml.stream.XMLStreamException;
049: import javax.xml.stream.XMLStreamWriter;
050: import javax.xml.transform.dom.DOMResult;
051: import javax.xml.ws.WebServiceException;
052: import java.lang.reflect.Method;
053: import java.lang.reflect.Modifier;
054: import java.util.HashMap;
055: import java.util.HashSet;
056: import java.util.LinkedHashMap;
057: import java.util.Map;
058: import java.util.logging.Logger;
059:
060: /**
061: * Introspects a web service
062: */
063: public class WebServiceIntrospector {
064: private static final Logger log = Logger
065: .getLogger(WebServiceIntrospector.class.getName());
066: private static XMLOutputFactory _outputFactory = null;
067:
068: public static final L10N L = new L10N(WebServiceIntrospector.class);
069:
070: /**
071: * Introspects the class
072: */
073: public static DirectSkeleton introspect(Class type)
074: throws JAXBException, WebServiceException {
075: // matches RI stub for the WSDL location
076: return introspect(type, "REPLACE_WITH_ACTUAL_URL", null);
077: }
078:
079: /**
080: * Introspects the class
081: */
082: public static DirectSkeleton introspect(Class type,
083: String wsdlLocation, WSDLDefinitions wsdl)
084: throws JAXBException, WebServiceException {
085: // server/4221 vs soap/0301
086: /*
087: if (! type.isAnnotationPresent(WebService.class))
088: throw new RuntimeException(L.l("{0}: needs a @WebService annotation.",
089: type.getName()));
090: */
091:
092: boolean isInterface = type.isInterface();
093:
094: WebService webService = (WebService) type
095: .getAnnotation(WebService.class);
096:
097: // Get all the classes that JAXB needs, then generate schema for them
098: HashSet<Class> jaxbClasses = new HashSet<Class>();
099: JAXBUtil.introspectClass(type, jaxbClasses);
100: Class[] jaxbClassArray = new Class[jaxbClasses.size()];
101: jaxbClasses.toArray(jaxbClassArray);
102:
103: Class api = JAXWSUtil.getEndpointInterface(type);
104: String namespace = JAXWSUtil.getTargetNamespace(type, api);
105:
106: Map<String, Object> properties = new HashMap<String, Object>();
107: properties.put(JAXBContextImpl.TARGET_NAMESPACE, namespace);
108:
109: JAXBContextImpl jaxbContext = new JAXBContextImpl(
110: jaxbClassArray, properties);
111: Marshaller marshaller = jaxbContext.createMarshaller();
112: Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
113:
114: DirectSkeleton skel = new DirectSkeleton(type, api,
115: jaxbContext, wsdlLocation, namespace, wsdl);
116:
117: Method[] methods = type.getMethods();
118:
119: boolean excludeIfNoWebMethod = false;
120:
121: for (int i = 0; i < methods.length; i++) {
122: WebMethod webMethod = methods[i]
123: .getAnnotation(WebMethod.class);
124:
125: if (webMethod != null && !webMethod.exclude()) {
126: excludeIfNoWebMethod = true;
127: break;
128: }
129: }
130:
131: for (int i = 0; i < methods.length; i++) {
132: if ((methods[i].getModifiers() & Modifier.PUBLIC) == 0)
133: continue;
134:
135: WebMethod webMethod = methods[i]
136: .getAnnotation(WebMethod.class);
137:
138: if (api != type) {
139: /* XXX: needed for demo
140: if (webMethod != null)
141: throw new WebServiceException(L.l("Cannot use WebMethod with WebService.endpointInterface: {0}", type));
142: */
143:
144: try {
145: api.getDeclaredMethod(methods[i].getName(),
146: methods[i].getParameterTypes());
147: } catch (NoSuchMethodException e) {
148: // ignore methods not declared in the endpoint interface
149: continue;
150: }
151: }
152:
153: if (excludeIfNoWebMethod && webMethod == null)
154: continue;
155:
156: if (webService == null && webMethod == null && !isInterface)
157: continue;
158:
159: if (webMethod == null
160: && methods[i].getDeclaringClass() != type)
161: continue;
162:
163: if (webMethod != null && webMethod.exclude())
164: continue;
165:
166: AbstractAction action = AbstractAction.createAction(
167: methods[i], jaxbContext, namespace, wsdl,
168: marshaller, unmarshaller);
169:
170: skel.addAction(methods[i], action);
171: }
172:
173: return skel;
174: }
175:
176: private static XMLStreamWriter getStreamWriter(DOMResult result)
177: throws XMLStreamException {
178: if (_outputFactory == null)
179: _outputFactory = XMLOutputFactory.newInstance();
180:
181: return _outputFactory.createXMLStreamWriter(result);
182: }
183: }
|