KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > soap > skeleton > DirectSkeleton


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.soap.skeleton;
31
32 import com.caucho.jaxb.JAXBUtil;
33 import com.caucho.soap.wsdl.*;
34 import com.caucho.util.L10N;
35 import com.caucho.xml.XmlPrinter;
36
37 import org.w3c.dom.Node JavaDoc;
38
39 import javax.jws.WebService;
40 import javax.xml.bind.JAXBContext;
41 import javax.xml.bind.JAXBException;
42 import javax.xml.bind.Marshaller;
43 import javax.xml.bind.PropertyException;
44 import javax.xml.namespace.QName JavaDoc;
45 import javax.xml.stream.XMLStreamException;
46 import javax.xml.stream.XMLStreamReader;
47 import javax.xml.stream.XMLStreamWriter;
48 import javax.xml.transform.dom.DOMResult JavaDoc;
49 import javax.xml.ws.WebServiceException;
50 import java.io.File JavaDoc;
51 import java.io.FileOutputStream JavaDoc;
52 import java.io.IOException JavaDoc;
53 import java.io.OutputStream JavaDoc;
54 import java.io.Writer JavaDoc;
55 import java.lang.reflect.Method JavaDoc;
56 import java.net.MalformedURLException JavaDoc;
57 import java.util.HashMap JavaDoc;
58 import java.util.StringTokenizer JavaDoc;
59 import java.util.logging.Logger JavaDoc;
60
61 /**
62  * Invokes a SOAP request on a Java POJO
63  */

