package org.seasar.remoting.axis.connector;

import java.lang.reflect.Method;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;

import org.apache.axis.encoding.TypeMappingRegistry;
import org.apache.axis.enum.Use;
import org.seasar.remoting.axis.S2AxisConstants;
import org.seasar.remoting.axis.encoding.AutoRegisterTypeMappingImpl;
import org.seasar.remoting.common.connector.impl.TargetSpecificURLBasedConnector;

/**
 * Webサービスを呼び出すコネクタの実装クラスです。
 * 
 * @author koichik
 */
public class AxisConnector extends TargetSpecificURLBasedConnector {
    protected Service service;

    /**
     * Axisサービスを設定します。
     * 
     * @param service
     *            Axisサービス
     */
    public void setService(final Service service) {
        this.service = service;

        final TypeMappingRegistry tmr = (TypeMappingRegistry) service.getTypeMappingRegistry();
        if (!(tmr.getTypeMapping(Use.DEFAULT.getEncoding()) instanceof AutoRegisterTypeMappingImpl)) {
            final AutoRegisterTypeMappingImpl autoTM = new AutoRegisterTypeMappingImpl(null);
            tmr.register(Use.DEFAULT.getEncoding(), autoTM);
        }
    }

    /**
     * Axisサービスを使用してリモートメソッドの呼び出しを実行し、その結果を返します。
     * 
     * @param targetURL
     *            リモートオブジェクトのURL
     * @param method
     *            呼び出すメソッド
     * @param args
     *            リモートオブジェクトのメソッド呼び出しに渡される引数値を格納するオブジェクト配列
     * @return リモートオブジェクトに対するメソッド呼び出しからの戻り値
     * @throws Throwable
     *             リモートオブジェクトに対するメソッド呼び出しからスローされる例外
     */
    protected Object invoke(final URL targetURL, final Method method, final Object[] args)
            throws Throwable {
        final Call call = service.createCall();
        call.setTargetEndpointAddress(targetURL.toString());
        call.setOperationName(new QName(S2AxisConstants.OPERATION_NAMESPACE_URI, method.getName()));
        return call.invoke(args);
    }
}