CVS: ivory/src/java/org/codehaus/ivory/axis AvalonProvider.java,1.1,1.2 DefaultAxisService.java,1.1,1.2

[email protected] Sun, 4 May 2003 15:25:58 -0500
Newsgroups gmane.comp.java.plexus.devel
Message-ID <[email protected]>
Update of /cvsroot/plexus/ivory/src/java/org/codehaus/ivory/axis
In directory eng.werken.com:/tmp/cvs-serv24814/src/java/org/codehaus/ivory/axis

Modified Files:
	AvalonProvider.java DefaultAxisService.java 
Log Message:
- Documentation corrections
- move the servlets to the plexus package.
- IvoryTestCase which should make testing services a little easier.
  See the unit tests if you're interested.  More testing utilities coming
  soon!
- You do not need to call AxisServer.start() as it turns out, the
  AxisServer constructor already does that.
- AxisService will not expose methods that return a List or take it
  as a parameter.  Axis does not know how to hanlde this yet.

Index: AvalonProvider.java
===================================================================
RCS file: /cvsroot/plexus/ivory/src/java/org/codehaus/ivory/axis/AvalonProvider.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- AvalonProvider.java	18 Mar 2003 00:04:33 -0000	1.1
+++ AvalonProvider.java	4 May 2003 20:25:56 -0000	1.2
@@ -29,10 +29,9 @@
      */
     protected Object makeNewServiceObject( MessageContext msgContext,
                                            String role )
