KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > axis > SoapServerImpl


1 /*
2  * Copyright 1999-2005 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 package org.apache.cocoon.components.axis;
17
18 import java.io.File JavaDoc;
19 import java.io.InputStreamReader JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import javax.servlet.ServletContext JavaDoc;
27 import javax.servlet.http.HttpServletRequest JavaDoc;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29
30 import org.apache.avalon.framework.activity.Initializable;
31 import org.apache.avalon.framework.activity.Startable;
32 import org.apache.avalon.framework.component.Component;
33 import org.apache.avalon.framework.component.ComponentException;
34 import org.apache.avalon.framework.component.ComponentManager;
35 import org.apache.avalon.framework.component.Composable;
36 import org.apache.avalon.framework.configuration.Configurable;
37 import org.apache.avalon.framework.configuration.Configuration;
38 import org.apache.avalon.framework.configuration.ConfigurationException;
39 import org.apache.avalon.framework.context.Context;
40 import org.apache.avalon.framework.context.ContextException;
41 import org.apache.avalon.framework.context.Contextualizable;
42 import org.apache.avalon.framework.logger.AbstractLogEnabled;
43 import org.apache.avalon.framework.thread.ThreadSafe;
44 import org.apache.axis.AxisEngine;
45 import org.apache.axis.Constants;
46 import org.apache.axis.EngineConfiguration;
47 import org.apache.axis.MessageContext;
48 import org.apache.axis.configuration.FileProvider;
49 import org.apache.axis.deployment.wsdd.WSDDDeployment;
50 import org.apache.axis.deployment.wsdd.WSDDDocument;
51 import org.apache.axis.deployment.wsdd.WSDDService;
52 import org.apache.axis.security.servlet.ServletSecurityProvider;
53 import org.apache.axis.server.AxisServer;
54 import org.apache.axis.transport.http.HTTPConstants;
55 import org.apache.axis.transport.http.HTTPTransport;
56 import org.apache.axis.transport.http.ServletEndpointContextImpl;
57 import org.apache.axis.utils.XMLUtils;
58 import org.apache.cocoon.components.axis.providers.AvalonProvider;
59 import org.apache.cocoon.util.IOUtils;
60 import org.apache.commons.lang.BooleanUtils;
61 import org.apache.excalibur.source.Source;
62 import org.apache.excalibur.source.SourceResolver;
63 import org.apache.excalibur.xml.dom.DOMParser;
64 import org.w3c.dom.Document JavaDoc;
65 import org.xml.sax.InputSource JavaDoc;
66
67 /**
68  * SOAP Server Implementation
69  *
70  * <p>
71  * This server accepts a SOAP Request, and generates the resultant
72  * response as output. Essentially, this reader allows you to serve SOAP
73  * requests from your Cocoon application.
74  * </p>
75  *
76  * <p>
77  * Code originates from the Apache
78  * <a HREF="http://xml.apache.org/axis">AXIS</a> project,
79  * <code>org.apache.axis.http.transport.AxisServlet</code>.
80  * </p>
81  *
82  * Ported to Cocoon by:
83  *
84  * @author <a HREF="mailto:crafterm@apache.org">Marcus Crafter</a>
85  *
86  * Original <code>AxisServlet</code> authors:
87  *
88  * @author <a HREF="mailto:">Steve Loughran</a>
89  * @author <a HREF="mailto:dug@us.ibm.com">Doug Davis</a>
90  *
91  * @version CVS $Id: SoapServerImpl.java 149132 2005-01-30 18:24:33Z cziegeler $
92  */

