FileDocCategorySizeDatePackage
OperationImpl.javaAPI DocphoneME MR2 API (J2ME)18816Wed May 02 18:00:34 BST 2007com.sun.j2mews.xml.rpc

OperationImpl

public class OperationImpl extends Operation
The OperationImpl class is an implementation of the javax.microedition.xml.rpc.Operation class, corresponding to a wsdl:operation defined for a target service endpoint.
version
0.1

Fields Summary
private static String[]
cookies
HTTP Sessions are implemented through the use of cookies. Since a "session" would involve likely more than one Operation, the set of cookies for all known sessions is made static across all Operations. The cookies array is implemented like the properties array - as a set of tuples. The first value being the endpoint address which started the session, the second value being the cookie for the session (i.e., cookie 0 is represented by the endpoint at index 0, and the cookie string at index 1).
private static int
cookieIndex
The index of the next available entry in the cookie set. Since cookies are tuples, the algorithm (cookieIndex / 2) will yield the number of properties stored in the set.
private String[]
properties
The set of properties set by the setProperty method. Each property is a tuple, represented by two sequential entries in the array (i.e., property 0 is represented by the key at index 0, and the value at index 1)
private int
propertyIndex
The index of the next available entry in the property set. Since properties are tuples, the algorithm (propertyIndex / 2) will yield the number of properties stored in the set.
private SOAPEncoder
encoder
The Encoder to use when encoding communications to Web Services
private SOAPDecoder
decoder
The Decoder to use when decoding communications from Web Services
private QName
name
The QName of this operation
private Element
inputType
The Type of the input parameter to this Operation
private Element
returnType
The Type of the output parameter to this Operation
private FaultDetailHandler
faultHandler
The handler to provide the decoding information for custom fault details
private boolean
resourceMoved
A flag indicating the the object was moved (i.e. 3xx HTTP response was received) and we have to retry the operation using a new location
Constructors Summary
public OperationImpl(QName name, Element input, Element output)
Default constructor matches that of Operation

param
name the QName of this Operation
param
input the input Type for this Operation
param
output the output Type for this Operation


                                      
          
         
    
        this.name = name;
        this.inputType = input;
        this.returnType = output;

        this.encoder = new SOAPEncoder();
        this.decoder = new SOAPDecoder();
    
public OperationImpl(QName name, Element input, Element output, FaultDetailHandler faultDetailHandler)
Default constructor matches that of Operation

param
name the QName of this Operation
param
input the input Type for this Operation
param
output the output Type for this Operation
param
faultDetailHandler the handler which will return the type descriptor for a custom fault detail this operation may encounter

        this.name = name;
        this.inputType = input;
        this.returnType = output;
        this.faultHandler = faultDetailHandler;

        this.encoder = new SOAPEncoder();
        this.decoder = new SOAPDecoder();
    
Methods Summary
private static synchronized voidaddSessionCookie(java.lang.String endpoint, java.lang.String cookie)
Adds a cookie to identify this session. Please refer to the section 13.2 of the JAX-RPC 1.1 spec.

param
endpoint an address to associate with the given cookie
param
cookie a cookie identifying the session

        if (endpoint == null || cookie == null) {
            return;
        }

        // We strip off everything after the name=value info
        int i = cookie.indexOf(";");
        if (i > 0) {
            cookie = cookie.substring(0, i);
        }

        // Before appending, check to see if we are modifying
        // a previous key/value pair
        if (cookies != null) {
            for (i = 0; i < cookieIndex; i += 2) {
                if (cookies[i].equals(endpoint)) {
                    cookies[i + 1] = cookie;
                    return;
                }
            }
        }

        // If cookies not instantiated yet, start out with '
        // room to hold 5 cookies (5 * 2 entries = 10)
        if (cookies == null) {
            cookies = new String[10];

        // If cookies is full, re-size with room for another
        // 5 cookies
        } else if (cookieIndex == cookies.length) {
            String[] newCookies = new String[cookies.length + 10];
            System.arraycopy(cookies, 0, newCookies, 0, cookies.length);
            cookies = null;
            cookies = newCookies;
        }

        cookies[cookieIndex++] = endpoint;
        cookies[cookieIndex++] = cookie;

        // cookieIndex is left pointing at the next available
        // entry in the cookie list
    
