KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > handlers > soap > SOAPService


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis.handlers.soap;
18
19 import org.apache.axis.AxisEngine;
20 import org.apache.axis.AxisFault;
21 import org.apache.axis.Constants;
22 import org.apache.axis.Handler;
23 import org.apache.axis.Message;
24 import org.apache.axis.MessageContext;
25 import org.apache.axis.SimpleTargetedChain;
26 import org.apache.axis.attachments.Attachments;
27 import org.apache.axis.components.logger.LogFactory;
28 import org.apache.axis.description.JavaServiceDesc;
29 import org.apache.axis.description.ServiceDesc;
30 import org.apache.axis.encoding.TypeMappingRegistry;
31 import org.apache.axis.encoding.TypeMapping;
32 import org.apache.axis.constants.Style;
33 import org.apache.axis.constants.Use;
34 import org.apache.axis.handlers.HandlerChainImpl;
35 import org.apache.axis.handlers.HandlerInfoChainFactory;
36 import org.apache.axis.message.SOAPEnvelope;
37 import org.apache.axis.message.SOAPFault;
38 import org.apache.axis.providers.BasicProvider;
39 import org.apache.axis.session.Session;
40 import org.apache.axis.utils.LockableHashtable;
41 import org.apache.axis.utils.Messages;
42 import org.apache.axis.utils.XMLUtils;
43 import org.apache.axis.utils.ClassUtils;
44 import org.apache.commons.logging.Log;
45 import org.w3c.dom.Document JavaDoc;
46
47 import javax.xml.rpc.soap.SOAPFaultException JavaDoc;
48 import java.io.File JavaDoc;
49 import java.io.FileInputStream JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.InputStream JavaDoc;
52 import java.util.ArrayList JavaDoc;
53 import java.util.Hashtable JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.Vector JavaDoc;
56 import java.util.Map JavaDoc;
57 import java.util.HashMap JavaDoc;
58 import java.util.List JavaDoc;
59
60 /** A <code>SOAPService</code> is a Handler which encapsulates a SOAP
61  * invocation. It has an request chain, an response chain, and a pivot-point,
62  * and handles the SOAP semantics when invoke()d.
63  *
64  * @author Glen Daniels (gdaniels@apache.org)
65  * @author Doug Davis (dug@us.ibm.com)
66  */