-            throws Exception {
-                
-        // TODO: put in a security mechanism
-        
+    	throws Exception
+    {
+
         Object targetObject = manager.lookup( role );
         return targetObject;
     }

Index: DefaultAxisService.java
===================================================================
RCS file: /cvsroot/plexus/ivory/src/java/org/codehaus/ivory/axis/DefaultAxisService.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- DefaultAxisService.java	18 Mar 2003 00:04:33 -0000	1.1
+++ DefaultAxisService.java	4 May 2003 20:25:56 -0000	1.2
@@ -1,290 +1,368 @@
-package org.codehaus.ivory.axis;
-
-import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.activity.Startable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.thread.ThreadSafe;
-import org.apache.axis.AxisFault;
-import org.apache.axis.configuration.FileProvider;
-import org.apache.axis.configuration.SimpleProvider;
-import org.apache.axis.description.ServiceDesc;
-import org.apache.axis.encoding.TypeMappingImpl;
-import org.apache.axis.encoding.TypeMappingRegistry;
-import org.apache.axis.enum.Scope;
-import org.apache.axis.handlers.soap.SOAPService;
-import org.apache.axis.providers.java.RPCProvider;
-import org.apache.axis.server.AxisServer;
-import org.apache.axis.wsdl.fromJava.Namespaces;
-
-/**
- * The default AxisService implementation.
- * 
- * @author <a href="mailto:[email protected]">Dan Diephouse</a>
- * @since Mar 9, 2003
- */
-public class DefaultAxisService 
-    extends AbstractLogEnabled
-    implements AxisService, Startable, Configurable, Initializable, ThreadSafe,
-               Serviceable
-{
-    private ServiceManager manager;
-
-    protected static final String SERVER_CONFIG_KEY = "server-config";
-    
-    private SimpleProvider provider;
-    
-    private AxisServer axisServer;
-    
-    private String serverConfig;
-    
-    private Configuration services;
-    
-    /**
-     * @param configuration
-     * @throws ConfigurationException
-     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
-     */
-    public void configure( Configuration configuration )
-        throws ConfigurationException
-    {
-        serverConfig = configuration.getAttribute( SERVER_CONFIG_KEY );
-        
-        services = configuration.getChild( "services" );
-    }
-    
-    /**
-     * @param services
-     */
-    protected void initializeServices(Configuration services)
-        throws Exception
-    {
-        initializeClassServices( services.getChildren( "classService" ) );
-        
-        initializeAvalonServices( services.getChildren( "avalonService" ) );  
-    }
-
-    /**
-     * @param configurations
-     */
-    protected void initializeClassServices( Configuration[] services )
-        throws Exception
-    {
-        for ( int i = 0; i < services.length; i++ )
-        {
-            String name = services[i].getAttribute( "name" );
-            String role = services[i].getAttribute( "class" );
-            exposeClass( name, role );
-        }   
-    }
-
-    /**
-     * @param configurations
-     */
-    protected void initializeAvalonServices(Configuration[] services )
-        throws Exception
-    {
-        for ( int i = 0; i < services.length; i++ )
-        {
-            String name = services[i].getAttribute( "name" );
-            String className = services[i].getAttribute( "role" );
-            exposeService( name, className );
-        }
-    }
-
-    /**
-     * Initializes the AxisServer.
-     * 
-     * @throws Exception
-     * @see org.apache.avalon.framework.activity.Initializable#initialize()
-     */
-    public void initialize() throws Exception
-    {
-    	/* TODO: if serverConfig equals null then I'm not sure how we create the
-    	 * configuration.  We want to be able to handle this in case the user
-    	 * is only deploying services on the fly.  The 
-    	 * EngineConfigurationFactory way of doing things doesn't like null and
-    	 * bombs out.
-    	 */
-    	 
-        /* Technically, we are supposed to use Axis's EngineConfigurationFactory
-         * but it is a big PITA and seems uneccessary.  This can be changed
-         * in the future if more flexible mechanisms of loading the
-         * configuration are needed.
-         */
-    	FileProvider fileProvider = new FileProvider( serverConfig );
-
-        /* Wrap the FileProvider with a SimpleProvider.  This needs to be done
-         * because the only way to expose services with the FileProvider is to
-         * use WSDD deployment descriptors.  SimpleProvider allows us to deploy
-         * services much easier.
-         */
-        provider = new SimpleProvider( fileProvider );
-        
-    	// Create the AxisServer from the configuraiton.
-        axisServer = new AxisServer( provider );
-
-        // Initialize the services in the configuration.
-        initializeServices( services );
-    }
-    
-    /**
-     * @throws Exception
-     * @see org.apache.avalon.framework.activity.Startable#start()
-     */
-    public void start() throws Exception
-    {
-        axisServer.start();
-    }
-    
-    /**
-     * @throws Exception
-     * @see org.apache.avalon.framework.activity.Startable#stop()
-     */
-    public void stop() throws Exception
-    {
-        axisServer.stop();        
-    }
-    
-    /**
-     * @return AxisServer
-     * @see org.codehaus.ivory.axis.AxisService#getAxisServer()
-     */
-    public AxisServer getAxisServer()
-    {
-        return axisServer;
-    }
-    
-    /**
-     * @see org.codehaus.ivory.axis.AxisService#exposeClass(java.lang.String, java.lang.Class)
-     */
-    public void exposeClass( String serviceName, String classService )
-        throws AxisFault
-    {
-    	exposeClass( serviceName, null, classService );
-    }
-    
-    /**
-     * @see org.codehaus.ivory.axis.AxisService#exposeClass(java.lang.String, java.lang.String[], java.lang.Class)
-     */
-    public void exposeClass( String serviceName,
-    					     String[] methodNames, 
-                             String className )
-        throws AxisFault
-    {
-    	SOAPService service = new SOAPService( new RPCProvider() );
-        
-        initializeService( service, serviceName,
-                           methodNames, className );
-            
-        getLogger().debug( "Exposed class " + className + 
-                           " as " + serviceName + "." );
-    }
-
-    /**
-     * @see org.codehaus.ivory.axis.AxisService#exposeService(java.lang.String, java.lang.String)
-     */
-    public void exposeService(String serviceName, String role)
-        throws AxisFault
-    {
-        exposeService( serviceName, null, role ); 
-    }
-
-    /**
-     * @see org.codehaus.ivory.axis.AxisService#exposeService(java.lang.String, java.lang.String[], java.lang.String)
-     */
-    public void exposeService(String serviceName, 
-                              String[] methodNames, 
-                              String role)
-        throws AxisFault
-    {
-        SOAPService service = new SOAPService( new AvalonProvider( manager ) );
-        
-        initializeService( service, serviceName, methodNames, role );
-            
-        getLogger().debug( "Exposed service " + role + 
-                           " as " + serviceName + "." );
-    }
-
-    /**
-     * Initializes the SOAPService with the appropriate information.
-     */
-    protected void initializeService( SOAPService service,
-                                      String serviceName, 
-                                      String[] methodNames, 
-                                      String className )
-        throws AxisFault
-    {
-        service.setEngine( getAxisServer() );
-        
-        // The namespace of the service.
-        String namespace =  Namespaces.makeNamespace( className );
-        
-        /* Now we set up the various options for the SOAPService. We set:
-         * 
-         * RPCProvider.OPTION_WSDL_SERVICEPORT
-         * In essense, this is our service name
-         * 
-         * RPCProvider.OPTION_CLASSNAME
-         * This tells the provider (whether it be an AvalonProvider or just
-         * JavaProvider) what class to load via "makeNewServiceObject".
-         * 
-         * RPCProvider.OPTION_SCOPE
-         * How long the object loaded via "makeNewServiceObject" will persist -
-         * either request, session, or application.  We use the default for now.
-         * 
-         * RPCProvider.OPTION_WSDL_TARGETNAMESPACE
-         * TODO: It is not clear what this target namespace should be quite yet.
-         * 
-         * RPCProvider.OPTION_ALLOWEDMETHODS
-         * What methods the service can execute on our class.
-         * 
-         * We don't set:
-         * RPCProvider.OPTION_WSDL_PORTTYPE
-         * RPCProvider.OPTION_WSDL_SERVICEELEMENT
-         */
-        service.setOption( RPCProvider.OPTION_WSDL_SERVICEPORT, serviceName );
-        service.setOption( RPCProvider.OPTION_CLASSNAME, className );
-        service.setOption( RPCProvider.OPTION_SCOPE, Scope.DEFAULT.getName());
-        service.setOption( RPCProvider.OPTION_WSDL_TARGETNAMESPACE, 
-                           namespace  );
-                    
-        // Set the allowed methods, allow all if there are none specified.
-        if ( methodNames == null)
-        {
-            service.setOption( RPCProvider.OPTION_ALLOWEDMETHODS, "*" );
-        }
-        else
-        {
-            service.setOption( RPCProvider.OPTION_ALLOWEDMETHODS, methodNames ); 
-        }
-                
-        /* Create a service description.  This tells access that this
-         * service exists and also what it can execute on this service..  It is
-         * created with all the options we set above.
-         */
-        ServiceDesc sd = service.getInitializedServiceDesc(null);
-        
-        // Tell Axis to try and be intelligent about serialization.
-        TypeMappingRegistry registry = service.getTypeMappingRegistry();        
-        
-        TypeMappingImpl tm = (TypeMappingImpl) registry.getDefaultTypeMapping();
-        tm.setDoAutoTypes( true );
-        
-        // Tell the axis configuration about our new service.
-        provider.deployService( serviceName, service );
-    }
-    
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager manager) throws ServiceException
-    {
-        this.manager = manager;
-    }
-}
+package org.codehaus.ivory.axis;
+
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.activity.Startable;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.axis.AxisFault;
+import org.apache.axis.configuration.FileProvider;
+import org.apache.axis.configuration.SimpleProvider;
+import org.apache.axis.description.OperationDesc;
+import org.apache.axis.description.ParameterDesc;
+import org.apache.axis.description.ServiceDesc;
+import org.apache.axis.encoding.TypeMappingImpl;
+import org.apache.axis.encoding.TypeMappingRegistry;
+import org.apache.axis.enum.Scope;
+import org.apache.axis.handlers.soap.SOAPService;
+import org.apache.axis.providers.java.RPCProvider;
+import org.apache.axis.server.AxisServer;
+import org.apache.axis.wsdl.fromJava.Namespaces;
+
+/**
+ * The default AxisService implementation.
+ * 
+ * @author <a href="mailto:[email protected]">Dan Diephouse</a>
+ * @since Mar 9, 2003
+ */
+public class DefaultAxisService 
+    extends AbstractLogEnabled
+    implements AxisService, Startable, Configurable, Initializable, Serviceable
+{
+    private ServiceManager manager;
+
+    protected static final String SERVER_CONFIG_KEY = "server-config";
+    
+    protected static final String DEFAULT_SERVER_CONFIG = 
+    	"/org/codehaus/ivory/axis/server-config.wsdd";
+
+    private SimpleProvider provider;
+    
+    private AxisServer axisServer;
+    
+    private String serverConfig;
+    
+    private Configuration services;
+    
+    /**
+     * @param configuration
+     * @throws ConfigurationException
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+     */
+    public void configure( Configuration configuration )
+        throws ConfigurationException
+    {
+        serverConfig = configuration.getAttribute( SERVER_CONFIG_KEY, "" );
+        
+        services = configuration.getChild( "services" );
+    }
+    
+	/**
+	 * @throws Exception
+	 * @see org.apache.avalon.framework.activity.Initializable#initialize()
+	 */
+	public void initialize() throws Exception
+	{
+		initializeAxisServer();
+		   
+		// Initialize the services in the configuration.
+		initializeServices( services );
+	}
+    
+    /**
+     * @param services
+     */
+    protected void initializeServices(Configuration services)
+        throws Exception
+    {
+        initializeClassServices( services.getChildren( "classService" ) );
+        
+        initializeAvalonServices( services.getChildren( "avalonService" ) );  
+    }
+
+    /**
+     * @param configurations
+     */
+    protected void initializeClassServices( Configuration[] services )
+        throws Exception
+    {
+        for ( int i = 0; i < services.length; i++ )
+        {
+            String name = services[i].getAttribute( "name" );
+            String role = services[i].getAttribute( "class" );
+            exposeClass( name, role );
+        }   
+    }
+
+    /**
+     * @param configurations
+     */
+    protected void initializeAvalonServices(Configuration[] services )
+        throws Exception
+    {
+        for ( int i = 0; i < services.length; i++ )
+        {
+            String name = services[i].getAttribute( "name" );
+            String className = services[i].getAttribute( "role" );
+            exposeService( name, className );
+        }
+    }
+
+	/**
+	 * Initializes the AxisServer.
+	 * @throws Exception
+	 */
+    public void initializeAxisServer() throws Exception
+    {
+		/* Technically, we are supposed to use Axis's EngineConfigurationFactory
+		 * but it is a big PITA and seems uneccessary.  This can be changed
+		 * in the future if more flexible mechanisms of loading the
+		 * configuration are needed.
+		 */
+		FileProvider fileProvider = null;
+
+    	if ( serverConfig.equals("") )
+    	{
+    		getLogger().debug( "Using default server-config.wsdd." );
+    		
+    		InputStream is = this.getClass().getResourceAsStream( DEFAULT_SERVER_CONFIG );
+			
+			if ( is == null )
+				throw new RuntimeException( "Configuration is null!" );
+
+    		fileProvider = new FileProvider( DEFAULT_SERVER_CONFIG );
+    		fileProvider.setInputStream( is );
+    	}
+    	else
+    	{
+			getLogger().debug( "Using server-config " + serverConfig + "." );
+    		
+    		fileProvider = new FileProvider( serverConfig );
+    	}
+
+        /* Wrap the FileProvider with a SimpleProvider.  This needs to be done
+         * because the only way to expose services with the FileProvider is to
+         * use WSDD deployment descriptors.  SimpleProvider allows us to deploy
+         * services much easier.
+         */
+        provider = new SimpleProvider( fileProvider );
+
+    	// Create the AxisServer from the configuraiton.
+        axisServer = new AxisServer( provider );
+    }
+   
+    /**
+     * @throws Exception
+     * @see org.apache.avalon.framework.activity.Startable#start()
+     */
+    public void start() throws Exception
+    {
+    	getLogger().debug( "Starting " + DefaultAxisService.ROLE );
+    	
+    	// This doesn't need to be done, since the AxisServier constructor
+    	// calls init(), which is what start() does.
+        // axisServer.start();
+    }
+    
+    /**
+     * @throws Exception
+     * @see org.apache.avalon.framework.activity.Startable#stop()
+     */
+    public void stop() throws Exception
+    {
+		getLogger().debug( "Stopping " + DefaultAxisService.ROLE );
+    	
+    	axisServer.stop();        
+    }
+    
+    /**
+     * @return AxisServer
+     * @see org.codehaus.ivory.axis.AxisService#getAxisServer()
+     */
+    public AxisServer getAxisServer()
+    {
+        return axisServer;
+    }
+    
+    /**
+     * @see org.codehaus.ivory.axis.AxisService#exposeClass(java.lang.String, java.lang.Class)
+     */
+    public void exposeClass( String serviceName, String classService )
+        throws AxisFault
+    {
+    	exposeClass( serviceName, null, classService );
+    }
+    
+    /**
+     * @see org.codehaus.ivory.axis.AxisService#exposeClass(java.lang.String, java.lang.String[], java.lang.Class)
+     */
+    public void exposeClass( String serviceName,
+    					     String[] methodNames, 
+                             String className )
+        throws AxisFault
+    {
+    	SOAPService service = new SOAPService( new RPCProvider() );
+        
+        initializeService( service, serviceName,
+                           methodNames, className );
+            
+        getLogger().debug( "Exposed class " + className + 
+                           " as " + serviceName + "." );
+    }
+
+    /**
+     * @see org.codehaus.ivory.axis.AxisService#exposeService(java.lang.String, java.lang.String)
+     */
+    public void exposeService(String serviceName, String role)
+        throws AxisFault
+    {
+        exposeService( serviceName, null, role ); 
+    }
+
+    /**
+     * @see org.codehaus.ivory.axis.AxisService#exposeService(java.lang.String, java.lang.String[], java.lang.String)
+     */
+    public void exposeService(String serviceName, 
+                              String[] methodNames, 
+                              String role)
+        throws AxisFault
+    {
+        SOAPService service = new SOAPService( new AvalonProvider( manager ) );
+        
+        initializeService( service, serviceName, methodNames, role );
+            
+        getLogger().debug( "Exposed service " + role + 
+                           " as " + serviceName + "." );
+    }
+
+    /**
+     * Initializes the SOAPService with the appropriate information.
+     */
+    protected void initializeService( SOAPService service,
+                                      String serviceName, 
+                                      String[] methodNames, 
+                                      String className )
+        throws AxisFault
+    {
+        service.setEngine( getAxisServer() );
+        
+        // The namespace of the service.
+        String namespace =  Namespaces.makeNamespace( className );
+        
+        /* Now we set up the various options for the SOAPService. We set:
+         * 
+         * RPCProvider.OPTION_WSDL_SERVICEPORT
+         * In essense, this is our service name
+         * 
+         * RPCProvider.OPTION_CLASSNAME
+         * This tells the provider (whether it be an AvalonProvider or just
+         * JavaProvider) what class to load via "makeNewServiceObject".
+         * 
+         * RPCProvider.OPTION_SCOPE
+         * How long the object loaded via "makeNewServiceObject" will persist -
+         * either request, session, or application.  We use the default for now.
+         * 
+         * RPCProvider.OPTION_WSDL_TARGETNAMESPACE
+         * A namespace created from the package name of the service.
+         * 
+         * RPCProvider.OPTION_ALLOWEDMETHODS
+         * What methods the service can execute on our class.
+         * 
+         * We don't set:
+         * RPCProvider.OPTION_WSDL_PORTTYPE
+         * RPCProvider.OPTION_WSDL_SERVICEELEMENT
+         */
+        service.setOption( RPCProvider.OPTION_WSDL_SERVICEPORT, serviceName );
+        service.setOption( RPCProvider.OPTION_CLASSNAME, className );
+        service.setOption( RPCProvider.OPTION_SCOPE, Scope.DEFAULT.getName());
+        service.setOption( RPCProvider.OPTION_WSDL_TARGETNAMESPACE, 
+                           namespace  );
+                    
+        // Set the allowed methods, allow all if there are none specified.
+        if ( methodNames == null)
+        {
+            service.setOption( RPCProvider.OPTION_ALLOWEDMETHODS, "*" );
+        }
+        else
+        {
+            service.setOption( RPCProvider.OPTION_ALLOWEDMETHODS, methodNames ); 
+        }
+                
+        /* Create a service description.  This tells Axis that this
+         * service exists and also what it can execute on this service.  It is
+         * created with all the options we set above.
+         */
+        ServiceDesc sd = service.getInitializedServiceDesc(null);
+
+		customizeServiceDescription( sd );
+		
+        // Tell Axis to try and be intelligent about serialization.
+        TypeMappingRegistry registry = service.getTypeMappingRegistry();        
+        
+        TypeMappingImpl tm = (TypeMappingImpl) registry.getDefaultTypeMapping();
+        tm.setDoAutoTypes( true );
+        
+        // Tell the axis configuration about our new service.
+        provider.deployService( serviceName, service );
+    }
+    
+    /**
+     * @param sd
+     */
+    private void customizeServiceDescription(ServiceDesc sd)
+    {
+        List operations = sd.getOperations();
+
+        for ( Iterator itr = operations.iterator(); itr.hasNext(); )
+        {
+        	OperationDesc operation = ( OperationDesc ) itr.next();
+        	
+        	if ( !isExposable( operation ) )
+        	{
+				getLogger().info( "Operation " + operation.getName()  +
+								  " on service " + sd.getImplClass() +
+								  " uses a java.util.List class which cannot " +
+								  "be used with the current version of Ivory." );
+				itr.remove();
+        	}
+        }
+    }
+
+    private boolean isExposable( OperationDesc operation )
+    {
+		for( Iterator itr = operation.getParameters().iterator(); itr.hasNext(); )
+		{
+			if ( !isValidParameter( (ParameterDesc) itr.next() ))
+				return false;		
+		}
+		
+		return isValidParameter( operation.getReturnParamDesc() );
+    }
+
+	private boolean isValidParameter( ParameterDesc parameter )
+	{
+		if ( parameter.getJavaType().equals( java.util.List.class.getClass() )
+			 || List.class.isAssignableFrom( parameter.getJavaType() ) )
+		{
+			return false;
+		}
+		
+		return true;
+	}
+
+    /**
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
+    public void service(ServiceManager manager) throws ServiceException
+    {
+        this.manager = manager;
+    }
+}