001: /*
002: * Copyright 2001-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package samples.attachments;
018:
019: import org.apache.axis.AxisFault;
020: import org.apache.axis.attachments.AttachmentPart;
021: import org.apache.axis.client.Call;
022: import org.apache.axis.client.Service;
023: import org.apache.axis.message.SOAPBodyElement;
024: import org.apache.axis.transport.http.HTTPConstants;
025: import org.apache.axis.utils.Options;
026: import org.w3c.dom.Document;
027: import org.w3c.dom.Element;
028: import org.w3c.dom.Node;
029:
030: import javax.activation.DataHandler;
031: import javax.activation.FileDataSource;
032: import java.io.ByteArrayInputStream;
033: import java.net.URL;
034: import java.util.Hashtable;
035: import java.util.Vector;
036:
037: /**
038: *
039: * @author Rick Rineholt
040: */
041:
042: /**
043: * An example of sending an attachment via messages.
044: * The main purpose is to validate the different types of attachment references
045: * by content Id, content location both absolute and relative.
046: *
047: * Creates 5 separate attachments referenced differently by a SOAP document.
048: * Each attachment contains a string that is assembled and tested to see if
049: * if the attachments are correctly sent and referenced. Each attachment also
050: * contains a mime header indicating its position and validated on the server
051: * to see if mime headers are correctly sent with attachments.
052: *
053: * Sends the same message again however the second attachments are placed in the
054: * stream in reverse to see if they are still referenced ok.
055: *
056: *
057: * The return SOAP document references a single attachment which is the a Java
058: * serialized vector holding strings to the individual attachments sent.
059: *
060: * Demos using attachments directly.
061: *
062: */
063: public class TestRef {
064:
065: Options opts = null;
066: public static final String positionHTTPHeader = "Ordinal";
067: public static final String TheKey = "Now is the time for all good men to come to the aid of their country.";
068:
069: public TestRef(Options opts) {
070: this .opts = opts;
071: }
072:
073: /**
074: * This method sends all the files in a directory.
075: * @param The directory that is the source to send.
076: * @return True if sent and compared.
077: */
078: public boolean testit() throws Exception {
079: boolean rc = true;
080: String baseLoc = "http://axis.org/attachTest";
081: Vector refs = new Vector(); //holds a string of references to attachments.
082:
083: Service service = new Service(); //A new axis Service.
084:
085: Call call = (Call) service.createCall(); //Create a call to the service.
086:
087: /*Un comment the below statement to do HTTP/1.1 protocol*/
088: //call.setScopedProperty(MessageContext.HTTP_TRANSPORT_VERSION,HTTPConstants.HEADER_PROTOCOL_V11);
089: Hashtable myhttp = new Hashtable();
090: myhttp.put(HTTPConstants.HEADER_CONTENT_LOCATION, baseLoc); //Send extra soap headers
091:
092: /*Un comment the below to do http chunking to avoid the need to calculate content-length. (Needs HTTP/1.1)*/
093: //myhttp.put(HTTPConstants.HEADER_TRANSFER_ENCODING, HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED);
094: /*Un comment the below to force a 100-Continue... This will cause httpsender to wait for
095: * this response on a post. If HTTP 1.1 and this is not set, *SOME* servers *MAY* reply with this anyway.
096: * Currently httpsender won't handle this situation, this will require the resp. which it will handle.
097: */
098: //myhttp.put(HTTPConstants.HEADER_EXPECT, HTTPConstants.HEADER_EXPECT_100_Continue);
099: call.setProperty(HTTPConstants.REQUEST_HEADERS, myhttp);
100:
101: call.setTargetEndpointAddress(new URL(opts.getURL())); //Set the target service host and service location,
102:
103: java.util.Stack rev = new java.util.Stack();
104: //Create an attachment referenced by a generated contentId.
105: AttachmentPart ap = new AttachmentPart(
106: new javax.activation.DataHandler("Now is the time",
107: "text/plain"));
108: refs.add(ap.getContentIdRef()); //reference the attachment by contentId.
109: ap.setMimeHeader(positionHTTPHeader, "" + refs.size()); //create a MIME header indicating postion.
110: call.addAttachmentPart(ap);
111: rev.push(ap);
112:
113: //Create an attachment referenced by a set contentId.
114: String setContentId = "rick_did_this";
115: ap = new AttachmentPart(new DataHandler(" for all good",
116: "text/plain"));
117: //new MemoryOnlyDataSource(
118: ap.setContentId(setContentId);
119: refs.add("cid:" + setContentId); //reference the attachment by contentId.
120: ap.setMimeHeader(positionHTTPHeader, "" + refs.size()); //create a MIME header indicating postion.
121: call.addAttachmentPart(ap);
122: rev.push(ap);
123:
124: //Create an attachment referenced by a absolute contentLocation.
125: ap = new AttachmentPart(
126: new DataHandler(" men to", "text/plain"));
127: //new MemoryOnlyDataSource( " men to", "text/plain" )));
128: ap.setContentLocation(baseLoc + "/firstLoc");
129: refs.add(baseLoc + "/firstLoc"); //reference the attachment by contentId.
130: ap.setMimeHeader(positionHTTPHeader, "" + refs.size()); //create a MIME header indicating postion.
131: call.addAttachmentPart(ap);
132: rev.push(ap);
133:
134: //Create an attachment referenced by relative location to a absolute location.
135: ap = new AttachmentPart(new DataHandler(" come to",
136: "text/plain"));
137: // new MemoryOnlyDataSource( " come to", "text/plain" )));
138: ap.setContentLocation(baseLoc + "/secondLoc");
139: refs.add("secondLoc"); //reference the attachment by contentId.
140: ap.setMimeHeader(positionHTTPHeader, "" + refs.size()); //create a MIME header indicating postion.
141: call.addAttachmentPart(ap);
142: rev.push(ap);
143:
144: //Create an attachment referenced by relative location to a relative location.
145: ap = new AttachmentPart(new DataHandler(
146: " the aid of their country.", "text/plain"));
147: // new MemoryOnlyDataSource( " the aid of their country.", "text/plain" )));
148: ap.setContentLocation("thirdLoc");
149: refs.add("thirdLoc"); //reference the attachment by contentId.
150: ap.setMimeHeader(positionHTTPHeader, "" + refs.size()); //create a MIME header indicating postion.
151: call.addAttachmentPart(ap);
152: rev.push(ap);
153:
154: //Now build the message....
155: String namespace = "urn:attachmentsTestRef"; //needs to match name of service.
156:
157: StringBuffer msg = new StringBuffer("\n<attachments xmlns=\""
158: + namespace + "\">\n");
159: for (java.util.Iterator i = refs.iterator(); i.hasNext();)
160: msg.append(" <attachment href=\"" + (String) i.next()
161: + "\"/>\n");
162:
163: msg.append("</attachments>");
164:
165: call.setUsername(opts.getUser());
166:
167: call.setPassword(opts.getPassword());
168:
169: call.setOperationStyle("document");
170: call.setOperationUse("literal");
171:
172: //Now do the call....
173: Object ret = call.invoke(new Object[] { new SOAPBodyElement(
174: new ByteArrayInputStream(msg.toString().getBytes(
175: "UTF-8"))) });
176:
177: validate(ret, call, "12345");
178:
179: //Note: that even though the attachments are sent in reverse they are still
180: // retreived by reference so the ordinal will still match.
181: int revc = 1;
182: for (ap = (AttachmentPart) rev.pop(); ap != null; ap = rev
183: .empty() ? null : (AttachmentPart) rev.pop()) {
184: call.addAttachmentPart(ap);
185: }
186:
187: //Now do the call....
188: ret = call.invoke(new Object[] { new SOAPBodyElement(
189: new ByteArrayInputStream(msg.toString().getBytes(
190: "UTF-8"))) });
191:
192: validate(ret, call, "54321");
193:
194: return rc;
195: }
196:
197: void validate(Object ret, Call call, final String expOrdPattern)
198: throws Exception {
199: if (null == ret) {
200: System.out.println("Received null ");
201: throw new AxisFault("", "Received null", null, null);
202: }
203:
204: if (ret instanceof String) {
205: System.out
206: .println("Received problem response from server: "
207: + ret);
208: throw new AxisFault("", (String) ret, null, null);
209: }
210:
211: Vector vret = (Vector) ret;
212:
213: if (!(ret instanceof java.util.Vector)) {
214: //The wrong type of object that what was expected.
215: System.out.println("Received unexpected type :"
216: + ret.getClass().getName());
217: throw new AxisFault("", "Received unexpected type:"
218: + ret.getClass().getName(), null, null);
219:
220: }
221:
222: org.apache.axis.message.RPCElement retrpc = (org.apache.axis.message.RPCElement) ((Vector) ret)
223: .elementAt(0);
224:
225: Document retDoc = org.apache.axis.utils.XMLUtils
226: .newDocument(new org.xml.sax.InputSource(
227: new java.io.ByteArrayInputStream(retrpc
228: .toString().getBytes())));
229:
230: //get at the attachments.
231: org.apache.axis.attachments.Attachments attachments = call
232: .getResponseMessage().getAttachmentsImpl();
233:
234: //Still here, so far so good.
235: Element rootEl = retDoc.getDocumentElement();
236:
237: Element caEl = getNextFirstChildElement(rootEl);
238: //this should be the only child element with the ref to our attachment
239: // response.
240: String href = caEl.getAttribute("href");
241: org.apache.axis.Part p = attachments
242: .getAttachmentByReference(href);
243: if (null == p)
244: throw new org.apache.axis.AxisFault("Attachment for ref='"
245: + href + "' not found.");
246:
247: //Check to see the the attachment were sent in order
248: String ordPattern = caEl.getAttribute("ordinalPattern");
249: if (!expOrdPattern.equals(ordPattern))
250: throw new org.apache.axis.AxisFault(
251: "Attachments sent out of order expected:'"
252: + expOrdPattern + "', got:'" + ordPattern
253: + "'.");
254:
255: //now get at the data...
256: DataHandler dh = ((org.apache.axis.attachments.AttachmentPart) p)
257: .getDataHandler();
258: System.err.println("content-type:" + dh.getContentType());
259:
260: java.util.Vector rspVector = null;
261: Object rspObject = dh.getContent();//This SHOULD just return the vector but reality strikes...
262: if (rspObject == null)
263: throw new AxisFault("", "Received unexpected object:null",
264: null, null);
265: else if (rspObject instanceof java.util.Vector)
266: rspVector = (java.util.Vector) rspObject;
267: else if (rspObject instanceof java.io.InputStream)
268: rspVector = (java.util.Vector) new java.io.ObjectInputStream(
269: (java.io.InputStream) rspObject).readObject();
270: else
271: throw new AxisFault("", "Received unexpected object:"
272: + rspObject.getClass().getName(), null, null);
273:
274: StringBuffer fullmsg = new StringBuffer();
275: for (java.util.Iterator ri = rspVector.iterator(); ri.hasNext();) {
276: String part = (String) ri.next();
277: fullmsg.append(part);
278: System.out.print(part);
279: }
280: System.out.println("");
281:
282: if (!(TheKey.equals(fullmsg.toString())))
283: throw new org.apache.axis.AxisFault("Fullmsg not correct'"
284: + fullmsg + "'.");
285: }
286:
287: Element getNextFirstChildElement(Node n) {
288: if (n == null)
289: return null;
290: n = n.getFirstChild();
291: for (; n != null && !(n instanceof Element); n = n
292: .getNextSibling())
293: ;
294: return (Element) n;
295: }
296:
297: Element getNextSiblingElement(Node n) {
298: if (n == null)
299: return null;
300: n = n.getNextSibling();
301: for (; n != null && !(n instanceof Element); n = n
302: .getNextSibling())
303: ;
304: return (Element) n;
305: }
306:
307: /**
308: * Give a single file to send or name a directory
309: * to send an array of attachments of the files in
310: * that directory.
311: */
312: public static void main(String args[]) {
313: try {
314:
315: Options opts = new Options(args);
316: TestRef echoattachment = new TestRef(opts);
317:
318: args = opts.getRemainingArgs();
319: int argpos = 0;
320:
321: if (echoattachment.testit()) {
322: System.out.println("Attachments sent and received ok!");
323: System.exit(0);
324: }
325: } catch (Exception e) {
326: System.err.println(e);
327: e.printStackTrace();
328: }
329: System.exit(18);
330: }
331:
332: /**
333: * Return an array of datahandlers for each file in the dir.
334: * @param the name of the directory
335: * @return return an array of datahandlers.
336: */
337:
338: protected DataHandler[] getAttachmentsFromDir(String dirName) {
339: java.util.LinkedList retList = new java.util.LinkedList();
340: DataHandler[] ret = new DataHandler[0];// empty
341:
342: java.io.File sourceDir = new java.io.File(dirName);
343:
344: java.io.File[] files = sourceDir.listFiles();
345:
346: for (int i = files.length - 1; i >= 0; --i) {
347: java.io.File cf = files[i];
348:
349: if (cf.isFile() && cf.canRead()) {
350: String fname = null;
351:
352: try {
353: fname = cf.getAbsoluteFile().getCanonicalPath();
354: } catch (java.io.IOException e) {
355: System.err.println("Couldn't get file \"" + fname
356: + "\" skipping...");
357: continue;
358: }
359: retList.add(new DataHandler(new FileDataSource(fname)));
360: }
361: }
362: if (!retList.isEmpty()) {
363: ret = new DataHandler[retList.size()];
364: ret = (DataHandler[]) retList.toArray(ret);
365: }
366:
367: return ret;
368: }
369:
370: /**This class should store all attachment data in memory */
371: static class MemoryOnlyDataSource extends
372: org.apache.axis.attachments.ManagedMemoryDataSource {
373:
374: MemoryOnlyDataSource(byte[] in, String contentType)
375: throws java.io.IOException {
376: super (new java.io.ByteArrayInputStream(in),
377: Integer.MAX_VALUE - 2, contentType, true);
378: }
379:
380: MemoryOnlyDataSource(String in, String contentType)
381: throws java.io.IOException {
382: this(in.getBytes(), contentType);
383: }
384: }
385: }
|