001: /*
002: * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
003: * Copyright (C) 2007 - Javolution (http://javolution.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package javolution.xml.ws;
010:
011: import j2me.lang.CharSequence;
012: import j2me.lang.UnsupportedOperationException;
013: import java.io.IOException;
014: import javolution.io.AppendableWriter;
015: import javolution.io.UTF8StreamWriter;
016: import javolution.text.Text;
017: import javolution.text.TextBuilder;
018: import javolution.xml.XMLObjectReader;
019: import javolution.xml.XMLObjectWriter;
020: import javolution.xml.stream.XMLStreamException;
021: import javolution.xml.stream.XMLStreamReader;
022: import javolution.xml.stream.XMLStreamWriter;
023:
024: /**
025: * <p> This class provides a simple web service client capable of leveraging
026: * Javolution {@link javolution.xml XML marshalling/unmarshalling}.</p>
027: *
028: * <p> Sub-classes may work from WSDL files, {@link javolution.xml.XMLFormat
029: * XMLFormat} or directly with the XML streams (StAX). For example:[code]
030: * private static class HelloWorld extends WebServiceClient {
031: * protected void writeRequest(XMLObjectWriter out) throws XMLStreamException {
032: * XMLStreamWriter xml = out.getStreamWriter();
033: * xml.writeDefaultNamespace("http://www.openuri.org/");
034: * xml.writeEmptyElement("helloWorld"); // Operation name.
035: * }
036: * protected void readResponse(XMLObjectReader in) throws XMLStreamException {
037: * XMLStreamReader xml = in.getStreamReader();
038: * xml.require(START_ELEMENT, "http://www.openuri.org/", "string");
039: * xml.next(); // Move to character content.
040: * System.out.println(xml.getText());
041: * }
042: * }
043: * WebServiceClient ws = new HelloWorld().setAddress("http://acme.com:80/HelloWorld.jws");
044: * ws.invoke();
045: *
046: * > Hello World!
047: * [/code]</p>
048: *
049: * <p><b>Note:</b> At this moment, this class is supported only on the J2SE
050: * platform. Soon, it will also be supported on mobile devices
051: * through the CLDC/MIDP Generic Connection framework.</p>
052: *
053: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
054: * @version 5.2, September 16, 2007
055: */
056: public abstract class WebServiceClient {
057:
058: /**
059: * Holds standard SOAP envelope prefix.
060: */
061: public static final String ENVELOPE_PREFIX = "env";
062:
063: /**
064: * Holds standard SOAP envelope namespace.
065: */
066: public static final String ENVELOPE_URI = "http://schemas.xmlsoap.org/soap/envelope/";
067:
068: /**
069: * Holds the URL (J2SE).
070: */
071: Object _url;
072:
073: /**
074: * Default constructor (address not set).
075: */
076: public WebServiceClient() {
077: /*@JVM-1.4+@
078: if (true) return;
079: /**/
080: throw new UnsupportedOperationException(
081: "J2ME Not Supported Yet");
082: }
083:
084: /**
085: * Sets the address of this web service.
086: *
087: * @param address the service full address.
088: */
089: public WebServiceClient setAddress(String address) {
090: /*@JVM-1.4+@
091: try {
092: _url = new java.net.URL(address);
093: } catch (java.net.MalformedURLException e) {
094: throw new IllegalArgumentException("Malformed URL: " + address);
095: }
096: /**/
097: return this ;
098: }
099:
100: /**
101: * Invokes the web service.
102: */
103: public void invoke() throws IOException, XMLStreamException {
104: try {
105: // Formats the request message (we cannot write directly to
106: // the output stream because the http request requires the length.
107: _out.setOutput(_buffer);
108: _writer.setOutput(_out);
109: final XMLStreamWriter xmlOut = _writer.getStreamWriter();
110: xmlOut.setPrefix(csq(ENVELOPE_PREFIX), csq(ENVELOPE_URI));
111: xmlOut
112: .writeStartElement(csq(ENVELOPE_URI),
113: csq("Envelope"));
114: xmlOut.writeNamespace(csq(ENVELOPE_PREFIX),
115: csq(ENVELOPE_URI));
116: xmlOut.writeStartElement(csq(ENVELOPE_URI), csq("Header"));
117: xmlOut.writeEndElement();
118: xmlOut.writeStartElement(csq(ENVELOPE_URI), csq("Body"));
119: writeRequest(_writer);
120: _writer.close();
121:
122: // Sends the request.
123: if (_url == null)
124: throw new IOException("URL not set");
125: /*@JVM-1.4+@
126: java.net.HttpURLConnection http = (java.net.HttpURLConnection)
127: ((java.net.URL)_url).openConnection();
128: http.setRequestProperty("Content-Length", String.valueOf(_buffer
129: .length()));
130: http.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
131: // httpConn.setRequestProperty("SOAPAction", "");
132: http.setRequestMethod("POST");
133: http.setDoOutput(true);
134: http.setDoInput(true);
135: _utf8Writer.setOutput(http.getOutputStream());
136: /**/
137: _buffer.print(_utf8Writer);
138: _utf8Writer.close();
139:
140: // Reads the response.
141: /*@JVM-1.4+@
142: _reader.setInput(http.getInputStream());
143: /**/
144: final XMLStreamReader xmlIn = _reader.getStreamReader();
145: while (xmlIn.hasNext()) {
146: if ((xmlIn.next() == XMLStreamReader.START_ELEMENT)
147: && xmlIn.getLocalName().equals("Body")
148: && xmlIn.getNamespaceURI().equals(ENVELOPE_URI)) {
149: // Found body, position reader to next element.
150: xmlIn.next();
151: readResponse(_reader);
152: break;
153: }
154: }
155:
156: } finally {
157: _reader.close();
158: _writer.reset();
159: _out.reset();
160: _buffer.reset();
161: _utf8Writer.reset();
162: _reader.reset();
163: }
164: }
165:
166: private final TextBuilder _buffer = new TextBuilder();
167: private final AppendableWriter _out = new AppendableWriter();
168: private final XMLObjectWriter _writer = new XMLObjectWriter();
169: private final UTF8StreamWriter _utf8Writer = new UTF8StreamWriter();
170: private final XMLObjectReader _reader = new XMLObjectReader();
171:
172: /**/
173:
174: /**
175: * Writes the web service request (SOAP body).
176: *
177: * @param out the XML object writer.
178: */
179: protected abstract void writeRequest(XMLObjectWriter out)
180: throws XMLStreamException;
181:
182: /**
183: * Reads the web service response (SOAP body). The default implementation
184: * writes the body XML events to <code>System.out</code>.
185: *
186: * @param in the XML object reader.
187: */
188: protected void readResponse(XMLObjectReader in)
189: throws XMLStreamException {
190: final XMLStreamReader xml = in.getStreamReader();
191: while (xml.hasNext()) {
192: switch (xml.next()) {
193: case XMLStreamReader.START_DOCUMENT:
194: System.out.println("Start Document");
195: break;
196: case XMLStreamReader.END_DOCUMENT:
197: System.out.println("End Document.");
198: break;
199: case XMLStreamReader.START_ELEMENT:
200: System.out.println("Start Element: "
201: + xml.getLocalName() + "("
202: + xml.getNamespaceURI() + ")");
203: for (int i = 0, n = xml.getAttributeCount(); i < n; i++) {
204: System.out.println(" Attribute: "
205: + xml.getAttributeLocalName(i) + "("
206: + xml.getAttributeNamespace(i)
207: + "), Value: " + xml.getAttributeValue(i));
208: }
209: break;
210: case XMLStreamReader.END_ELEMENT:
211: if (xml.getLocalName().equals("Body")
212: && xml.getNamespaceURI().equals(ENVELOPE_URI))
213: return; // End body.
214: System.out.println("End Element: " + xml.getLocalName()
215: + "(" + xml.getNamespaceURI() + ")");
216: break;
217: case XMLStreamReader.CHARACTERS:
218: System.out.println("Characters: " + xml.getText());
219: break;
220: case XMLStreamReader.CDATA:
221: System.out.println("CDATA: " + xml.getText());
222: break;
223: case XMLStreamReader.COMMENT:
224: System.out.println("Comment: " + xml.getText());
225: break;
226: case XMLStreamReader.SPACE:
227: System.out.println("Space");
228: break;
229: default:
230: System.out.println(xml);
231: }
232: }
233:
234: }
235:
236: // For J2ME compatiblity.
237: private static final CharSequence csq(Object string) {
238: return (string instanceof CharSequence) ? (CharSequence) string
239: : Text.valueOf(string);
240:
241: }
242: }
|