64 public class DirectSkeleton extends Skeleton {
65   private static final Logger JavaDoc log =
66     Logger.getLogger(DirectSkeleton.class.getName());
67   public static final L10N L = new L10N(DirectSkeleton.class);
68
69   private JAXBContext _context;
70   private Marshaller _marshaller;
71   private Node JavaDoc _wsdlNode;
72
73   private HashMap JavaDoc<String JavaDoc,AbstractAction> _actionMap
74     = new HashMap JavaDoc<String JavaDoc,AbstractAction>();
75
76   private Class JavaDoc _api;
77   
78   private String JavaDoc _namespace;
79   private String JavaDoc _name;
80   private String JavaDoc _typeName;
81   private String JavaDoc _portName;
82   private String JavaDoc _serviceName;
83   private String JavaDoc _wsdlLocation;
84
85   private final WSDLDefinitions _wsdl = new WSDLDefinitions();
86   private final WSDLTypes _wsdlTypes = new WSDLTypes();
87   private final WSDLPortType _wsdlPortType = new WSDLPortType();
88   private final WSDLBinding _wsdlBinding = new WSDLBinding();
89   private final WSDLService _wsdlService = new WSDLService();
90   private final SOAPAddress _soapAddress = new SOAPAddress();
91
92   public DirectSkeleton(Class JavaDoc type, String JavaDoc wsdlAddress)
93   {
94     WebService webService = (WebService) type.getAnnotation(WebService.class);
95     setNamespace(type);
96
97     _name = getWebServiceName(type);
98     _typeName = _name + "PortType";
99
100     _serviceName = webService != null && ! webService.serviceName().equals("")
101       ? webService.serviceName()
102       : _name + "HttpBinding";
103
104     _portName =
105       webService != null && ! webService.portName().equals("")
106       ? webService.portName()
107       : _name + "HttpPort";
108
109     _wsdlLocation =
110       webService != null && ! webService.wsdlLocation().equals("")
111       ? webService.wsdlLocation()
112       : null;
113
114     _wsdl.setTargetNamespace(_namespace);
115
116     _wsdl.addDefinition(_wsdlTypes);
117
118     _wsdlPortType.setName(_typeName);
119     _wsdl.addDefinition(_wsdlPortType);
120
121     javax.jws.soap.SOAPBinding sbAnnotation =
122       (javax.jws.soap.SOAPBinding)
123       type.getAnnotation(javax.jws.soap.SOAPBinding.class);
124
125     com.caucho.soap.wsdl.SOAPBinding soapBinding =
126       new com.caucho.soap.wsdl.SOAPBinding();
127     soapBinding.setTransport("http://schemas.xmlsoap.org/soap/http");
128
129     if (sbAnnotation != null &&
130         sbAnnotation.style() == javax.jws.soap.SOAPBinding.Style.RPC)
131       soapBinding.setStyle(SOAPStyleChoice.RPC);
132     else
133       soapBinding.setStyle(SOAPStyleChoice.DOCUMENT);
134
135     if (sbAnnotation != null &&
136         sbAnnotation.use() == javax.jws.soap.SOAPBinding.Use.ENCODED)
137       throw new WebServiceException(L.l("Encoded SOAP style not supported by JAX-WS"));
138
139     _wsdlBinding.addAny(soapBinding);
140     _wsdlBinding.setName(_name + "Binding");
141     _wsdlBinding.setType(new QName JavaDoc(_namespace, _typeName, "tns"));
142
143     _wsdl.addDefinition(_wsdlBinding);
144
145     _wsdlService.setName(_serviceName);
146
147     WSDLPort port = new WSDLPort();
148     port.setName(_name + "Port");
149     port.setBinding(new QName JavaDoc(_namespace, _name + "Binding", "tns"));
150
151     _soapAddress.setLocation(wsdlAddress);
152     port.addAny(_soapAddress);
153
154     _wsdlService.addPort(port);
155
156     _wsdl.addDefinition(_wsdlService);
157   }
158
159   public String JavaDoc getNamespace()
160   {
161     return _namespace;
162   }
163
164   private void setNamespace(Class JavaDoc type)
165   {
166     WebService webService = (WebService) type.getAnnotation(WebService.class);
167
168     if (webService != null && ! webService.targetNamespace().equals(""))
169       _namespace = webService.targetNamespace();
170     else {
171       _namespace = null;
172       String JavaDoc packageName = type.getPackage().getName();
173       StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(packageName, ".");
174
175       while (st.hasMoreTokens()) {
176         if (_namespace == null)
177           _namespace = st.nextToken();
178         else
179           _namespace = st.nextToken() + "." + _namespace;
180       }
181
182       _namespace = "http://"+_namespace+"/";
183     }
184   }
185
186   static String JavaDoc getWebServiceName(Class JavaDoc type)
187   {
188     WebService webService = (WebService) type.getAnnotation(WebService.class);
189
190     if (webService != null && !webService.name().equals(""))
191       return webService.name();
192     else
193       return JAXBUtil.classBasename(type);
194   }
195
196   public void addAction(String JavaDoc name, AbstractAction action)
197   {
198     _actionMap.put(name, action);
199
200     _wsdl.addDefinition(action.getInputMessage());
201     _wsdl.addDefinition(action.getOutputMessage());
202
203     _wsdlPortType.addOperation(action.getOperation());
204     _wsdlBinding.addOperation(action.getBindingOperation());
205   }
206
207   /**
208    * Invokes the request on a remote object using an outbound XML stream.
209    */

210   public Object JavaDoc invoke(Method JavaDoc method, String JavaDoc url, Object JavaDoc[] args)
211     throws IOException JavaDoc, XMLStreamException, MalformedURLException JavaDoc, JAXBException
212   {
213     String JavaDoc actionName = AbstractAction.getWebMethodName(method);
214     AbstractAction action = _actionMap.get(actionName);
215
216     if (action != null)
217       return action.invoke(url, args);
218     else if ("toString".equals(actionName))
219       return "SoapStub[" + (_api != null ? _api.getName() : "") + "]";
220     else
221       throw new RuntimeException JavaDoc("no such method: " + actionName);
222   }
223   
224   /**
225    * Invokes the request on a local object using an inbound XML stream.
226    */

227   public void invoke(Object JavaDoc service, XMLStreamReader in, XMLStreamWriter out)
228     throws IOException JavaDoc, XMLStreamException, Throwable JavaDoc
229   {
230     in.nextTag();
231
232     if (! "Envelope".equals(in.getName().getLocalPart()))
233       throw new IOException JavaDoc(L.l("expected Envelope at {0}", in.getName()));
234
235     in.nextTag();
236
237     if ("Header".equals(in.getName().getLocalPart())) {
238       int depth = 1;
239
240       while (depth > 0) {
241         switch (in.nextTag()) {
242           case XMLStreamReader.START_ELEMENT:
243             depth++;
244             break;
245           case XMLStreamReader.END_ELEMENT:
246             depth--;
247             break;
248         }
249       }
250
251       in.nextTag();
252     }
253
254     if (! "Body".equals(in.getName().getLocalPart()))
255       throw new IOException JavaDoc(L.l("expected Body at {0}", in.getName()));
256
257     in.nextTag();
258
259     String JavaDoc actionName = in.getName().getLocalPart();
260     in.nextTag();
261
262     out.writeStartDocument();
263     out.writeStartElement(SOAP_ENVELOPE_PREFIX, "Envelope", SOAP_ENVELOPE);
264     out.writeNamespace(SOAP_ENVELOPE_PREFIX, SOAP_ENVELOPE);
265     //out.writeNamespace("xsi", XMLNS_XSI);
266
out.writeNamespace("xsd", XMLNS_XSD);
267
268     out.writeStartElement(SOAP_ENVELOPE_PREFIX, "Body", SOAP_ENVELOPE);
269
270     AbstractAction action = _actionMap.get(actionName);
271
272     // XXX: exceptions<->faults
273
if (action != null)
274       action.invoke(service, in, out);
275     else {
276       // XXX: fault
277
}
278
279     if (in.getEventType() != in.END_ELEMENT)
280       throw new IOException JavaDoc("expected </" + actionName + ">, " +
281                             "not event of type " + in.getEventType());
282     else if (! actionName.equals(in.getLocalName()))
283       throw new IOException JavaDoc("expected </" + actionName + ">, " +
284                             "not </" + in.getLocalName() + ">");
285
286     if (in.nextTag() != in.END_ELEMENT)
287       throw new IOException JavaDoc("expected </Body>, got: " + in.getName());
288     else if (! "Body".equals(in.getLocalName()))
289       throw new IOException JavaDoc("expected </Body>, got: " + in.getName());
290     /*
291     if (in.nextTag() != in.END_ELEMENT)
292       throw new IOException("expected </Envelope>");
293     else if (! "Envelope".equals(in.getName().getLocalPart()))
294       throw new IOException("expected </Envelope>");
295     */

296
297     out.writeEndElement(); // Body
298
out.writeEndElement(); // Envelope
299
}
300
301   private Node JavaDoc getWSDLNode()
302     throws JAXBException
303   {
304     if (_wsdlNode != null)
305       return _wsdlNode;
306
307     if (_context == null)
308       _context = JAXBContext.newInstance("com.caucho.soap.wsdl");
309
310     if (_marshaller == null) {
311       _marshaller = _context.createMarshaller();
312
313       try {
314         _marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
315       }
316       catch(PropertyException e) {
317         // Non fatal
318
log.finer(L.l("Unable to set prefix mapper"));
319       }
320     }
321
322     DOMResult JavaDoc result = new DOMResult JavaDoc();
323     _marshaller.marshal(_wsdl, result);
324
325     _wsdlNode = result.getNode();
326
327     return _wsdlNode;
328   }
329
330   /**
331    * Used by WebServiceIntrospector to append the schema for the WSDL.
332    */

333   public Node JavaDoc getTypesNode()
334     throws JAXBException
335   {
336     Node JavaDoc wsdlNode = getWSDLNode();
337
338     Node JavaDoc definitionsNode = wsdlNode.getFirstChild();
339
340     // XXX switch from getNodeName to getLocalName when QName is fixed
341
if (definitionsNode == null ||
342         ! "definitions".equals(definitionsNode.getNodeName()))
343       throw new JAXBException(L.l("Unable to attach types node"));
344
345     Node JavaDoc typesNode = definitionsNode.getFirstChild();
346
347     if (typesNode == null || ! "types".equals(typesNode.getNodeName()))
348       throw new JAXBException(L.l("Unable to attach types node"));
349
350     return typesNode;
351   }
352
353   public void dumpWSDL(OutputStream JavaDoc w)
354     throws IOException JavaDoc, JAXBException
355   {
356     XmlPrinter printer = new XmlPrinter(w);
357     printer.setPrintDeclaration(true);
358     printer.printPrettyXml(getWSDLNode());
359   }
360
361   public void dumpWSDL(Writer w)
362     throws IOException JavaDoc, JAXBException
363   {
364     XmlPrinter printer = new XmlPrinter(w);
365     printer.setPrintDeclaration(true);
366     printer.printPrettyXml(getWSDLNode());
367   }
368
369   /**
370    * Dumps a WSDL into the specified directory using the service name
371    * annotation if present. (Mainly for TCK, wsgen)
372    */

373   public void dumpWSDL(String JavaDoc dir)
374     throws IOException JavaDoc, JAXBException
375   {
376     File JavaDoc child = new File JavaDoc(dir, _serviceName + ".wsdl");
377     dumpWSDL(new FileOutputStream JavaDoc(child));
378   }
379 }
380
Popular Tags