67 public class SOAPService extends SimpleTargetedChain
68 {
69     private static Log log =
70         LogFactory.getLog(SOAPService.class.getName());
71
72     /** Valid transports for this service
73      * (server side only!)
74      *
75      * !!! For now, if this is null, we assume all
76      * transports are valid.
77      */

78     private Vector JavaDoc validTransports = null;
79
80     /**
81      * Does this service require a high-fidelity SAX recording of messages?
82      * (default is true)
83      */

84     private boolean highFidelityRecording = true;
85
86     /**
87      * How does this service wish data which would normally be sent as
88      * an attachment to be sent? Default for requests is
89      * org.apache.axis.attachments.Attachments.SEND_TYPE_DEFAULT,
90      * and the default for responses is to match the request.
91      */

92     private int sendType = Attachments.SEND_TYPE_NOTSET;
93
94     /**
95      * Our ServiceDescription. Holds pretty much all the interesting
96      * metadata about this service.
97      */

98     private ServiceDesc serviceDescription = new JavaServiceDesc();
99     private AxisEngine engine;
100
101     /**
102      * A list of our active service objects (these can have lifetimes and
103      * be reaped)
104      */

105     public Map JavaDoc serviceObjects = new HashMap JavaDoc();
106     public int nextObjectID = 1;
107
108     /**
109      * List of sessions (for all services), key=serviceName, value=Service
110      */

111     static private Hashtable sessions = new Hashtable();
112
113     private boolean isRunning = true;
114     
115     /**
116      * Add this passed in Session to this Service's list of sessions
117      */

118     public void addSession(Session session) {
119       Vector JavaDoc v = (Vector JavaDoc) sessions.get( this.getName() );
120       if ( v == null ) {
121         v = new Vector JavaDoc();
122         sessions.put( this.getName(), v);
123       }
124       if ( !v.contains(session) ) v.add(session);
125     }
126
127     /**
128      * Remove all of this Service's serviceObjects from it known sessions
129      */

130     public void clearSessions() {
131       Vector JavaDoc v = (Vector JavaDoc) sessions.get( this.getName() );
132       if ( v == null ) return ;
133       Iterator JavaDoc iter = v.iterator();
134       while ( iter.hasNext() ) {
135         Session session = (Session) iter.next();
136         session.remove( this.getName() );
137       }
138     }
139
140     /**
141      * Actor list - these are just the service-specific ones
142      */

143     ArrayList JavaDoc actors = new ArrayList JavaDoc();
144
145     /**
146      * Get the service-specific actor list
147      * @return
148      */

149     public ArrayList JavaDoc getServiceActors() {
150         return actors;
151     }
152
153     /**
154      * Get the merged actor list for this service, including engine-wide
155      * actor URIs.
156      *
157      * @return
158      */

159     public ArrayList JavaDoc getActors() {
160         ArrayList JavaDoc acts = (ArrayList JavaDoc)actors.clone(); // ??? cache this?
161

162         if (engine != null) {
163             acts.addAll(engine.getActorURIs());
164         }
165
166         return acts;
167     }
168     
169     public List JavaDoc getRoles() {
170         return getActors();
171     }
172
173     /**
174      * Set the service-specific role list
175      *
176      * @param roles a List of Strings, each containing a role URI
177      */

178     public void setRoles(List JavaDoc roles) {
179         actors = new ArrayList JavaDoc(roles);
180     }
181
182     /** Standard, no-arg constructor.
183      */

184     public SOAPService()
185     {
186         setOptionsLockable(true);
187         initHashtable();
188
189         // For now, always assume we're the ultimate destination.
190
actors.add("");
191     }
192
193     /** Constructor with real or null request, pivot, and response
194      * handlers. A special request handler is specified to inject
195      * SOAP semantics.
196      */

197     public SOAPService(Handler reqHandler, Handler pivHandler,
198                        Handler respHandler) {
199         this();
200         init(reqHandler, new MustUnderstandChecker(this), pivHandler, null, respHandler);
201     }
202
203     public TypeMappingRegistry getTypeMappingRegistry()
204     {
205         return serviceDescription.getTypeMappingRegistry();
206     }
207
208     /** Convenience constructor for wrapping SOAP semantics around
209      * "service handlers" which actually do work.
210      */

211     public SOAPService(Handler serviceHandler)
212     {
213         this();
214         init(null, new MustUnderstandChecker(this), serviceHandler, null, null);
215     }
216     
217     /** Tell this service which engine it's deployed to.
218      *
219      */

220     public void setEngine(AxisEngine engine)
221     {
222         if (engine == null)
223             throw new IllegalArgumentException JavaDoc(
224                     Messages.getMessage("nullEngine"));
225
226         this.engine = engine;
227         ((LockableHashtable)options).setParent(engine.getOptions());
228         TypeMappingRegistry tmr = engine.getTypeMappingRegistry();
229         getTypeMappingRegistry().delegate(tmr);
230     }
231
232     public AxisEngine getEngine() {
233         return engine;
234     }
235
236     public boolean availableFromTransport(String JavaDoc transportName)
237     {
238         if (validTransports != null) {
239             for (int i = 0; i < validTransports.size(); i++) {
240                 if (validTransports.elementAt(i).equals(transportName))
241                     return true;
242             }
243             return false;
244         }
245
246         return true;
247     }
248
249     public Style getStyle() {
250         return serviceDescription.getStyle();
251     }
252
253     public void setStyle(Style style) {
254         serviceDescription.setStyle(style);
255     }
256
257     public Use getUse() {
258         return serviceDescription.getUse();
259     }
260
261     public void setUse(Use style) {
262         serviceDescription.setUse(style);
263     }
264
265     public ServiceDesc getServiceDescription() {
266         return serviceDescription;
267     }
268
269     /**
270      * Returns a service description with the implementation class filled in.
271      * Syncronized to prevent simutaneous modification of serviceDescription.
272      */

273     public synchronized ServiceDesc getInitializedServiceDesc(
274                                                      MessageContext msgContext)
275             throws AxisFault {
276
277         if (!serviceDescription.isInitialized()) {
278
279             // Let the provider do the work of filling in the service
280
// descriptor. This is so that it can decide itself how best
281
// to map the Operations. In the future, we may want to support
282
// providers which don't strictly map to Java class backends
283
// (BSFProvider, etc.), and as such we hand off here.
284
if (pivotHandler instanceof BasicProvider) {
285                 ((BasicProvider)pivotHandler).initServiceDesc(this, msgContext);
286             }
287
288         }
289
290         return serviceDescription;
291     }
292
293     public void setServiceDescription(ServiceDesc serviceDescription) {
294         if (serviceDescription == null) {
295             // FIXME: Throw NPE?
296
return;
297         }
298         this.serviceDescription = serviceDescription;
299         //serviceDescription.setTypeMapping((TypeMapping)this.getTypeMappingRegistry().getDefaultTypeMapping());
300
}
301
302     public void setPropertyParent(Hashtable parent)
303     {
304         if (options == null) {
305             options = new LockableHashtable();
306         }
307         ((LockableHashtable)options).setParent(parent);
308     }
309
310     /**
311      * Generate WSDL. If we have a specific file configured in the
312      * ServiceDesc, just return that. Otherwise run through all the Handlers
313      * (including the provider) and call generateWSDL() on them via our
314      * parent's implementation.
315      */

316     public void generateWSDL(MessageContext msgContext) throws AxisFault {
317         if (serviceDescription == null ||
318                 serviceDescription.getWSDLFile() == null) {
319             super.generateWSDL(msgContext);
320             return;
321         }
322         InputStream JavaDoc instream = null;
323
324         // Got a WSDL file in the service description, so try and read it
325
try {
326             String JavaDoc filename= serviceDescription.getWSDLFile();
327             File JavaDoc file=new File JavaDoc(filename);
328             if(file.exists()) {
329                 //if this resolves to a file, load it
330
instream = new FileInputStream JavaDoc(filename);
331             } else if(msgContext.getStrProp(Constants.MC_HOME_DIR)!=null){
332                 String JavaDoc path = msgContext.getStrProp(Constants.MC_HOME_DIR) +'/' + filename;
333                 file = new File JavaDoc(path);
334                 if(file.exists()) {
335                     //if this resolves to a file, load it
336
instream = new FileInputStream JavaDoc(path);
337                 }
338             }
339             
340             if(instream == null) {
341                 //else load a named resource in our classloader.
342
instream = ClassUtils.getResourceAsStream(this.getClass(),filename);
343                 if (instream == null) {
344                     String JavaDoc errorText=Messages.getMessage("wsdlFileMissing",filename);
345                     throw new AxisFault(errorText);
346                 }
347             }
348             Document JavaDoc doc = XMLUtils.newDocument(instream);
349             msgContext.setProperty("WSDL", doc);
350         } catch (Exception JavaDoc e) {
351             throw AxisFault.makeFault(e);
352         } finally {
353             if(instream!=null) {
354                 try {
355                     instream.close();
356                 } catch (IOException JavaDoc e) { }
357             }
358         }
359     }
360     /*********************************************************************
361      * Administration and management APIs
362      *
363      * These can get called by various admin adapters, such as JMX MBeans,
364      * our own Admin client, web applications, etc...
365      *
366      *********************************************************************
367      */

368
369     /** Placeholder for "resume this service" method
370      */

371     public void start()
372     {
373         isRunning = true;
374     }
375
376     /** Placeholder for "suspend this service" method
377      */

378     public void stop()
379     {
380         isRunning = false;
381     }
382
383     /**
384      * Is this service suspended?
385      * @return
386      */

387     public boolean isRunning() {
388         return isRunning;
389     }
390     
391     /**
392      * Make this service available on a particular transport
393      */

394     public void enableTransport(String JavaDoc transportName)
395     {
396         if (log.isDebugEnabled()) {
397             log.debug(Messages.getMessage(
398                 "enableTransport00", "" + this, transportName));
399         }
400
401         if (validTransports == null)
402             validTransports = new Vector JavaDoc();
403         validTransports.addElement(transportName);
404     }
405
406     /**
407      * Disable access to this service from a particular transport
408      */

409     public void disableTransport(String JavaDoc transportName)
410     {
411         if (validTransports != null) {
412             validTransports.removeElement(transportName);
413         }
414     }
415
416     public boolean needsHighFidelityRecording() {
417         return highFidelityRecording;
418     }
419
420     public void setHighFidelityRecording(boolean highFidelityRecording) {
421         this.highFidelityRecording = highFidelityRecording;
422     }
423
424     // see org.apache.axis.attachments.Attachments
425
public int getSendType() {
426         return sendType;
427     }
428
429     public void setSendType(int sendType) {
430         this.sendType = sendType;
431     }
432
433     public void invoke(MessageContext msgContext) throws AxisFault {
434         HandlerInfoChainFactory handlerFactory = (HandlerInfoChainFactory) this.getOption(Constants.ATTR_HANDLERINFOCHAIN);
435         HandlerChainImpl handlerImpl = null;
436         if (handlerFactory != null) handlerImpl = (HandlerChainImpl) handlerFactory.createHandlerChain();
437         boolean result = true;
438
439         try {
440             if (handlerImpl != null) {
441                 try {
442                     result = handlerImpl.handleRequest(msgContext);
443                 }
444                 catch (SOAPFaultException JavaDoc e) {
445                     msgContext.setPastPivot(true);
446                     handlerImpl.handleFault(msgContext);
447                     return;
448                 }
449             }
450
451             if (result) {
452                 try {
453                     super.invoke(msgContext);
454                 } catch (AxisFault e) {
455                     msgContext.setPastPivot(true);
456                     if (handlerImpl != null) {
457                         handlerImpl.handleFault(msgContext);
458                     }
459                     throw e;
460                 }
461             } else {
462                 msgContext.setPastPivot(true);
463             }
464
465             if ( handlerImpl != null) {
466                 handlerImpl.handleResponse(msgContext);
467             }
468         } catch (SOAPFaultException JavaDoc e) {
469             msgContext.setPastPivot(true);
470             throw AxisFault.makeFault(e);
471
472         } catch (RuntimeException JavaDoc e) {
473             SOAPFault fault = new SOAPFault(new AxisFault("Server", "Server Error", null, null));
474             SOAPEnvelope env = new SOAPEnvelope();
475             env.addBodyElement(fault);
476             Message message = new Message(env);
477             message.setMessageType(Message.RESPONSE);
478             msgContext.setResponseMessage(message);
479             throw AxisFault.makeFault(e);
480         }
481         finally {
482             if (handlerImpl != null) {
483                 handlerImpl.destroy();
484             }
485         }
486     }
487 }
488
Popular Tags