private java.lang.StringgetProperty(java.lang.String key)
Internal utility method to retrieve a property value from the property set

param
key the property identifier
return
the string value of the property

        if (properties != null) {
            for (int i = 0; i < (properties.length - 2); i += 2) {
                if (properties[i] == null) {
                    return null;
                }
                if (properties[i].equals(key)) {
                    return properties[i + 1];
                }
            }
        }
        return null;
    
private static synchronized java.lang.StringgetSessionCookie(java.lang.String endpoint)
Look through the set of session cookies, and return the one that matches the current endpoint address of this Operation, if any.

param
endpoint address of this Operation
return
the session cookie for this Operation's endpoint address, or null if there is no session cookie

        if (cookies != null) {
            for (int i = 0; i < (cookies.length - 2); i += 2) {
                if (cookies[i] == null) {
                    return null;
                }
                if (cookies[i].equals(endpoint)) {
                    return cookies[i + 1];
                }
            }
        }
        return null;
    
public java.lang.Objectinvoke(java.lang.Object params)
Invokes the wsdl:operation defined by this Operation and returns the result.

param
params a ValueType array representing the input parameters for this Operation. Can be null if this operation takes no parameters.
return
a ValueType array representing the output value(s) for this operation. Can be null if this operation returns no value.
throws
JAXRPCException
  • if an error occurs while excuting the operation.
see
javax.microedition.xml.rpc.Operation

        HttpConnection http = null;
        OutputStream ostream = null;
        InputStream istream = null;
        Object result = null;
        int attempts = 0;
        // Maximal number of "Object moved" http responses that we will handle
        final int maxAttempts = Constants.MAX_REDIRECT_ATTEMPTS;

        try {
            do {
                // This flag will be set to 'true' by setupResStream() method
                // if code 3xx is returned by the http connection.
                resourceMoved = false;

                // open stream to service endpoint
                http = (HttpConnection)Connector.open(
                    getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY));

                ostream = setupReqStream(http);

                // IMPL NOTE: encoding should be either UTF-8 or UTF-16
                encoder.encode(params, inputType, ostream, null);

                if (ostream != null) {
                    ostream.close();
                }

                istream = setupResStream(http);

                if (returnType != null && istream != null) {
                    result = decoder.decode(returnType,
                                            istream,
                                            http.getEncoding(),
                                            http.getLength());
                }

                if (http != null) {
                    http.close();
                }
                if (istream != null) {
                    istream.close();
                }

            } while (resourceMoved && (attempts++ < maxAttempts));

            if (resourceMoved) {
                throw new JAXRPCException("Too many redirections");
            }

            return result;

        } catch (Throwable t) {
            // Debug Line

            if (ostream != null) {
                try {
                    ostream.close();
                } catch (Throwable t2) { }
            }
            if (istream != null) {
                try {
                    istream.close();
                } catch (Throwable t3) { }
            }
            if (http != null) {
                try {
                    http.close();
                } catch (Throwable t1) { }
            }
            // Re-throw whatever error/exception occurs as a new
            // JAXRPCException
            if (t instanceof JAXRPCException) {
                throw (JAXRPCException)t;
            } else {
                if (t instanceof MarshalException ||
                    t instanceof ServerException ||
                        t instanceof FaultDetailException) {
                    throw new JAXRPCException(t);
                } else {
                    throw new JAXRPCException(t.toString());
                }
            }
        }
    
public voidsetProperty(java.lang.String name, java.lang.String value)
Sets the property name to the value, value.

param
name the name of the property to be set
param
value the value the property is to be set
throws
IllegalArgumentException
  • if an error occurs setting the property

        // disallow any null key or value data
        if (name == null || value == null) {
            throw new IllegalArgumentException();
        } else if (
            !name.equals(Stub.ENDPOINT_ADDRESS_PROPERTY) &&
            !name.equals(Stub.PASSWORD_PROPERTY) &&
            !name.equals(Stub.USERNAME_PROPERTY) &&
            !name.equals(Stub.SESSION_MAINTAIN_PROPERTY) &&
            !name.equals(Operation.SOAPACTION_URI_PROPERTY))
        {
            throw new IllegalArgumentException();
        }

        // Before appending, check to see if we are modifying
        // a previous key/value pair
        if (properties != null) {
            for (int i = 0; i < propertyIndex; i += 2) {
                if (properties[i].equals(name)) {
                    properties[i + 1] = value;
                    return;
                }
            }
        }

        // If properties not instantiated yet, start out with '
        // room to hold 5 properties (5 * 2 entries = 10)
        if (properties == null) {
            properties = new String[10];

        // If properties is full, re-size with room for another
        // 5 properties
        } else if (propertyIndex == properties.length) {
            String[] newProps = new String[properties.length + 10];
            System.arraycopy(properties, 0, newProps, 0, properties.length);
            properties = null;
            properties = newProps;
        }

        properties[propertyIndex++] = name;
        properties[propertyIndex++] = value;

        // propertyIndex is left pointing at the next available
        // entry in the property list
    