93 public class SoapServerImpl extends AbstractLogEnabled
94     implements SoapServer, Composable, Configurable, Contextualizable, Initializable,
95                Startable, ThreadSafe {
96
97     /**
98      * Constant describing the default location of the server configuration file
99      */

100     public static final String JavaDoc DEFAULT_SERVER_CONFIG
101         = "resource://org/apache/axis/server/server-config.wsdd";
102
103     // transport name
104
private String JavaDoc m_transportName;
105
106     // security provider reference
107
private ServletSecurityProvider m_securityProvider;
108
109     // JWS output directory
110
private String JavaDoc m_jwsClassDir;
111
112     // per-instance cache of the axis server
113
private AxisServer m_axisServer;
114
115     // axis server configuration
116
private FileProvider m_engineConfig;
117
118     // location of attachments
119
private String JavaDoc m_attachmentDir;
120
121     // server configuration
122
private Source m_serverWSDD;
123
124     // array containing locations to descriptors this reader should manage
125
private WSDDDocument[] m_descriptors;
126
127     // context reference
128
private Context JavaDoc context;
129
130     // component manager reference
131
private ComponentManager manager;
132
133     /* (non-Javadoc)
134      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
135      */

136     public void contextualize(final Context JavaDoc context)
137     throws ContextException {
138         this.context = context;
139     }
140
141     /* (non-Javadoc)
142      * @see org.apache.avalon.framework.component.Composable#compose(org.apache.avalon.framework.component.ComponentManager)
143      */

144     public void compose(ComponentManager manager)
145     throws ComponentException {
146         this.manager = manager;
147     }
148
149     /**
150      * Configures this server.
151      *
152      * <p>
153      * Sets the following optional configuration settings:
154      *
155      * <ul>
156      * <li>Server WSDD configuration
157      * <li>Attachment directory
158      * <li>JWS directory
159      * <li>Security provider
160      * <li>Transport name
161      * <li>Mananged services
162      * </ul>
163      * </p>
164      *
165      * <p>
166      * The following format is used:
167      * <pre>
168      * &lt;soap-server&gt;
169      * &lt;server-wsdd SRC="..."/&gt;
170      * &lt;attachment-dir SRC="..."/&gt;
171      * &lt;jws-dir SRC="..."/&gt;
172      * &lt;security-provider enabled="..."/&gt;
173      * &lt;transport name="..."/&gt;
174      * &lt;managed-services&gt;
175      * &lt;descriptor SRC="..."/&gt;
176      * &lt;descriptor SRC="..."/&gt;
177      * &lt;/managed-services&gt;
178      * &lt;/soap-server&gt;
179      * </pre>
180      * </p>
181      *
182      * @param config a <code>Configuration</code> instance
183      * @exception ConfigurationException if an error occurs
184      */

185     public void configure(final Configuration config)
186     throws ConfigurationException {
187         try {
188             setServerConfig(config);
189             setAttachmentDir(config);
190             setJWSDir(config);
191             setSecurityProvider(config);
192             setTransportName(config);
193             setManagedServices(config);
194
195             if (getLogger().isDebugEnabled()) {
196                 getLogger().debug("SoapServerImpl.configure() complete");
197             }
198         } catch (final Exception JavaDoc e) {
199             throw new ConfigurationException("Error during configuration", e);
200         }
201     }
202
203     /**
204      * Helper method to set the axis server configuration.
205      *
206      * @param config a <code>Configuration</code> instance
207      * @exception Exception if an error occurs
208      */

209     public void setServerConfig(final Configuration config)
210     throws Exception JavaDoc {
211         final Configuration wsdd = config.getChild("server-wsdd");
212         SourceResolver resolver = null;
213
214         try {
215             resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
216             m_serverWSDD =
217                 resolver.resolveURI(
218                     wsdd.getAttribute("src", DEFAULT_SERVER_CONFIG)
219                 );
220         } finally {
221             this.manager.release(resolver);
222         }
223     }
224
225     /**
226      * Helper method to set the attachment dir. If no attachment directory has
227      * been specified, then its set up to operate out of the Cocoon workarea.
228      *
229      * @param config a <code>Configuration</code> instance
230      * @exception ConfigurationException if a configuration error occurs
231      * @exception ContextException if a context error occurs
232      */

233     private void setAttachmentDir(final Configuration config)
234     throws ConfigurationException, ContextException {
235         final Configuration dir = config.getChild("attachment-dir");
236         m_attachmentDir = dir.getAttribute("src", null);
237
238         if (m_attachmentDir == null) {
239             File JavaDoc workDir =
240                 (File JavaDoc) this.context.get(org.apache.cocoon.Constants.CONTEXT_WORK_DIR);
241             File JavaDoc attachmentDir =
242                 IOUtils.createFile(workDir, "attachments" + File.separator);
243             m_attachmentDir = IOUtils.getFullFilename(attachmentDir);
244         }
245
246         if (getLogger().isDebugEnabled()) {
247             getLogger().debug("attachment directory = " + m_attachmentDir);
248         }
249     }
250
251     /**
252      * Helper method to set the JWS class dir. If no directory is specified then
253      * the directory <i>axis-jws</i> is used, under the Cocoon workarea.
254      *
255      * @param config a <code>Configuration</code> instance
256      * @exception ConfigurationException if a configuration error occurs
257      * @exception ContextException if a context error occurs
258      */

259     private void setJWSDir(final Configuration config)
260     throws ConfigurationException, ContextException {
261         final Configuration dir = config.getChild("jws-dir");
262         m_jwsClassDir = dir.getAttribute("src", null);
263
264         if (m_jwsClassDir == null) {
265             File JavaDoc workDir =
266                 (File JavaDoc) this.context.get(org.apache.cocoon.Constants.CONTEXT_WORK_DIR);
267             File JavaDoc jwsClassDir =
268                 IOUtils.createFile(workDir, "axis-jws" + File.separator);
269             m_jwsClassDir = IOUtils.getFullFilename(jwsClassDir);
270         }
271
272         if (getLogger().isDebugEnabled()) {
273             getLogger().debug("jws class directory = " + m_jwsClassDir);
274         }
275     }
276
277     /**
278      * Helper method to set the security provider.
279      *
280      * @param config a <code>Configuration</code> instance
281      * @exception ConfigurationException if an error occurs
282      */

283     private void setSecurityProvider(final Configuration config)
284     throws ConfigurationException {
285         final Configuration secProvider =
286             config.getChild("security-provider", false);
287
288         if (secProvider != null) {
289             final String JavaDoc attr = secProvider.getAttribute("enabled");
290             final boolean providerIsEnabled = BooleanUtils.toBoolean(attr);
291
292             if (providerIsEnabled) {
293                 m_securityProvider = new ServletSecurityProvider();
294             }
295         }
296
297         if (getLogger().isDebugEnabled()) {
298             getLogger().debug("security provider = " + m_securityProvider);
299         }
300     }
301
302     /**
303      * Helper method to set the transport name
304      *
305      * @param config a <code>Configuration</code> instance
306      * @exception ConfigurationException if an error occurs
307      */

308     private void setTransportName(final Configuration config)
309     throws ConfigurationException {
310         final Configuration name = config.getChild("transport");
311         m_transportName =
312             name.getAttribute("name", HTTPTransport.DEFAULT_TRANSPORT_NAME);
313     }
314
315     /**
316      * Helper method to obtain a list of managed services from the given
317      * configuration (ie. locations of deployement descriptors to be
318      * deployed).
319      *
320      * @param config a <code>Configuration</code> value
321      * @exception Exception if an error occurs
322      */

323     private void setManagedServices(final Configuration config)
324     throws Exception JavaDoc {
325         final Configuration m = config.getChild("managed-services", false);
326         final List JavaDoc descriptors = new ArrayList JavaDoc();
327
328         if (m != null) {
329             SourceResolver resolver = null;
330             DOMParser parser = null;
331
332             try {
333                 final Configuration[] services = m.getChildren("descriptor");
334                 resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
335                 parser = (DOMParser) this.manager.lookup(DOMParser.ROLE);
336
337                 for (int i = 0; i < services.length; ++i) {
338                     final String JavaDoc location = services[i].getAttribute("src");
339                     Source source = resolver.resolveURI(location);
340
341                     final Document d =
342                         parser.parseDocument(
343                             new InputSource JavaDoc(
344                                 new InputStreamReader JavaDoc(source.getInputStream())
345                             )
346                         );
347
348                     descriptors.add(new WSDDDocument(d));
349                 }
350             } finally {
351                 this.manager.release(resolver);
352                 this.manager.release((Component)parser);
353             }
354         }
355
356         // convert the list of descriptors to an array, for easier iteration
357
m_descriptors =
358             (WSDDDocument[]) descriptors.toArray(new WSDDDocument[]{});
359     }
360
361     /* (non-Javadoc)
362      * @see org.apache.avalon.framework.activity.Initializable#initialize()
363      */

364     public void initialize()
365     throws Exception JavaDoc {
366         m_axisServer = createEngine();
367
368         if (getLogger().isDebugEnabled()) {
369             getLogger().debug("SoapServerImpl.initialize() complete");
370         }
371     }
372
373     /**
374      * Starts this server. Deploys all managed services as specified at
375      * configuration time.
376      *
377      * @exception Exception if an error occurs
378      */

379     public void start()
380     throws Exception JavaDoc {
381         // deploy all configured services
382
for (int i = 0; i < m_descriptors.length; ++i) {
383             WSDDDeployment deployment = m_engineConfig.getDeployment();
384             m_descriptors[i].deploy(deployment);
385
386             if (getLogger().isDebugEnabled()) {
387                 getLogger().debug(
388                     "Deployed Descriptor:\n" +
389                     XMLUtils.DocumentToString(m_descriptors[i].getDOMDocument())
390                 );
391             }
392         }
393
394         if (getLogger().isDebugEnabled()) {
395             getLogger().debug("SoapServerImpl.start() complete");
396         }
397     }
398
399     /**
400      * Stops this reader. Undeploys all managed services this reader
401      * currently manages (includes services dynamically added to the reader
402      * during runtime).
403      *
404      * @exception Exception if an error occurs
405      */

406     public void stop()
407     throws Exception JavaDoc {
408         WSDDDeployment deployment = m_engineConfig.getDeployment();
409         WSDDService[] services = deployment.getServices();
410
411         // undeploy all deployed services
412
for (int i = 0; i < services.length; ++i) {
413             deployment.undeployService(services[i].getQName());
414
415             if (getLogger().isDebugEnabled()) {
416                 getLogger().debug("Undeployed: " + services[i].toString());
417             }
418         }
419
420         if (getLogger().isDebugEnabled()) {
421             getLogger().debug("SoapServerImpl.stop() complete");
422         }
423     }
424
425     /* (non-Javadoc)
426      * @see org.apache.cocoon.components.axis.SoapServer#invoke(org.apache.axis.MessageContext)
427      */

428     public void invoke(MessageContext message)
429     throws Exception JavaDoc {
430         m_axisServer.invoke(message);
431     }
432
433     /**
434      * Place the Request message in the MessagContext object - notice
435      * that we just leave it as a 'ServletRequest' object and let the
436      * Message processing routine convert it - we don't do it since we
437      * don't know how it's going to be used - perhaps it might not
438      * even need to be parsed.
439      */

440     public MessageContext createMessageContext(
441         HttpServletRequest JavaDoc req,
442         HttpServletResponse JavaDoc res,
443         ServletContext JavaDoc con) {
444
445         MessageContext msgContext = new MessageContext(m_axisServer);
446         String JavaDoc webInfPath = con.getRealPath("/WEB-INF");
447         String JavaDoc homeDir = con.getRealPath("/");
448
449         // Set the Transport
450
msgContext.setTransportName(m_transportName);
451
452         // Add Avalon specifics to MessageContext
453
msgContext.setProperty(LOGGER, getLogger());
454         msgContext.setProperty(AvalonProvider.COMPONENT_MANAGER, this.manager);
455
456         // Save some HTTP specific info in the bag in case someone needs it
457
msgContext.setProperty(Constants.MC_JWS_CLASSDIR, m_jwsClassDir);
458         msgContext.setProperty(Constants.MC_HOME_DIR, homeDir);
459         msgContext.setProperty(Constants.MC_RELATIVE_PATH, req.getServletPath());
460         msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this );
461         msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req );
462         msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res );
463         msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION, webInfPath);
464         msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO,
465                                req.getPathInfo() );
466         msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION,
467                                req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
468         msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr());
469
470
471         // Set up a javax.xml.rpc.server.ServletEndpointContext
472
ServletEndpointContextImpl sec = new ServletEndpointContextImpl();
473         msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);
474
475         // Save the real path
476
String JavaDoc realpath = con.getRealPath(req.getServletPath());
477
478         if (realpath != null) {
479             msgContext.setProperty(Constants.MC_REALPATH, realpath);
480         }
481
482         msgContext.setProperty(Constants.MC_CONFIGPATH, webInfPath);
483
484         if (m_securityProvider != null) {
485             msgContext.setProperty("securityProvider", m_securityProvider);
486         }
487
488         // write out the contents of the message context for debugging purposes
489
if (getLogger().isDebugEnabled()) {
490             debugMessageContext(msgContext);
491         }
492
493         return msgContext;
494     }
495
496     /**
497      * Helper method to log the contents of a given message context
498      *
499      * @param context a <code>MessageContext</code> instance
500      */

