1 /*
2  * Created on Jun 17, 2003
3  *
4  * To change the template for this generated file go to
5  * Window>Preferences>Java>Code Generation>Code and Comments
6  */
7 /*
8  * Copyright (C) 2003  robert rowntree
9 
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19
20 * ref. http://www.gnu.org/copyleft/gpl.html
21*/
22//TODO this class should impl interface so that it can be plug-in
23//  impl of behavior that gets event(s) of type "data created"
24//  transportd from client to the PO. PO then inspects contents
25//  of what came up over the wire and reacts by forwarding the 
26//  raw data or by useing the transported event to "PULL" the 
27//  data from the client or maybe even trigger a 3rd party 
28//  P2P session(s) amoung all subscribers and the producer.
29package com.borneo.net.soap;
30
31import java.io.BufferedInputStream;
32import java.io.File;
33import java.io.IOException;
34import java.io.InputStream;
35import java.net.MalformedURLException;
36import java.net.URL;
37import java.rmi.RemoteException;
38import java.util.ArrayList;
39import java.util.Collection;
40import java.util.Iterator;
41import java.util.LinkedList;
42import java.util.Vector;
43
44import javax.activation.DataHandler;
45import javax.activation.FileDataSource;
46
47import javax.xml.namespace.QName;
48import javax.xml.rpc.ParameterMode;
49import javax.xml.rpc.ServiceException;
50import javax.xml.soap.AttachmentPart;
51import javax.xml.soap.Name;
52import javax.xml.soap.SOAPBody;
53import javax.xml.soap.SOAPBodyElement;
54import javax.xml.soap.SOAPConnection;
55import javax.xml.soap.SOAPElement;
56import javax.xml.soap.SOAPException;
57import javax.xml.soap.SOAPMessage;
58
59import org.apache.axis.AxisFault;
60import org.apache.axis.Constants;
61import org.apache.axis.Message;
62import org.apache.axis.MessageContext;
63import org.apache.axis.attachments.OctetStream;
64import org.apache.axis.client.Call;
65import org.apache.axis.client.Service;
66import org.apache.axis.description.ParameterDesc;
67import org.apache.axis.encoding.TypeMapping;
68import org.apache.axis.encoding.TypeMappingRegistry;
69import org.apache.axis.encoding.TypeMappingRegistryImpl;
70import org.apache.axis.encoding.XMLType;
71import org.apache.axis.message.RPCElement;
72import org.apache.axis.message.RPCParam;
73import org.apache.axis.message.SOAPEnvelope;
74import org.apache.axis.soap.MessageFactoryImpl;
75import org.apache.axis.soap.SOAPConnectionFactoryImpl;
76import org.apache.log4j.Logger;
77import org.apache.log4j.PropertyConfigurator;
78
79import com.borneo.util.FileSelector;
80import com.borneo.util.POProperty;
81
82/** 
83 * This implementation uses following API's to PUSH data to Remote Node:
84 *   HTTP, SOAP, Apache AXIS, JAX-RPC, SAAJ or SwA.  
85 * Manager class for API's in above list. This class sits between the client app.
86 * where data is being created and the entire API collection that implements
87 * connectivity for distributing files in a data-interchange or PostOffice.
88 * @author r
89 * <p>CLIENT-SIDE uses SAAJ API for Web Services and "Soap with Attachments"
90 * 4 options for WS connections designated by property file key="ws.invocation.typ"
91 *   - diicall "invoke" supports parm "ArrayOFDataHandler" dynamic req'd
92 *       std msg call won't support the array ... had to patch w/ dii
93 *   - SoapMsg "call" single File supports non-array type DataHandlers in parms
94 *   - SoapMsg "call" FileSet supports array-OF-DataHandlers in parms 
95 * </p><p>
96 * According to SAAJ API rules, the client formats a SOAP msg that will
97 * get to the proper WS endpt and that will meet the signature of the
98 * requested method at that endpt. 
99 * see WSDL "service", "port", "operation" elements.
00 * </p><p>
01 * The Server is according to JAX-RPC so, according to SAAJ, the SOAP message
02 * constructed here in the client needs to conform to the server-side JAX-RPC signature.
03 * 
04 * The properties file has following directives:
05 * - 3 for "wsdl" concat these for the service Endpoint
06 * - 1 for "soap" operation or method called by RPC on server 
07 * - 1 for "ws" "connect" type  (dynamic or static msg call) 
08 *  - for the method called on the service class handling that endpt
09 *    useing these, go chek the method and it's argList... 
10 * The "service" element of the wsdd file, relates the URL from the 
11 * client's endpt. to the actual Service class and list of allowed methods...
12 * Well, what is the link you use to coordinate Client and Server?
13 * * Ans: get the endpt. URL and query the WSDL via browser link belo
14 *  <host><port>/axis/services/urn:EchoAttachmentsService?wsdl 
15 * </p><p>
16 * If you want to extend the signature you have to make correlated changes to:
17 *  - wsdd.   then redeploy to AXIS container
18 *  - Client methods <this> to format the SOAP Envelope's elements
19 *  - server implementation and method's parameters and parm order
20 *  - without the server being up, you can test revision...
21 *     use TCPMON to trap the client message and inspect
22 *    the child element of <soapenv:Body>. Child's name should =
23 *    method name on the server .. follow the rules outlined in the SOAP
24 *    spec under "RPC and SOAP Body"
25 * </p>
26 * To change the template for this generated type comment go to
27 * Window>Preferences>Java>Code Generation>Code and Comments
28 * TODO encryption and other bolt on Services can be added via 
29 * DD Layer and the following Interface. 
30 * see ${sun.JWSDP.dev.pack}/docs/api/javax/xml/rpc/handler/Handler.html
31 * The above also applies to server-side changes.
32 */
33
34public class SAAJCallMgr {
35    
36    SOAPConnection soapConnection;
37//  SOAPMessage message;
38    Message reqMessage;
39    Message resMessage;
40    
41    SOAPEnvelope requestEnvelope; 
42    SOAPElement elementRpcOp;
43    protected static Logger log;
44    private MessageContext     msgContext      = null ;
45
46
47//TODO what is the proper duration of the connection belo??
48//    where is the connection killed    
49    public void setConnection(SOAPConnection conn){
50        log.debug("beg. getconn ");     
51            soapConnection = conn;
52        }
53    public SOAPConnection getConnection(){
54        return soapConnection;
55        }
56//TODO need an interface for the SOAP struct setters
57//    they are always the same ( env, body, method, parmSet )       
58
59// wrong should be addMessageAttachment (impl, File)
60//  
61    public void putFile(File afile, String wsdlURL){
62        AttachmentPart attachment =
63            getReqMessage().createAttachmentPart(
64                new DataHandler(
65                    new FileDataSource(
66                        afile               
67                    )
68                )
69            );
70        getReqMessage().addAttachmentPart(attachment);
71        try{
72            elementRpcOp.addAttribute(
73                requestEnvelope.createName("href")
74                , "cid:" + attachment.getContentId()
75            );
76            log.debug("making SOAP call to " +wsdlURL);
77            javax.xml.soap.SOAPMessage returnedSOAPMessage =
78                getConnection().call(getReqMessage(), wsdlURL);
79        } catch (SOAPException e) {
80        // TODO Auto-generated catch block
81        e.printStackTrace();
82        }   
83    }
84    public void putFile(Collection fileset){
85        for ( 
86            Iterator i = fileset.iterator();i.hasNext();
87        ){
88            putFile( 
89                (File)i.next()
90                ,
91                POProperty.get(
92                    "wsdl.service.addr.host"
93                ) 
94                + "/" 
95                + POProperty.get(
96                    "wsdl.service.addr.axis.webapp"
97                )
98                + "/" 
99                + POProperty.get(
00                    "wsdl.service.addr.port.name"
01                )                               
02            );
03        }   
04    }
05    public void putFile(String name, String wsdlURL){
06    // better signature(s) ( File, Endpt ) ( FileSet, Endpt )
07    // Set above just delegates to singleFile   
08    // not used because the instantiantion of the collection
09    // should be closer to the client making call of the service
10    // if you parm a string then you should also do a boolean parm
11    // for a "use name as regex pattern" to drive collection of files   
12    // fixme wrap the url
13    //"http://localhost:" +opts.getPort() + "/axis/services/urn:EchoAttachmentsService";
14    /*String wsdlURLString =  
15    POProperty.get(             
16        "file.io.output.rpc.attachment"                                 
17    );
18    */
19    System.out.println("beg. put fnm , endptURL : "
20        +name
21        +" "
22        +wsdlURL
23    );
24    try {
25                        
26
27//aset
28        
29      for ( Iterator i = 
30              FileSelector.getFiles(name).iterator() ;
31          i.hasNext();
32      ){
33                AttachmentPart attachment =
34                    getReqMessage().createAttachmentPart(
35                        new DataHandler(
36                            new FileDataSource(
37                                (File)i.next()              
38                            )
39                        )
40                    );                  
41                getReqMessage().addAttachmentPart(attachment);
42                elementRpcOp.addAttribute(
43                    requestEnvelope.createName("href")
44                    , "cid:" + attachment.getContentId()
45                );
46            }   //endFor
47            log.debug("making SOAP call to " +wsdlURL);
48            javax.xml.soap.SOAPMessage returnedSOAPMessage =
49                getConnection().call(getReqMessage(), wsdlURL);
50        } catch (SOAPException e) {
51        // TODO Auto-generated catch block
52        e.printStackTrace();
53    }
54    }
55    public MessageContext getMessageContext(){
56        return msgContext;
57    }
58    
59    public void setMessageContext(MessageContext msgC){
60         msgContext = msgC;
61    }   
62    
63    public Message getReqMessage(){
64        return reqMessage;
65    }
66    
67    /**
68     * Get the "SOAPMessage" portion of the soap message via calls
69     * to the appropriate Obj. Factory. Meant to be used by client 
70     * that is NOT in a container.
71     * @return javax.xml.soap.SOAPMessage
72     */ 
73    public void setReqMessage(Message msg){
74        log.debug("beg. getmsg ");
75    
76            reqMessage = msg;
77        
78    }
79
80    /**
81     * Get the "SOAPEnvelope" portion of the soap message.
82     * @return SOAPEnvelope
83     */ 
84    public SOAPEnvelope getRequestEnvelope(){           
85            return requestEnvelope;
86    }
87
88    public SOAPEnvelope getRequestEnvelope(Message msg){
89        try {
90            return msg.getSOAPEnvelope();
91            
92//          return this.getReqMessage().getSOAPEnvelope();
93//          return this.getMessage().getSOAPPart().getEnvelope();
94
95        } catch (AxisFault e) {
96            // TODO Auto-generated catch block
97            e.printStackTrace();
98            return null;
99        }
00    }
01
02    public void setRequestEnvelope(SOAPEnvelope env){
03
04        requestEnvelope = env;
05    }
06
07/**
08 * Get the "SOAPBody" portion of the soap message.
09 * @return javax.xml.soap.SOAPBody
10 */ 
11    public SOAPBody getBody(){
12        try {           
13            return  getRequestEnvelope(this.getReqMessage()).getBody();
14        } catch (SOAPException e) {
15            // TODO Auto-generated catch block
16            e.printStackTrace();
17            return null;
18        }
19    }
20    /** 
21     * This is the ROOT element of the XML content portion of the
22     * SoapBody obj. The name of this element is also the RPC Operation name
23     * that's called via JAX-RPC on the server.
24     */
25    public SOAPElement getElementRpcOp(){
26        return elementRpcOp;
27    }
28
29/**
30 * This needs to be set as part of the creation of the SOAPMESSAGe and 
31 * its contents. This is the ROOT element of the XML content portion of the
32 * SoapBody obj. The name of this element is also the RPC Operation name
33 * that's called via JAX-RPC on the server.
34 * @param element javax.xml.soap.SOAPElement
35 */ 
36    public void setElementRpcOp(SOAPElement element){
37        elementRpcOp = element;
38    }
39    
40    /**
41     * Use the appropriate Soap entry from the property file to create
42     * the QNAME whose value should be the corresponding WSDL entry for 
43     * "operation name" of the bound web service. The "port" and "service"
44     * sections ofthe WSDL should contain this value. 
45     * @return the QName for the Root Node of the XML content inside 
46     * the SOAPBODY. 
47     */
48    public Name setQName(String name){
49        try {
50            return getRequestEnvelope(this.getReqMessage())
51            .createName(name
52//              POProperty.get(
53//                  "soap.rpc.methodname.attachment"
54//              )
55            );
56        } catch (SOAPException e) {
57            // TODO Auto-generated catch block
58            e.printStackTrace();
59            return null;
60        }
61    }
62    public Name setQName(String name, String prefix, String uri){
63        try {
64            return getRequestEnvelope(this.getReqMessage())
65            .createName(
66                name, prefix, uri
67            );
68        } catch (SOAPException e) {
69            // TODO Auto-generated catch block
70            e.printStackTrace();
71            return null;
72        }
73    }   
74/**
75 * 
76 * @return the XML node that corresponds to the Root in the SOAPBODY.
77 * Also, according to SOAP Protocol, this is the 
78 * WSDL Binding sectn's "operation name".
79 */ 
80    public SOAPElement addMethod(String name){
81        try {
82            return
83             getBody()
84            .addBodyElement(
85                setQName(name)              
86            );
87        } catch (SOAPException e) {
88            // TODO Auto-generated catch block
89            e.printStackTrace();
90            return null;
91        }
92    }
93
94
95/**
96 * The mid-ware symantic is hey "i created some data on this client,
97 * in the clients file system, and it's data that is of interest to remote
98 * subscribers." All the SOAP message stuff is to satisfy the protocol but,
99 * this is where the meat and potatoes are because this is where the file 
00 * or the encoded version of the file will be hooked to the SAAJ envelope
01 * for its trip over-the-wire with the message.
02 * @param afile, part of the Collection from the client's call to 
03 * "FileSelector.getFiles."
04 * @return
05 */
06    public AttachmentPart createFileAttachment(File afile){
07        return
08        getReqMessage().createAttachmentPart(
09            new DataHandler(
10                new FileDataSource(
11                    afile               
12                )
13            )
14        );  
15    }
16    
17    /**
18     * <p>The SOAPBody hasa entity, (property with an attibute whose value
19     * is a reference to the actual "DataHandler" attached to the SOAP msg.
20     * according to the rules of JAX-RPC, SOAP, and SAAJ API). The name of 
21     * the property in the xml message is also a parm name in the signature
22     * of the RPC operation over on the server.</p><p>
23     * In addition to this, the message hasa Attachment part which is the
24     * encoded version of the client's file that will be transported to the
25     * Post Office where a different sub-system meets the needs of 
26     * subscribers on the topic associated with the message.</p><p>
27     * For each file that is new, create the xml node holding the refernce
28     * and also create the attachment. Connect the attachment to the message.
29     * @param fil java.io.File
30     */
31//TODO on anymore than 1 file , the "createName' won't be unique in NS
32// you should parm the element that attach ref will be added? 
33// its now hardcode as "getElementRpcOP' so you can only attach the refids here
34// get rid of hard-coded "dh"   
35    public void addAttachment(File fil){
36        AttachmentPart myAttachment = createFileAttachment(fil);
37        getReqMessage().addAttachmentPart(myAttachment);
38        try {
39            getElementRpcOp()
40            .addChildElement(
41                getRequestEnvelope(this.getReqMessage()).createName("dh")
42            )
43            .addAttribute(
44                getRequestEnvelope(this.getReqMessage()).createName("href")
45                , "cid:" + myAttachment.getContentId()
46            );
47        } catch (SOAPException e) {
48            // TODO Auto-generated catch block
49            e.printStackTrace();
50        }
51    }
52    public void addAttachment(File fil, String parm){
53        AttachmentPart myAttachment = createFileAttachment(fil);
54        getReqMessage().addAttachmentPart(myAttachment);
55        try {
56            getElementRpcOp()
57            .addChildElement(
58                getRequestEnvelope(this.getReqMessage()).createName(parm)
59            )
60            .addAttribute(
61                getRequestEnvelope(this.getReqMessage()).createName("href")
62                , "cid:" + myAttachment.getContentId()
63            );
64        } catch (SOAPException e) {
65            // TODO Auto-generated catch block
66            e.printStackTrace();
67        }
68    }
69    
70// pass in file, parent elem "attachments"
71// file to DH
72    
73    public void addAttachment(File fil, SOAPBodyElement element){
74//      AttachmentPart myAttachment = createFileAttachment(fil);
75        addAttachment(
76            new DataHandler(
77                new FileDataSource( 
78                    fil
79                )
80            )
81            ,
82            element
83        );
84    
85    }   
86/**
87 * According to the rules of SOAP, SAAJ, JAXRPC, create the XML node in the
88 * SOAP body that holds a value reference to the actual SAAJ attachment part.
89 * The xml node and its name will be treated as RPC parm by the server-side
90 * interface of the Operation specified in the Root element. A DataHandler obj.
91 * is being used to get the attachment file over-the-wire. So, for now,
92 * this element name is dh. 
93 * NOTE: only one dh is allowed at this point. 
94 * @param name the parm name used by the server-side operation's 
95 *
96 * @param nameVal the "href" to the actual attachment
97 */ 
98    public void addRPCParm ( String name, String nameVal){
99//      SOAPElement ele = getElementRpcOp()     
00        try {
01            getElementRpcOp()
02            .addChildElement(
03                getRequestEnvelope(this.getReqMessage())
04                .createName(name)
05            )
06            .addTextNode(nameVal);
07        } catch (SOAPException e) {
08            // TODO Auto-generated catch block
09            e.printStackTrace();
10        }
11    }
12
13    
14    /**
15     * Post the request that Wraps the SOAP message.  Explain??
16     * Using the AXIS runtime (client-side impl) that uses HTTP/SOAP to 
17     * connect to the URL endpt. on the Server. Server hosts the interface impl. 
18     * of the RPC method or operation.
19     * See 3 property file properties with name like "wsdl.service.addr."
20     * @param message SOAPMessage
21     * @return
22     */
23    public SOAPMessage call ( SOAPMessage message ){
24        try {
25            return getConnection().call(
26                message                             
27                ,
28                    POProperty.get(
29                        "wsdl.service.addr.host"
30                    ) 
31                    + "/" 
32                    + POProperty.get(
33                        "wsdl.service.addr.axis.webapp"
34                    )
35                    + "/" 
36                    + POProperty.get(
37                        "wsdl.service.addr.port.name"
38                    ) 
39            );
40        } catch (SOAPException e) {
41            // TODO Auto-generated catch block
42            e.printStackTrace();
43            return null;
44        }
45    }
46// get the param, set it's ParmDesc
47//   then load it into Array
48    public Object[] setParam(DataHandler[] dh){
49        RPCParam rpcParam = new RPCParam(
50            ""
51            , "attachments"
52            ,dh
53        );
54        rpcParam.setParamDesc(
55        new ParameterDesc(new QName("attachments"),
56                             ParameterDesc.IN,
57                             XMLType.SOAP_ARRAY)
58        );
59        Vector result = new Vector();
60        result.add(rpcParam);       
61        return ( result.toArray() );
62    }
63
64//  get the params (topicname, DH's) set their  ParmDesc's
65//    then load them into Array
66     public Object[] setParams(String topicname,DataHandler[] dh){
67        RPCParam rpcParam = new RPCParam(
68            ""
69            , "topicname"
70            ,topicname
71        );
72        rpcParam.setParamDesc(
73        new ParameterDesc(new QName("topicname"),
74                             ParameterDesc.IN,
75                             XMLType.XSD_STRING)
76        );
77        Vector result = new Vector();
78        result.add(rpcParam);       
79        
80         RPCParam rpcParam2 = new RPCParam(
81             ""
82             , "attachments"
83             ,dh
84         );
85         rpcParam.setParamDesc(
86         new ParameterDesc(new QName("attachments"),
87                              ParameterDesc.IN,
88                              XMLType.SOAP_ARRAY)
89         );
90         result.add(rpcParam2);     
91         return ( result.toArray() );
92     }
93//  Default apache typemapping for OctetStream looks tobe improvement over
94//    base64Bin. Since the mailGateway interface specifies "attachments" 
95//    as InputStream[], this method is used to do the conversion from
96//    one ArrayType to another. 
97//  TODO verify that the implementation is optimal. Look to get the germans
98//    to drive following 2 interfaces into their client portions of code:
99//          javax.mail.internet.MimeMultipart  <-- totally easy
00//          javax.activation.DataHandler        <-- encapsulates MIME type...
01//  Note: for .NET clients it may have to be Arrayofbase64Binary  
02//    each MIME attachment from email gateWy is conver to Steam then load them into Array
03//  Note: see axis utils for re-injecting to MIME on the other side
04//    ref: <axis_root>\org\apache\axis\attachments\MimeUtils.java
05     public Object[] setParams(String topicname, InputStream[] is){
06        LinkedList osList = new LinkedList();       
07        for (int i = 0; i < is.length; i++) {
08          osList.add(this.setOctet(is[i]));
09        }       
10        OctetStream[] osarray = new OctetStream[0];                 
11        return this.setParams(topicname      
12            , (OctetStream[])new ArrayList(osList).toArray(osarray));                   
13    }
14
15//  Demo  version of the OutboundMailGateway uses this for protocol converter
16//  By the time the rpc element is complete, the original collection of  
17//   Mime Attachments is completed conversion into type= 
18//   org.apache.axis.attachments.OctetStream for default bundling in SAAJ API
19     public Object[] setParams(String topicname, OctetStream[] is){
20        RPCParam rpcParam = new RPCParam(
21            ""
22            , "topicnameo"
23            ,topicname
24        );
25        rpcParam.setParamDesc(
26        new ParameterDesc(new QName("topicnameo"),
27                             ParameterDesc.IN,
28                             XMLType.XSD_STRING)
29        );
30        Vector result = new Vector();
31        result.add(rpcParam);       
32        
33         RPCParam rpcParam2 = new RPCParam(
34             ""
35             , "octetstream"
36             ,is
37         );
38         rpcParam.setParamDesc(
39         new ParameterDesc(new QName("octetstream"),
40                              ParameterDesc.IN,
41                              XMLType.SOAP_ARRAY)
42         );
43         result.add(rpcParam2);     
44         return ( result.toArray() );
45     }
46
47     
48//  get the params (topicname, DH's) set their  ParmDesc's
49//    then load them into Array
50     public Object[] setParams(String topicname){
51        RPCParam rpcParam = new RPCParam(
52            ""
53            , "topicname"
54            ,topicname
55        );
56        rpcParam.setParamDesc(
57        new ParameterDesc(new QName("topicname"),
58                             ParameterDesc.IN,
59                             XMLType.XSD_STRING)
60        );
61        Vector result = new Vector();
62        result.add(rpcParam);       
63                 return ( result.toArray() );
64     }
65
66    public DataHandler[] setDH(Collection fileset){
67        LinkedList dhList = new LinkedList();       
68            for ( 
69                Iterator i = fileset.iterator();i.hasNext();
70            ){          
71                dhList.add(
72                    new DataHandler(
73                        new FileDataSource( 
74                            (File)i.next()
75                        )
76                    )
77                );                                      
78            }               
79        DataHandler[] dharray = new DataHandler[0];                 
80        return 
81            (DataHandler[])new ArrayList(dhList).toArray(dharray);      
82    }
83// call this w/     setDHArray(SelectFiles(), attachments    as parms
84// AttachmentPart caution subcls
85//   javax.xml.soap.AttachmentPart
86//      org.apache.axis.attachments | a subcls
87//  addchild "item" to attachments
88//  addattr href cid to item
89//  addattachment dh to message
90
91    public void addAttachment(DataHandler dh, SOAPBodyElement element){
92//      AttachmentPart myAttachment = getMessage()
93//      .createAttachmentPart();
94
95        org.apache.axis.attachments.AttachmentPart 
96        myAttachment = new org.apache.axis.attachments.AttachmentPart(
97            new DataHandler(
98                dh 
99                ,"text/plain"
00            )
01        );
02        getReqMessage().addAttachmentPart(myAttachment);
03        try {
04            element
05            .addChildElement(
06                getRequestEnvelope(this.getReqMessage()).createName("item")
07            )
08            .addAttribute(
09                getRequestEnvelope(this.getReqMessage()).createName("href")
10                , "cid:" + myAttachment.getContentId()
11            );
12        } catch (SOAPException e) {
13        // TODO Auto-generated catch block
14            e.printStackTrace();
15        }   
16        }   
17    /**
18     * what other way is there to handle DataHandler[] as parm??
19     * this seems to work with the attachment sample's "echoDir" operation
20     * where a parm encapsulates ArrayofDataHandlers...
21     * The key was removing the explicit Typ Registration for encoding the
22     * DH array. Just let it default and it seems to work OK on client...
23     * @return
24     */
25    public Call getCall(){
26        try {
27            Call call = (Call)(new Service().createCall());
28            /*Un comment the below statement to do HTTP/1.1 protocol*/
29            //call.setScopedProperty(MessageContext.HTTP_TRANSPORT_VERSION,HTTPConstants.HEADER_PROTOCOL_V11);
30/* rcr removed 5 lines as extraneous
31
32            Hashtable myhttp = new Hashtable();
33            myhttp.put("dddd", "yyy");     //Send extra soap headers
34            myhttp.put("SOAPAction", "dyyy");
35            myhttp.put("SOAPActions", "prova");
36            call.setProperty(HTTPConstants.REQUEST_HEADERS, myhttp);
37            */
38            
39            /*Un comment the below to do http chunking to avoid the need to calculate content-length. (Needs HTTP/1.1)*/
40            //myhttp.put(HTTPConstants.HEADER_TRANSFER_ENCODING, HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED);
41
42            /*Un comment the below to force a 100-Continue... This will cause  httpsender to wait for
43             * this response on a post.  If HTTP 1.1 and this is not set, *SOME* servers *MAY* reply with this anyway.
44             *  Currently httpsender won't handle this situation, this will require the resp. which it will handle.
45             */
46            //myhttp.put(HTTPConstants.HEADER_EXPECT, HTTPConstants.HEADER_EXPECT_100_Continue);
47
48            //Set the target service host and service location,
49            call.setTargetEndpointAddress(
50                new URL(                        
51                    POProperty.get(
52                        "wsdl.service.addr.host"
53                    ) 
54                    + "/" 
55                    + POProperty.get(
56                        "wsdl.service.addr.axis.webapp"
57                    )
58                    + "/" 
59                    + POProperty.get(
60                        "wsdl.service.addr.port.name"
61                    )                       
62                )
63            );
64            //This is the target services method to invoke.
65//TODO hardcode removal use wsdl.service.addr.port.name for valueOf
66//     urn:EchoAttach...            
67            call.setOperationName(
68                new QName(
69                    "urn:EchoAttachmentsService"
70                    , 
71                    POProperty.get(
72                        "soap.rpc.methodname.attachment"
73                    )
74                )
75            );
76                        
77//          Add serializer for attachment.
78/* rcr tst byp          call.registerTypeMapping(
79                Class.forName(
80                    "javax.activation.DataHandler"
81                )
82                ,  
83                new QName(
84                    "urn:EchoAttachmentsService"
85                    , "DataHandler"
86                )                                    
87                , JAFDataHandlerSerializerFactory.class
88                , JAFDataHandlerDeserializerFactory.class
89            ); // end registerType
90            */
91            // argname for serverside method is the parm here
92            call.addParameter(
93                "attachments"
94                , XMLType.SOAP_ARRAY // new XMLType(qnameAttachment),
95                ,ParameterMode.IN
96            ); //Add the file.
97            call.setReturnType(XMLType.SOAP_ARRAY); // new XMLType(qnameAttachment));
98/* rcr tst byp          call.setProperty(
99                Call.ATTACHMENT_ENCAPSULATION_FORMAT
00                , Call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME
01            );
02            */
03            return call;                                         
04            
05        } catch (ServiceException e) {
06            // TODO Auto-generated catch block
07            e.printStackTrace();
08        }
09        catch (MalformedURLException e) {
10            // TODO Auto-generated catch block
11            e.printStackTrace();
12        }
13        return null;
14    }
15    /**
16     * <p>Make the call to the WS endpt and operation specified in the props
17     * file directives ( soap.wsdl.url, soap.rpc.methodname )
18     * Note that serverside method "echoDir" expects a DataHandler[] typ parm.
19     * </p><p>Using an intermediate List form , convert collection of file(s)
20     *  returned by an earlier call to "FileSelector.getFiles()" to an Array  
21     * of DataHandlers because this is acceptible struct. for auto-encoding 
22     * by JAX-RPC runtime...
23     * Invoke the Service...
24     * @param fileset Collection of files that will be loaded in Array of DH's
25     * @param argcal The DII "call" that will get invoked
26     * @return the "Response type" of the WS and the return type of the operation
27     *   that's being invoked...
28     */
29    public Object diiCall(Collection fileset, Call argcal){
30                                
31        LinkedList dhList = new java.util.LinkedList();     
32        for ( 
33            Iterator i = fileset.iterator();i.hasNext();
34        ){          
35            dhList.add(
36                new DataHandler(
37                    new FileDataSource( 
38                        (File)i.next()
39                    )
40                )
41            );                                      
42        }
43        try {
44            DataHandler[] dharray = new DataHandler[0]; 
45            return argcal.invoke(
46                new Object[]{
47                   new ArrayList(dhList).toArray(dharray)
48                }
49            );
50        } catch (RemoteException e) {
51            // TODO Auto-generated catch block
52            e.printStackTrace();
53        }
54        return new Object();
55    }
56    
57    public void close(){
58        try {
59            getConnection().close();
60        } catch (SOAPException e) {
61            // TODO Auto-generated catch block
62            e.printStackTrace();
63        }   
64    }
65
66    public void setTypeMappingRegistry() {
67         TypeMappingRegistry tmr = null;
68         TypeMapping tm = null;
69  
70      
71        tmr = new TypeMappingRegistryImpl();
72
73        // Gets / Creates the TypeMapping instance
74        String encodingStyle = Constants.URI_DEFAULT_SOAP_ENC;
75        tm = (TypeMapping) tmr.getTypeMapping(encodingStyle);
76        TypeMapping df = (TypeMapping) tmr.getDefaultTypeMapping();
77        
78        Class[] myclass = df.getAllClasses();
79    
80        for ( int j = 0
81            ;j < myclass.length ;
82            j++
83            ){
84                log.debug(
85                    "mapd : "
86                    + myclass[j].getName()
87                    + " "
88                    +df.getTypeQName(myclass[j]).toString()
89                    + " "
90                    +df.getSerializer(myclass[j])
91                    )
92                ;               
93            }   
94        
95    /*  if (tm == null || tm == df) {
96          tm = (TypeMapping) tmr.createTypeMapping();
97          tm.setSupportedEncodings(new String[] {encodingStyle});
98          tmr.register(encodingStyle, tm);
99        }
00        */
01      
02    }
03    private OctetStream setOctet(InputStream is){
04        BufferedInputStream bis = new BufferedInputStream(is);
05        OctetStream out = new OctetStream();
06
07          byte[] buf = new byte[20 * 1024];  // 20K buffer for .xls in j/1_2/docs
08          int bytesRead;
09          try {
10            while ((bytesRead = bis.read(buf)) != -1) {
11                out.setBytes(buf);
12              }
13        } catch (IOException e) {
14            // TODO Auto-generated catch block
15            e.printStackTrace();
16        }
17        return out;
18    }
19    
20    
21    //TODO need to get the 4 modes of connection split out in seperate
22    // classes , all impls. of the same interface
23    //  soapsingleImpl, diiImpl, soapArrayImpl 
24    //A point-to-point connection SoapConnection - soapconnection
25    //JAXRPC Dynamic Invoation Interface implementation of the Service - diiservice
26    //#ws.invocation.typ=soapconnection
27    //ws.invocation.typ=diiservice  arg0=tm1*
28    // file name and endpt are the args
29    // F:\\axis-1_1RC2\\samples\\attachments\\build.xml
30    //http://localhost:8080/axis/services/urn:EchoAttachmentsService
31    // use diiservice for operation with DataHandler[] as parm
32    public static void main(String[] args) {
33        SAAJCallMgr myMgr= new SAAJCallMgr();
34//      myMgr.setMessageContext(
35//          MessageContext.getCurrentContext()
36//      );
37        myMgr.setMessageContext(
38            new MessageContext(
39                new Service().getEngine()
40                )
41        );
42        
43        if (
44            POProperty.get(
45                "ws.invocation.typ"
46            ).equalsIgnoreCase("soapconnection")
47        ) {
48        try {
49            myMgr.setConnection(
50                SOAPConnectionFactoryImpl.newInstance()
51                .createConnection()
52            );
53            myMgr.setReqMessage(
54
55                (Message)MessageFactoryImpl.newInstance().createMessage()
56            );
57        } catch (UnsupportedOperationException e) {
58            // TODO Auto-generated catch block
59            e.printStackTrace();
60        } catch (SOAPException e) {
61            // TODO Auto-generated catch block
62            e.printStackTrace();
63        }
64
65        myMgr.setElementRpcOp(myMgr.addMethod("echo"));
66        log.debug("RpcOp as element " + myMgr.getElementRpcOp().toString());
67//      myMgr.addRPCParm("topicaction","publish");
68//      myMgr.addRPCParm("topicname","testattachment");     
69        for ( Iterator i = 
70                FileSelector.getFiles(args[0]).iterator() ;
71            i.hasNext();
72        ){
73            myMgr.addAttachment(
74                (File)i.next()
75                , "dh"
76            );              
77        }
78//TODO remove 2nd file name for test of dh2 and 2nd parm
79  for ( Iterator i = 
80          FileSelector.getFiles(args[1]).iterator() ;
81      i.hasNext();
82  ){
83      myMgr.addAttachment(
84          (File)i.next()
85          , "dh2"
86      );                
87  }     
88        myMgr.call(myMgr.getReqMessage());
89        myMgr.close();
90    }else if (
91        POProperty.get(
92            "ws.invocation.typ"
93        ).equalsIgnoreCase("diiservice")
94    )
95    {
96        Object ret = myMgr.diiCall(
97            FileSelector.getFiles(args[0])
98            ,
99            myMgr.getCall()
00        );
01//      myMgr.close();  rcr causing error 6/29
02    }
03    // this option doesn't work due to illegal parm being thrown at
04    // mysoapmessage.createAttachmentPart(dhset[] , cType)
05    else if (
06            POProperty.get(
07                "ws.invocation.typ"
08            ).equalsIgnoreCase("soaparrayofdhattach") 
09        )
10        {
11            // rcr test check typemapping for default serialization
12            myMgr.setTypeMappingRegistry();
13            try {
14                myMgr.setConnection(
15                    SOAPConnectionFactoryImpl.newInstance()
16                    .createConnection()
17                );
18                myMgr.setReqMessage(
19                    (Message)MessageFactoryImpl.newInstance().createMessage()
20                );
21                    
22            
23//              myMgr.setElementRpcOp(myMgr.addMethod("echoDir"));
24                RPCElement myRpcEl =    
25                new RPCElement(
26                    "urn:EchoAttachmentsService"
27                    ,"echoDir"
28                    ,myMgr.setDH(
29                        FileSelector.getFiles(
30                            args[0]
31                        )
32                    )
33                );
34                log.debug("using encd styl : "+
35                myMgr.getMessageContext(                        
36                    ).getSOAPConstants().getEncodingURI());
37                myRpcEl.setEncodingStyle(
38                    myMgr.getMessageContext(                        
39                    ).getSOAPConstants().getEncodingURI()
40                );
41                myRpcEl.setParentElement(myMgr.getBody());
42//              ).setParentElement(myMgr.getElementRpcOp());
43
44            } catch (SOAPException e) {
45                // TODO Auto-generated catch block
46                e.printStackTrace();
47            }                                                                               
48            myMgr.call(myMgr.getReqMessage());
49            myMgr.close();          
50        }
51        
52// in order to replace diiCall with a more static form of:
53// getConnection().call(amessage
54// provide re-impl of the code found in cls=
55//      org.apache.axis.client.Call.invoke(RPCElement) and in
56//      org.apache.axis.client.Call.invoke()
57//Note that the key to re-impl is using the RPCElement 
58//   built from Array of RPCParams
59// Note that this array contains the parameter(s) expected by the operation
60//  that is the target of the Service Call ie the server side method...
61        
62        else if (
63                POProperty.get(
64                    "ws.invocation.typ"
65                ).equalsIgnoreCase("soapconnparms") 
66            )
67// get new  envelope that will hold all attachments
68            myMgr.setRequestEnvelope(
69                new SOAPEnvelope(
70                    myMgr.getMessageContext().getSOAPConstants()
71                    ,myMgr.getMessageContext().getSchemaVersion()
72                )
73            );
74 
75// get new element with FileSet to DataHandler[] to RPCParam[]
76            RPCElement myRpcEl =    
77            new RPCElement(
78                "urn:EchoAttachmentsService"
79                ,"echoDir"
80                ,myMgr.setParam(                
81                    myMgr.setDH(
82                        FileSelector.getFiles(
83                            args[0]
84                        )
85                    )
86                )               
87            );          
88            log.debug("using encd styl : "+
89            myMgr.getMessageContext(                        
90                ).getSOAPConstants().getEncodingURI());
91            try {
92                myRpcEl.setEncodingStyle(
93                    myMgr.getMessageContext(                        
94                    ).getSOAPConstants().getEncodingURI()
95                );
96            } catch (SOAPException e) {
97                // TODO Auto-generated catch block
98                e.printStackTrace();
99            }
00// add attachments to envelope
01            myMgr.getRequestEnvelope().addBodyElement(myRpcEl);
02            myMgr.getRequestEnvelope().setMessageType(Message.REQUEST);         
03            try {
04                myMgr.getMessageContext().setTargetService(
05                    myMgr.getRequestEnvelope()
06                    .getFirstBody()
07                    .getNamespaceURI()
08                );              
09                myMgr.setConnection(
10                    SOAPConnectionFactoryImpl.newInstance()
11                    .createConnection()
12                );              
13            } catch (AxisFault e1) {
14                // TODO Auto-generated catch block
15                e1.printStackTrace();
16            } catch (UnsupportedOperationException e) {
17                // TODO Auto-generated catch block
18                e.printStackTrace();
19            } catch (SOAPException e) {
20                // TODO Auto-generated catch block
21                e.printStackTrace();
22            }
23//  call on the connection with parm of new message
24            myMgr.setReqMessage(
25                new Message(
26                    myMgr.getRequestEnvelope()
27                )
28            );
29            myMgr.getReqMessage().setMessageContext(
30                myMgr.getMessageContext()
31            );
32            myMgr.call(myMgr.getReqMessage());
33            myMgr.close();          
34            }
35        
36    static 
37    {
38        log = Logger.getLogger((SAAJCallMgr.class).getName());  
39        ClassLoader cl = SAAJCallMgr.class.getClassLoader();
40        PropertyConfigurator.configure(cl.getResource(
41            "config/log4j.properties"));
42    }
43    }
44