protected java.io.OutputStreamsetupReqStream(HttpConnection http)
Method to configure the HTTP request stream. This method will do whatever mechanics are necessary to utilize the HTTP connection object to return an output stream to be utilized to send the HTTP request.

param
http the HttpConnection object, unopened, with no headers or any configuration yet set
return
an OutputStream which can be used to write the request data to this HTTP request.

        http.setRequestMethod(HttpConnection.POST);
        http.setRequestProperty("User-Agent",
            "Profile/MIDP-1.0 Configuration/CLDC-1.0");
        http.setRequestProperty("Content-Language", "en-US");
        http.setRequestProperty("Content-Type", "text/xml");

        String soapAction = getProperty(Operation.SOAPACTION_URI_PROPERTY);
        if (soapAction == null || "".equals(soapAction)) {
            soapAction = "\"\"";
        } else {
            if (!soapAction.startsWith("\"")) {
                soapAction = "\"" + soapAction;
            }
            if (!soapAction.endsWith("\"")) {
                soapAction = soapAction + "\"";
            }
        }

        http.setRequestProperty("SOAPAction", soapAction);

        String useSession = getProperty(Stub.SESSION_MAINTAIN_PROPERTY);
        if (useSession != null && useSession.toLowerCase().equals("true")) {
            String cookie = getSessionCookie(
                getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY));
            if (cookie != null) {
                http.setRequestProperty("Cookie", cookie);
            }
        }

        String s1 = getProperty(Stub.USERNAME_PROPERTY);
        String s2 = getProperty(Stub.PASSWORD_PROPERTY);
        if (s1 != null && s2 != null) {
            byte[] encodeData = (s1 + ":" + s2).getBytes();
            http.setRequestProperty("Authorization", "Basic " +
                Base64.encode(encodeData, 0, encodeData.length));
        }
        return http.openOutputStream();
    
protected java.io.InputStreamsetupResStream(HttpConnection http)
Method to configure the HTTP response stream. This method will do whatever mechanics are necessary to utilize the HTTP connection object to return an input stream to the HTTP response.

param
http the HttpConnection object, already opened and presumably with response data waiting
return
an InputStream corresponding to the response data from this HttpConnection or null if not available.

        int response = http.getResponseCode();

        if (response == HttpConnection.HTTP_MOVED_PERM ||
                response == HttpConnection.HTTP_MOVED_TEMP) {
            // Resource was moved, get a new location and retry the operation
            String newLocation = http.getHeaderField("Location");
            setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, newLocation);
            resourceMoved = true;
            return null;
        }

        InputStream input = http.openInputStream();

        if (response == HttpConnection.HTTP_OK) {

            // Catch any session cookie if one was set
            String useSession = getProperty(Stub.SESSION_MAINTAIN_PROPERTY);
            if (useSession != null && useSession.toLowerCase().equals("true"))
            {
                String cookie = http.getHeaderField("Set-Cookie");
                if (cookie != null) {
                    addSessionCookie(
                        getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY), cookie);
                }
            }

            return input;
        } else {
            Object detail = decoder.decodeFault(faultHandler,
                                                input,
                                                http.getEncoding(),
                                                http.getLength());

            if (detail instanceof String) {
                if (((String)detail).indexOf("DataEncodingUnknown") != -1) {
                    throw new MarshalException((String)detail);
                } else {
                    throw new ServerException((String)detail);
                }
            } else {
                Object[] wrapper = (Object[])detail;
                String message = (String)wrapper[0];
                QName name = (QName)wrapper[1];
                detail = wrapper[2];
                throw new JAXRPCException(message,
                    new FaultDetailException(name, detail));
            }
        }