501     private void debugMessageContext(final MessageContext context) {
502         for (final Iterator JavaDoc i = context.getPropertyNames(); i.hasNext(); ) {
503             final String JavaDoc key = (String JavaDoc) i.next();
504             getLogger().debug(
505                 "MessageContext: Key:" + key + ": Value: " + context.getProperty(key)
506             );
507         }
508     }
509
510
511     /**
512      * This is a uniform method of initializing AxisServer in a servlet
513      * context.
514      */

515     public AxisServer createEngine()
516     throws Exception JavaDoc {
517         AxisServer engine = AxisServer.getServer(getEngineEnvironment());
518
519         if (getLogger().isDebugEnabled()) {
520             getLogger().debug("Axis engine created");
521         }
522
523         return engine;
524     }
525
526     protected Map JavaDoc getEngineEnvironment()
527     throws Exception JavaDoc {
528         Map JavaDoc env = new HashMap JavaDoc();
529
530         // use FileProvider directly with a Avalon Source object instead of going
531
// through the EngineConfigurationFactoryServlet class
532
m_engineConfig = new FileProvider(m_serverWSDD.getInputStream());
533
534         env.put(EngineConfiguration.PROPERTY_NAME, m_engineConfig);
535         env.put(AxisEngine.ENV_ATTACHMENT_DIR, m_attachmentDir);
536         // REVISIT(MC): JNDI Factory support ?
537
//env.put(AxisEngine.ENV_SERVLET_CONTEXT, context);
538

539         return env;
540     }
541 }
542
Popular Tags