All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.rpc.client.dii.CallInvocationHandler Maven / Gradle / Ivy

/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.xml.rpc.client.dii;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.rpc.Call;
import javax.xml.rpc.Stub;
import javax.xml.rpc.holders.Holder;

import com.sun.xml.rpc.client.StubPropertyConstants;
import com.sun.xml.rpc.soap.streaming.SOAPNamespaceConstants;
import com.sun.xml.rpc.util.Holders;
import com.sun.xml.rpc.util.exception.LocalizableExceptionAdapter;

/**
 * @author JAX-RPC Development Team
 */
public class CallInvocationHandler implements InvocationHandler, Stub {
    private static final Set recognizedProperties;

    private Map callMap = new HashMap();
    private Map properties = new HashMap();
    private Class portInterface;

    static {
        Set temp = new HashSet();
        temp.add(USERNAME_PROPERTY);
        temp.add(PASSWORD_PROPERTY);
        temp.add(ENDPOINT_ADDRESS_PROPERTY);
        temp.add(SESSION_MAINTAIN_PROPERTY);
        temp.add(StubPropertyConstants.HTTP_COOKIE_JAR);
        recognizedProperties = Collections.unmodifiableSet(temp);
    }

    //InvocationHandler for the Dynamic Proxy
    CallInvocationHandler(Class portInterface) {
        this.portInterface = portInterface;
    }

    //add the call and store in the call map keyed by Method
    public void addCall(Method key, Call call) {
        callMap.put(key, call);
    }

    public Call getCall(Method key) {
        return (Call) callMap.get(key);
    }

    //does a sanity check and makes sure configured call actually
    //exists in the java methods declaring class
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Exception {
        if (portInterface.equals(method.getDeclaringClass())) {
            Call call = getCall(method);
            if (call == null) {
                String knownMethodNames = "";
                Iterator eachKnownMethod = callMap.keySet().iterator();
                while (eachKnownMethod.hasNext()) {
                    Method knownMethod = (Method) eachKnownMethod.next();
                    knownMethodNames += "\n" + knownMethod.getName();
                }
                throw new DynamicInvocationException("dii.dynamicproxy.method.unrecognized",
                        new Object[]{
                            method != null ? method.getName() : null,
                            knownMethodNames});
            }
            //good it checks out ok do it
            return doCall(call, args);
        } else {
            //this method isn't in the port interface
            //invoke anyway
            return doNonPort(method, args);
        }
    }

    protected Object doCall(Call call, Object[] args) throws RemoteException {
        //if no args just make Object so we don't get NPE
        if (args == null) {
            args = new Object[0];
        }

        //process holders
        Holder[] holders = new Holder[args.length];
        int[] holderLocations = new int[args.length];

        int lastHolderIndex = 0;
        for (int i = 0; i < args.length; i++) {
            Object arg = args[i];
            if (arg instanceof Holder) {
                Holder holderArg = (Holder) arg;
                //get the holder arg location
                holderLocations[lastHolderIndex] = i;
                //save the holder argument
                holders[lastHolderIndex] = holderArg;
                //get the value of the holder and
                //set as argument
                args[i] = Holders.getValue(holderArg);

                ++lastHolderIndex;
            }
        }

        //invoke BasicCall.invoke(args)
        Object returnValue = call.invoke(args);

        //we got the return value, let's get other out values
        //and set the appropriate holder with the returned value
        if (lastHolderIndex > 0) {
            List outputValues = call.getOutputValues();
            Iterator eachOutputValue = outputValues.iterator();
            int holderIndex = 0;
            while (eachOutputValue.hasNext()) {
                Object outParameter = eachOutputValue.next();

                int holderLocation = holderLocations[holderIndex];
                Holder holder = holders[holderIndex];
                Holders.setValue(holder, outParameter);
                args[holderLocation] = holder;

                ++holderIndex;
            }
        }
        return returnValue;
    }

    protected Object doNonPort(Method method, Object[] args) {
        //use reflection to invoke this unknown method
        try {
            return method.invoke(this, args);
        } catch (Exception e) {
            throw new DynamicInvocationException("dii.exception.nested",
                    new LocalizableExceptionAdapter(e));
        }
    }

    public void _setProperty(String name, Object value) {
        if (!recognizedProperties.contains(name)) {
            throw new IllegalArgumentException("Call object does not recognize property: " + name);
        }

        properties.put(name, value);

        setPropertyOnCallObjects(name, value);
    }

    public Object _getProperty(String name) {
        return properties.get(name);
    }

    public Iterator _getPropertyNames() {
        return properties.keySet().iterator();
    }

    private void setPropertyOnCallObjects(String propertyName, Object value) {
        for (Iterator eachCall = callMap.values().iterator();
             eachCall.hasNext();
                ) {

            Call call = (Call) eachCall.next();

            if (Stub.ENDPOINT_ADDRESS_PROPERTY.equals(propertyName)) {
                call.setTargetEndpointAddress((String) value);
            } else {
                call.setProperty(propertyName, value);
            }
        }
    }

    //used by streaming sender and callInvokerImpl during invocation
    // - do not remove
    public String _getDefaultEnvelopeEncodingStyle() {
        return null;
    }

    public String _getImplicitEnvelopeEncodingStyle() {
        return "";
    }

    public String _getEncodingStyle() {
        return SOAPNamespaceConstants.ENCODING;
    }

    public void _setEncodingStyle(String encodingStyle) {
        throw new UnsupportedOperationException("cannot set encoding style");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy