View Javadoc

1   package org.codehaus.ivory;
2   
3   import java.io.File;
4   import java.io.FileInputStream;
5   import java.io.InputStream;
6   
7   import javax.xml.namespace.QName;
8   
9   import org.apache.avalon.framework.activity.Initializable;
10  import org.apache.avalon.framework.activity.Startable;
11  import org.apache.avalon.framework.configuration.Configurable;
12  import org.apache.avalon.framework.configuration.Configuration;
13  import org.apache.avalon.framework.configuration.ConfigurationException;
14  import org.apache.avalon.framework.context.Context;
15  import org.apache.avalon.framework.context.ContextException;
16  import org.apache.avalon.framework.context.Contextualizable;
17  import org.apache.avalon.framework.logger.AbstractLogEnabled;
18  import org.apache.avalon.framework.service.ServiceException;
19  import org.apache.avalon.framework.service.ServiceManager;
20  import org.apache.avalon.framework.service.Serviceable;
21  
22  import org.apache.axis.AxisFault;
23  import org.apache.axis.configuration.FileProvider;
24  import org.apache.axis.configuration.SimpleProvider;
25  import org.apache.axis.deployment.wsdd.WSDDConstants;
26  import org.apache.axis.deployment.wsdd.WSDDProvider;
27  import org.apache.axis.description.ServiceDesc;
28  import org.apache.axis.encoding.TypeMappingImpl;
29  import org.apache.axis.encoding.TypeMappingRegistry;
30  import org.apache.axis.enum.Scope;
31  import org.apache.axis.handlers.soap.SOAPService;
32  import org.apache.axis.providers.java.RPCProvider;
33  import org.apache.axis.server.AxisServer;
34  import org.apache.axis.wsdl.fromJava.Namespaces;
35  
36  import org.codehaus.ivory.provider.AvalonProvider;
37  import org.codehaus.ivory.provider.IvoryAvalonProvider;
38  import org.codehaus.ivory.provider.IvoryProvider;
39  import org.codehaus.ivory.provider.WSDDJavaAvalonProvider;
40  import org.codehaus.ivory.util.AvalonContextUtilities;
41  
42  /***
43   * The default AxisService implementation.
44   * 
45   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
46   * @since Mar 9, 2003
47   */
48  public class DefaultAxisService 
49      extends AbstractLogEnabled
50      implements AxisService, Startable, Configurable, Initializable, Serviceable, Contextualizable
51  {
52      /*** We hold a static ServiceManager so the servlets can get at it. */
53      private static ServiceManager manager;
54      
55      public static final QName QNAME_AVALONRPC_PROVIDER =
56          new QName(WSDDConstants.URI_WSDD_JAVA, "Avalon");
57  
58      protected static final String SERVER_CONFIG_KEY = "server-config";
59      
60      protected static final String DEFAULT_SERVER_CONFIG = 
61      	"/org/codehaus/ivory/server-config.wsdd";
62      
63      private SimpleProvider provider;
64      
65      private AxisServer axisServer;
66      
67      private String serverConfig;
68      
69      private Configuration services;
70  
71      private Context context;
72      
73      /***
74       * @param configuration
75       * @throws ConfigurationException
76       * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
77       */
78      public void configure( Configuration configuration )
79          throws ConfigurationException
80      {
81          serverConfig = configuration.getAttribute( SERVER_CONFIG_KEY, "" );
82          
83          services = configuration.getChild( "services" );
84      }
85      
86  	/***
87  	 * @throws Exception
88  	 * @see org.apache.avalon.framework.activity.Initializable#initialize()
89  	 */
90  	public void initialize() throws Exception
91  	{
92  		initializeAxisServer();
93          initializeWSDDProviders();
94  		   
95  		// Initialize the services in the configuration.
96  		initializeServices( services );
97          
98          // This is definitely not what setOption was meant for...
99          getAxisServer().setOption(SERVICE_MANAGER_KEY, manager);
100 	}
101     
102     /***
103      * Register custom providers with Axis.
104      */
105     private void initializeWSDDProviders()
106     {
107         /* This could be registered other ways - like through the jar's
108          * META-INF, but lets take the easy and straightforward way out.
109          */
110         WSDDProvider.registerProvider(
111             QNAME_AVALONRPC_PROVIDER,
112             new WSDDJavaAvalonProvider());
113     }
114 
115     /***
116      * @param services
117      */
118     protected void initializeServices(Configuration services)
119         throws Exception
120     {
121         initializeClassServices( services.getChildren( "classService" ) );
122         
123         initializeAvalonServices( services.getChildren( "avalonService" ) );  
124     }
125 
126     /***
127      * @param configurations
128      */
129     protected void initializeClassServices( Configuration[] services )
130         throws Exception
131     {
132         for ( int i = 0; i < services.length; i++ )
133         {
134             String name = services[i].getAttribute( "name" );
135             String role = services[i].getAttribute( "class" );
136             exposeClass( name, role );
137         }   
138     }
139 
140     /***
141      * @param configurations
142      */
143     protected void initializeAvalonServices(Configuration[] services )
144         throws Exception
145     {
146         for ( int i = 0; i < services.length; i++ )
147         {
148             String name = services[i].getAttribute( "name" );
149             String className = services[i].getAttribute( "role" );
150             exposeService( name, className );
151         }
152     }
153 
154 	/***
155 	 * Initializes the AxisServer.
156 	 * @throws Exception
157 	 */
158     public void initializeAxisServer() throws Exception
159     {
160 		/* Technically, we are supposed to use Axis's EngineConfigurationFactory
161 		 * but it is a big PITA and seems uneccessary.  This can be changed
162 		 * in the future if more flexible mechanisms of loading the
163 		 * configuration are needed.
164 		 */
165 		FileProvider fileProvider = null;
166 
167     	if ( serverConfig.equals("") )
168     	{
169     		getLogger().debug( "Using default server-config.wsdd." );
170     		
171     		InputStream is = this.getClass().getResourceAsStream( DEFAULT_SERVER_CONFIG );
172 			
173 			if ( is == null )
174 				throw new RuntimeException( "Configuration is null!" );
175 
176     		fileProvider = new FileProvider( DEFAULT_SERVER_CONFIG );
177     		fileProvider.setInputStream( is );
178     	}
179     	else
180     	{
181 			getLogger().debug( "Using server-config " + serverConfig + "." );
182             File configFile = null;
183             try
184             {
185                 configFile = AvalonContextUtilities.getFile(context, serverConfig);
186             }
187             catch (Exception e)
188             {
189                 e.printStackTrace();
190             }
191             
192             getLogger().info( "Found AXIS configuration at " + configFile.getAbsolutePath() );
193     		fileProvider = new FileProvider( new FileInputStream(configFile) );
194     	}
195 
196         /* Wrap the FileProvider with a SimpleProvider.  This needs to be done
197          * because the only way to expose services with the FileProvider is to
198          * use WSDD deployment descriptors.  SimpleProvider allows us to deploy
199          * services much easier.
200          */
201         provider = new SimpleProvider( fileProvider );
202 
203     	// Create the AxisServer from the configuraiton.
204         axisServer = new AxisServer( provider );
205         axisServer.getApplicationSession().set( AvalonProvider.SERVICE_MANAGER,
206                                                 manager );
207     }
208    
209     /***
210      * @throws Exception
211      * @see org.apache.avalon.framework.activity.Startable#start()
212      */
213     public void start() throws Exception
214     {
215     	getLogger().debug( "Starting " + DefaultAxisService.ROLE );
216     	
217     	// This doesn't need to be done, since the AxisServier constructor
218     	// calls init(), which is what start() does.
219         // axisServer.start();
220     }
221     
222     /***
223      * @throws Exception
224      * @see org.apache.avalon.framework.activity.Startable#stop()
225      */
226     public void stop() throws Exception
227     {
228 		getLogger().debug( "Stopping " + DefaultAxisService.ROLE );
229     	
230     	axisServer.stop();        
231     }
232     
233     /***
234      * @return AxisServer
235      * @see org.codehaus.ivory.axis.AxisService#getAxisServer()
236      */
237     public AxisServer getAxisServer()
238     {
239         return axisServer;
240     }
241     
242     /***
243      * @see org.codehaus.ivory.axis.AxisService#exposeClass(java.lang.String, java.lang.Class)
244      */
245     public void exposeClass( String serviceName, String classService )
246         throws AxisFault, ClassNotFoundException
247     {
248     	exposeClass( serviceName, null, classService );
249     }
250     
251     /***
252      * @see org.codehaus.ivory.axis.AxisService#exposeClass(java.lang.String, java.lang.String[], java.lang.Class)
253      */
254     public void exposeClass( String serviceName,
255     					     String[] methodNames, 
256                              String className )
257         throws AxisFault, ClassNotFoundException
258     {
259     	SOAPService service = new SOAPService( new IvoryProvider() );
260         
261         initializeService( service, serviceName,
262                            methodNames, className );
263             
264         getLogger().debug( "Exposed class " + className + 
265                            " as " + serviceName + "." );
266     }
267 
268     /***
269      * @see org.codehaus.ivory.axis.AxisService#exposeService(java.lang.String, java.lang.String)
270      */
271     public void exposeService(String serviceName, String role)
272         throws AxisFault, ClassNotFoundException
273     {
274         exposeService( serviceName, null, role ); 
275     }
276 
277     /***
278      * @see org.codehaus.ivory.axis.AxisService#exposeService(java.lang.String, java.lang.String[], java.lang.String)
279      */
280     public void exposeService(String serviceName, 
281                               String[] methodNames, 
282                               String role)
283         throws AxisFault, ClassNotFoundException
284     {
285         SOAPService service = new SOAPService( new IvoryAvalonProvider() );
286         
287         initializeService( service, serviceName, methodNames, role );
288             
289         getLogger().debug( "Exposed service " + role + 
290                            " as " + serviceName + "." );
291     }
292 
293     /***
294      * Initializes the SOAPService with the appropriate information.
295      */
296     protected void initializeService( SOAPService service,
297                                       String serviceName, 
298                                       String[] methodNames, 
299                                       String className )
300         throws AxisFault, ClassNotFoundException
301     {
302         service.setEngine( getAxisServer() );
303         
304         // The namespace of the service.
305         String namespace =  Namespaces.makeNamespace( className );
306         
307         /* Now we set up the various options for the SOAPService. We set:
308          * 
309          * RPCProvider.OPTION_WSDL_SERVICEPORT
310          * In essense, this is our service name
311          * 
312          * RPCProvider.OPTION_CLASSNAME
313          * This tells the provider (whether it be an AvalonProvider or just
314          * JavaProvider) what class to load via "makeNewServiceObject".
315          * 
316          * RPCProvider.OPTION_SCOPE
317          * How long the object loaded via "makeNewServiceObject" will persist -
318          * either request, session, or application.  We use the default for now.
319          * 
320          * RPCProvider.OPTION_WSDL_TARGETNAMESPACE
321          * A namespace created from the package name of the service.
322          * 
323          * RPCProvider.OPTION_ALLOWEDMETHODS
324          * What methods the service can execute on our class.
325          * 
326          * We don't set:
327          * RPCProvider.OPTION_WSDL_PORTTYPE
328          * RPCProvider.OPTION_WSDL_SERVICEELEMENT
329          */
330         service.setOption( RPCProvider.OPTION_WSDL_SERVICEPORT, serviceName );
331         service.setOption( RPCProvider.OPTION_CLASSNAME, className );
332         service.setOption( RPCProvider.OPTION_SCOPE, Scope.DEFAULT.getName());
333         service.setOption( RPCProvider.OPTION_WSDL_TARGETNAMESPACE, 
334                            namespace  );
335                     
336         // Set the allowed methods, allow all if there are none specified.
337         if ( methodNames == null)
338         {
339             service.setOption( RPCProvider.OPTION_ALLOWEDMETHODS, "*" );
340         }
341         else
342         {
343             service.setOption( RPCProvider.OPTION_ALLOWEDMETHODS, methodNames ); 
344         }
345                 
346         /* Create a service description.  This tells Axis that this
347          * service exists and also what it can execute on this service.  It is
348          * created with all the options we set above.
349          */
350         ServiceDesc sd = service.getInitializedServiceDesc(null);
351 		
352         // Tell Axis to try and be intelligent about serialization.
353         TypeMappingRegistry registry = service.getTypeMappingRegistry();        
354         
355         TypeMappingImpl tm = (TypeMappingImpl) registry.getDefaultTypeMapping();
356         //tm.setDoAutoTypes( true );
357         
358         // Tell the axis configuration about our new service.
359         provider.deployService( serviceName, service );
360     }
361 
362     /***
363      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
364      */
365     public void service(ServiceManager manager) throws ServiceException
366     {
367         DefaultAxisService.manager = manager;
368     }
369     
370     public static ServiceManager getServiceManager()
371     {
372         return manager;
373     }
374 
375 	/***
376 	 * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
377 	 */
378 	public void contextualize(Context context) throws ContextException
379 	{
380 		this.context = context;
381 	}
382 }