/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.remoting.transport.soap.axis;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Map;

import javax.xml.rpc.ServiceException;

import org.jboss.remoting.ConnectionFailedException;
import org.jboss.remoting.InvokerLocator;
import org.jboss.remoting.RemoteClientInvoker;

/**
 * SOAPClientInvoker is the client side invoker to a remote SOAP transport
 *
 * @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
 * @version $Revision: 1.5.2.1 $
 */
public class SOAPClientInvoker extends RemoteClientInvoker
{
    private AxisSOAPConnector connector;

    public SOAPClientInvoker (InvokerLocator locator)
    {
        super (locator );
    }

    /**
     * subclasses must implement this method to provide a hook to connect to the remote server, if this applies
     * to the specific transport. However, in some transport implementations, this may not make must difference since
     * the connection is not persistent among invocations, such as SOAP.  In these cases, the method should
     * silently return without any processing.
     *
     * @throws org.jboss.remoting.ConnectionFailedException
     */
    protected void handleConnect ()
            throws ConnectionFailedException
    {
        try
        {
            URL serviceURL = new URL("http://"+locator.getHost()+(locator.getPort()>0?(":"+locator.getPort()):"")+"/axis/services/AxisSOAPConnector");
            AxisSOAPConnectorService service = new AxisSOAPConnectorServiceLocator();
            connector = service.getAxisSOAPConnector(serviceURL);
            Map params = locator.getParameters();
            int timeout = 30000;
            if (params!=null)
            {
                String t = (String)params.get("timeout");
                if (t!=null)
                {
                    timeout = Integer.parseInt(t);
                }
            }
            ((AxisSOAPConnectorSoapBindingStub) connector).setTimeout(timeout);
        }
        catch ( MalformedURLException e )
        {
            throw new ConnectionFailedException(e.getMessage());
        }
        catch (ServiceException se)
        {
            throw new ConnectionFailedException(se.getMessage());
        }

    }

    /**
     * subclasses must implement this method to provide a hook to disconnect from the remote server, if this applies
     * to the specific transport. However, in some transport implementations, this may not make must difference since
     * the connection is not persistent among invocations, such as SOAP.  In these cases, the method should
     * silently return without any processing.
     */
    protected void handleDisconnect ()
    {
    }

    /**
     * called to transport the marshalled invocation to the remote destination, and receive
     * back the marshalled invocation bytes back. this method allows the subclass to provide the
     * specific mechanism, protocol, etc. for delivering and returning remote invocations in a
     * transport-specific way.
     *
     * @param sessionId session id to pass along
     * @param buffer  buffer of the serialized method invocation to send to the server
     * @return result of the method invocation as serialized bytes
     * @throws java.io.IOException fatal exception should only be raised in the case the transport write fails (but is still a valid connection)
     * @throws org.jboss.remoting.ConnectionFailedException this exception is raised in the case the remote side is no longer available
     */
    protected byte[] transport ( String sessionId, byte buffer[] )
            throws IOException, ConnectionFailedException
    {
        if (isConnected()==false)
        {
            connect();
        }
        try
        {
            return connector.transport(buffer);
        }
        catch ( RemoteException e )
        {
            throw new ConnectionFailedException(e.getMessage());
        }
        catch ( IOException e )
        {
            throw new ConnectionFailedException(e.getMessage());
        }
    }
}
