/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.mx.remote.connector.soap.axis;
import org.apache.axis.AxisFault;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.message.SOAPBodyElement;
import org.apache.axis.transport.http.SimpleAxisServer;
import org.apache.axis.utils.Messages;
import javax.xml.rpc.ServiceException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.rmi.RemoteException;
import java.util.Vector;
/**
* This is the actual SOAP service engine that will accept the SOAP request from clients
* remote on the network. The entire SOAP service/server is embedded here. Also, all
* deployment/undeployment happens here as well.
*
* @author <a href="telrod@e2technologies.net">Tom Elrod</a>
*/
//TODO -TME JavaDoc
public class AxisSOAPServer
{
public static final int DEFAULT_PORT = 80;
private SimpleAxisServer soapServer;
//TODO -TME Need to make this configurable
private int port = DEFAULT_PORT;
/**
* Create the soap service listening on DEFAULT_PORT.
* @throws IOException Thrown if can not create socket on DEFAULT_PORT.
*/
public AxisSOAPServer() throws IOException
{
init();
}
/**
* Create the soap service listening on DEFAULT_PORT.
* @throws IOException Thrown if can not create socket on port specified.
*/
public AxisSOAPServer(int port) throws IOException
{
this.port = port;
init();
}
private void init() throws IOException
{
soapServer = new SimpleAxisServer();
ServerSocket svrSocket = null;
// Try five times
for(int i = 0; i < 5; i++)
{
try
{
svrSocket = new ServerSocket(port);
break;
}
catch(IOException e)
{
if(i < 4)
{
// At 3 second intervals.
try
{
Thread.sleep(3000);
}
catch(InterruptedException e1)
{
e1.printStackTrace();
}
}
else
{
System.err.println("unableToStartServer on port " + port);
throw e;
}
}
}
soapServer.setServerSocket(svrSocket);
}
private URL createServiceURL(String serviceName) throws MalformedURLException
{
String localhost = null;
URL serviceURL = null;
try
{
localhost = "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + port + serviceName;
}
catch(UnknownHostException ex)
{
localhost = "http://localhost:" + port + serviceName;
}
serviceURL = new URL(localhost);
System.out.println("service url = " + serviceURL);
return serviceURL;
}
/**
* Have to use this service name when starting internall since the path is different
* than if accessing externally (see service vs services in paths).
* @return String representing internal service path
*/
private String getPrivateServiceName()
{
return "/axis/service/AxisSOAPConnector";
}
private String getPublicServiceName()
{
return "/axis/services/AxisSOAPConnector";
}
public URL getServiceURL() throws MalformedURLException
{
return createServiceURL(getPublicServiceName());
}
/**
* Will start the soap service and deploy the connector service. If service
* has already been started, this method will cause a new thread to be spawned
* and wait till the service stops, then restart it (See SimpleAxisServer within
* Axis package).
* @throws Exception Thrown is server socket not properly setup.
*/
public void start()
throws Exception
{
if(soapServer.getServerSocket() != null)
{
soapServer.start();
//TODO - Might want this to be broken out into seperate class -TME
// now deploy service
deployService();
}
else
{
throw new Exception("Can not start AxisSOAPServer since was unable to create ServerSocket within constructor");
}
}
public void stop()
throws Exception
{
unDeployService();
soapServer.stop();
}
/**
* This will create a server-config.wsdd in the working directory
*
* @throws ServiceException
* @throws MalformedURLException
* @throws RemoteException
*/
private void deployService()
throws ServiceException, MalformedURLException, RemoteException
{
InputStream xmlDeploymentStream = getServiceDeployment();
manageService(xmlDeploymentStream);
}
private void unDeployService()
throws ServiceException, MalformedURLException, RemoteException
{
InputStream xmlDeploymentStream = getServiceUnDeployment();
manageService(xmlDeploymentStream);
}
/**
* Used to deploy or undeploy service based on deployment stream. Done by making
* SOAP calls to AdminService.
*
* @param xmlDeploymentStream
* @throws ServiceException
* @throws MalformedURLException
* @throws RemoteException
*/
private void manageService(InputStream xmlDeploymentStream)
throws ServiceException, MalformedURLException, RemoteException
{
Service service = new Service();
Call call = (Call) service.createCall();
setupCall(call);
call.setUseSOAPAction(true);
call.setSOAPActionURI("AdminService");
Object[] params = new Object[]{new SOAPBodyElement(xmlDeploymentStream)};
Vector result = (Vector) call.invoke(params);
if(result == null || result.isEmpty())
{
throw new AxisFault(Messages.getMessage("nullResponse00"));
}
SOAPBodyElement body = (SOAPBodyElement) result.elementAt(0);
}
private void setupCall(Call call) throws MalformedURLException
{
//TODO - Need to make this section configurable -TME
call.setTargetEndpointAddress(createServiceURL(getPrivateServiceName()));
//call.setUsername("telrod");
//call.setPassword("foobar");
}
private InputStream getServiceDeployment()
{
String deploymentString = getDeploymentString();
return createInputStream(deploymentString);
}
private InputStream createInputStream(String deploymentString)
{
ByteArrayInputStream inputStream = new ByteArrayInputStream(deploymentString.getBytes());
return inputStream;
}
private String getDeploymentString()
{
String deploymentXML = "<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\"" +
" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\">" +
" <service name=\"AxisSOAPConnector\" provider=\"java:RPC\" style=\"rpc\" use=\"encoded\">" +
" <parameter name=\"wsdlTargetNamespace\" value=\"urn:AxisSOAPConnector\"/>" +
" <parameter name=\"wsdlServiceElement\" value=\"AxisSOAPConnectorService\"/>" +
" <parameter name=\"wsdlServicePort\" value=\"AxisSOAPConnector\"/>" +
" <parameter name=\"className\" value=\"org.jboss.mx.remote.connector.soap.axis.AxisSOAPConnectorSoapBindingSkeleton\"/>" +
" <parameter name=\"wsdlPortType\" value=\"AxisSOAPConnector\"/>" +
" <parameter name=\"allowedMethods\" value=\"*\"/>" +
// " <parameter name=\"scope\" value=\"Session\"/>" +
" <parameter name=\"scope\" value=\"Application\"/>" +
" </service>" +
" </deployment>";
return deploymentXML;
}
private InputStream getServiceUnDeployment()
{
String undeploymentString = getUnDeploymentString();
return createInputStream(undeploymentString);
}
private String getUnDeploymentString()
{
String undeploymentXML = "<undeployment xmlns=\"http://xml.apache.org/axis/wsdd/\">" +
"<service name=\"AxisSOAPConnector\"/>" +
"</undeployment>";
return undeploymentXML;
}
}