Source code: org/apache/axis/server/AxisServer.java
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.server ;
18
19 import org.apache.axis.AxisEngine;
20 import org.apache.axis.AxisFault;
21 import org.apache.axis.AxisProperties;
22 import org.apache.axis.Constants;
23 import org.apache.axis.EngineConfiguration;
24 import org.apache.axis.Handler;
25 import org.apache.axis.Message;
26 import org.apache.axis.MessageContext;
27 import org.apache.axis.SimpleTargetedChain;
28 import org.apache.axis.message.SOAPEnvelope;
29 import org.apache.axis.soap.SOAPConstants;
30 import org.apache.axis.client.AxisClient;
31 import org.apache.axis.components.logger.LogFactory;
32 import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
33 import org.apache.axis.utils.ClassUtils;
34 import org.apache.axis.utils.Messages;
35 import org.apache.commons.logging.Log;
36
37 import java.util.Map;
38 /**
39 *
40 * @author Doug Davis (dug@us.ibm.com)
41 * @author Glen Daniels (gdaniels@allaire.com)
42 */
43 public class AxisServer extends AxisEngine
44 {
45 protected static Log log =
46 LogFactory.getLog(AxisServer.class.getName());
47 private static Log tlog =
48 LogFactory.getLog("org.apache.axis.TIME");
49
50 private static AxisServerFactory factory = null;
51
52 public static AxisServer getServer(Map environment) throws AxisFault
53 {
54 if (factory == null) {
55 String factoryClassName = AxisProperties.getProperty("axis.ServerFactory");
56 if (factoryClassName != null) {
57 try {
58 Class factoryClass = ClassUtils.forName(factoryClassName);
59 if (AxisServerFactory.class.isAssignableFrom(factoryClass))
60 factory = (AxisServerFactory)factoryClass.newInstance();
61 } catch (Exception e) {
62 // If something goes wrong here, should we just fall
63 // through and use the default one?
64 log.error(Messages.getMessage("exception00"), e);
65 }
66 }
67
68 if (factory == null) {
69 factory = new DefaultAxisServerFactory();
70 }
71 }
72
73 return factory.getServer(environment);
74 }
75
76 /**
77 * the AxisClient to be used by outcalling Services
78 */
79 private AxisEngine clientEngine;
80
81 public AxisServer()
82 {
83 this(EngineConfigurationFactoryFinder.newFactory().getServerEngineConfig());
84 }
85
86 public AxisServer(EngineConfiguration config)
87 {
88 super(config);
89 // Server defaults to persisting configuration
90 setShouldSaveConfig(true);
91 }
92
93 /** Is this server active? If this is false, any requests will
94 * cause a SOAP Server fault to be generated.
95 */
96 private boolean running = true;
97
98 public boolean isRunning() { return running; }
99
100 /** Start the server.
101 */
102 public void start()
103 {
104 // re-init...
105 init();
106 running = true;
107 }
108
109 /** Stop the server.
110 */
111 public void stop()
112 {
113 running = false;
114 }
115
116 /**
117 * Get this server's client engine. Create it if it does
118 * not yet exist.
119 */
120 public synchronized AxisEngine getClientEngine () {
121 if (clientEngine == null) {
122 clientEngine = new AxisClient(); // !!!!
123 }
124 return clientEngine;
125 }
126
127 /**
128 * Main routine of the AXIS server. In short we locate the appropriate
129 * handler for the desired service and invoke() it.
130 */
131 public void invoke(MessageContext msgContext) throws AxisFault {
132 long t0=0, t1=0, t2=0, t3=0, t4=0, t5=0;
133 if( tlog.isDebugEnabled() ) {
134 t0=System.currentTimeMillis();
135 }
136
137 if (log.isDebugEnabled()) {
138 log.debug("Enter: AxisServer::invoke");
139 }
140
141 if (!isRunning()) {
142 throw new AxisFault("Server.disabled",
143 Messages.getMessage("serverDisabled00"),
144 null, null);
145 }
146
147 String hName = null ;
148 Handler h = null ;
149
150 // save previous context
151 MessageContext previousContext = getCurrentMessageContext();
152
153 try {
154 // set active context
155 setCurrentMessageContext(msgContext);
156
157 hName = msgContext.getStrProp( MessageContext.ENGINE_HANDLER );
158 if ( hName != null ) {
159 if ( (h = getHandler(hName)) == null ) {
160 ClassLoader cl = msgContext.getClassLoader();
161 try {
162 log.debug( Messages.getMessage("tryingLoad00", hName) );
163 Class cls = ClassUtils.forName(hName, true, cl);
164 h = (Handler) cls.newInstance();
165 }
166 catch( Exception e ) {
167 h = null ;
168 }
169 }
170 if( tlog.isDebugEnabled() ) {
171 t1=System.currentTimeMillis();
172 }
173 if ( h != null )
174 h.invoke(msgContext);
175 else
176 throw new AxisFault( "Server.error",
177 Messages.getMessage("noHandler00", hName),
178 null, null );
179 if( tlog.isDebugEnabled() ) {
180 t2=System.currentTimeMillis();
181 tlog.debug( "AxisServer.invoke " + hName + " invoke=" +
182 ( t2-t1 ) + " pre=" + (t1-t0 ));
183 }
184
185 }
186 else {
187 // This really should be in a handler - but we need to discuss it
188 // first - to make sure that's what we want.
189 /* Now we do the 'real' work. The flow is basically: */
190 /* Transport Specific Request Handler/Chain */
191 /* Global Request Handler/Chain */
192 /* Protocol Specific-Handler(ie. SOAP, XP) */
193 /* ie. For SOAP Handler: */
194 /* - Service Specific Request Handler/Chain */
195 /* - SOAP Semantic Checks */
196 /* - Service Specific Response Handler/Chain */
197 /* Global Response Handler/Chain */
198 /* Transport Specific Response Handler/Chain */
199 /**************************************************************/
200
201 // When do we call init/cleanup??
202 if (log.isDebugEnabled()) {
203 log.debug(Messages.getMessage("defaultLogic00") );
204 }
205
206 /* This is what the entirety of this logic might evolve to:
207
208 hName = msgContext.getStrProp(MessageContext.TRANSPORT);
209 if ( hName != null ) {
210 if ((h = hr.find( hName )) != null ) {
211 h.invoke(msgContext);
212 } else {
213 log.error(Messages.getMessage("noTransport02", hName));
214 }
215 } else {
216 // No transport set, so use the default (probably just
217 // calls the global->service handlers)
218 defaultTransport.invoke(msgContext);
219 }
220
221 */
222
223 /* Process the Transport Specific Request Chain */
224 /**********************************************/
225 hName = msgContext.getTransportName();
226 SimpleTargetedChain transportChain = null;
227
228 if (log.isDebugEnabled())
229 log.debug(Messages.getMessage("transport01", "AxisServer.invoke", hName));
230
231 if( tlog.isDebugEnabled() ) {
232 t1=System.currentTimeMillis();
233 }
234 if ( hName != null && (h = getTransport( hName )) != null ) {
235 if (h instanceof SimpleTargetedChain) {
236 transportChain = (SimpleTargetedChain)h;
237 h = transportChain.getRequestHandler();
238 if (h != null)
239 h.invoke(msgContext);
240 }
241 }
242
243 if( tlog.isDebugEnabled() ) {
244 t2=System.currentTimeMillis();
245 }
246 /* Process the Global Request Chain */
247 /**********************************/
248 if ((h = getGlobalRequest()) != null ) {
249 h.invoke(msgContext);
250 }
251
252 /**
253 * At this point, the service should have been set by someone
254 * (either the originator of the MessageContext, or one of the
255 * transport or global Handlers). If it hasn't been set, we
256 * fault.
257 */
258 h = msgContext.getService();
259 if (h == null) {
260 // It's possible that we haven't yet parsed the
261 // message at this point. This is a kludge to
262 // make sure we have. There probably wants to be
263 // some kind of declarative "parse point" on the handler
264 // chain instead....
265 Message rm = msgContext.getRequestMessage();
266 rm.getSOAPEnvelope().getFirstBody();
267
268 h = msgContext.getService();
269 if (h == null)
270 throw new AxisFault("Server.NoService",
271 Messages.getMessage("noService05",
272 "" + msgContext.getTargetService()),
273 null, null );
274 }
275 if( tlog.isDebugEnabled() ) {
276 t3=System.currentTimeMillis();
277 }
278
279 initSOAPConstants(msgContext);
280 try {
281 h.invoke(msgContext);
282 } catch (AxisFault ae) {
283 if ((h = getGlobalRequest()) != null ) {
284 h.onFault(msgContext);
285 }
286 throw ae;
287 }
288
289 if( tlog.isDebugEnabled() ) {
290 t4=System.currentTimeMillis();
291 }
292
293 /* Process the Global Response Chain */
294 /***********************************/
295 if ((h = getGlobalResponse()) != null)
296 h.invoke(msgContext);
297
298 /* Process the Transport Specific Response Chain */
299 /***********************************************/
300 if (transportChain != null) {
301 h = transportChain.getResponseHandler();
302 if (h != null)
303 h.invoke(msgContext);
304 }
305
306 if( tlog.isDebugEnabled() ) {
307 t5=System.currentTimeMillis();
308 tlog.debug( "AxisServer.invoke2 " +
309 " preTr=" +
310 ( t1-t0 ) + " tr=" + (t2-t1 ) +
311 " preInvoke=" + ( t3-t2 ) +
312 " invoke=" + ( t4-t3 ) +
313 " postInvoke=" + ( t5-t4 ) +
314 " " + msgContext.getTargetService() + "." +
315 ((msgContext.getOperation( ) == null) ?
316 "" : msgContext.getOperation().getName()) );
317 }
318
319 }
320 } catch (AxisFault e) {
321 throw e;
322 } catch (Exception e) {
323 // Should we even bother catching it ?
324 throw AxisFault.makeFault(e);
325
326 } finally {
327 // restore previous state
328 setCurrentMessageContext(previousContext);
329 }
330
331 if (log.isDebugEnabled()) {
332 log.debug("Exit: AxisServer::invoke");
333 }
334 }
335
336 /**
337 * Extract ans store soap constants info from the envelope
338 * @param msgContext
339 * @throws AxisFault
340 */
341 private void initSOAPConstants(MessageContext msgContext) throws AxisFault {
342 Message msg = msgContext.getRequestMessage();
343 if (msg == null)
344 return;
345 SOAPEnvelope env = msg.getSOAPEnvelope();
346 if (env == null)
347 return;
348 SOAPConstants constants = env.getSOAPConstants();
349 if (constants == null)
350 return;
351 // Ensure that if we get SOAP1.2, then reply using SOAP1.2
352 msgContext.setSOAPConstants(constants);
353 }
354
355 /**
356 *
357 */
358 public void generateWSDL(MessageContext msgContext) throws AxisFault {
359 if (log.isDebugEnabled()) {
360 log.debug("Enter: AxisServer::generateWSDL");
361 }
362
363 if (!isRunning()) {
364 throw new AxisFault("Server.disabled",
365 Messages.getMessage("serverDisabled00"),
366 null, null);
367 }
368
369 String hName = null ;
370 Handler h = null ;
371
372 // save previous context
373 MessageContext previousContext = getCurrentMessageContext();
374
375 try {
376 // set active context
377 setCurrentMessageContext(msgContext);
378
379 hName = msgContext.getStrProp( MessageContext.ENGINE_HANDLER );
380 if ( hName != null ) {
381 if ( (h = getHandler(hName)) == null ) {
382 ClassLoader cl = msgContext.getClassLoader();
383 try {
384 log.debug( Messages.getMessage("tryingLoad00", hName) );
385 Class cls = ClassUtils.forName(hName, true, cl);
386 h = (Handler) cls.newInstance();
387 }
388 catch( Exception e ) {
389 throw new AxisFault(
390 "Server.error",
391 Messages.getMessage("noHandler00", hName),
392 null, null );
393 }
394 }
395 h.generateWSDL(msgContext);
396 }
397 else {
398 // This really should be in a handler - but we need to discuss it
399 // first - to make sure that's what we want.
400 /* Now we do the 'real' work. The flow is basically: */
401 /* Transport Specific Request Handler/Chain */
402 /* Global Request Handler/Chain */
403 /* Protocol Specific-Handler(ie. SOAP, XP) */
404 /* ie. For SOAP Handler: */
405 /* - Service Specific Request Handler/Chain */
406 /* - SOAP Semantic Checks */
407 /* - Service Specific Response Handler/Chain */
408 /* Global Response Handler/Chain */
409 /* Transport Specific Response Handler/Chain */
410 /**************************************************************/
411
412 // When do we call init/cleanup??
413 log.debug( Messages.getMessage("defaultLogic00") );
414
415 /* This is what the entirety of this logic might evolve to:
416
417 hName = msgContext.getStrProp(MessageContext.TRANSPORT);
418 if ( hName != null ) {
419 if ((h = hr.find( hName )) != null ) {
420 h.generateWSDL(msgContext);
421 } else {
422 log.error(Messages.getMessage("noTransport02", hName));
423 }
424 } else {
425 // No transport set, so use the default (probably just
426 // calls the global->service handlers)
427 defaultTransport.generateWSDL(msgContext);
428 }
429
430 */
431
432 /* Process the Transport Specific Request Chain */
433 /**********************************************/
434 hName = msgContext.getTransportName();
435 SimpleTargetedChain transportChain = null;
436
437 if (log.isDebugEnabled())
438 log.debug(Messages.getMessage("transport01",
439 "AxisServer.generateWSDL",
440 hName));
441 if ( hName != null && (h = getTransport( hName )) != null ) {
442 if (h instanceof SimpleTargetedChain) {
443 transportChain = (SimpleTargetedChain)h;
444 h = transportChain.getRequestHandler();
445 if (h != null) {
446 h.generateWSDL(msgContext);
447 }
448 }
449 }
450
451 /* Process the Global Request Chain */
452 /**********************************/
453 if ((h = getGlobalRequest()) != null )
454 h.generateWSDL(msgContext);
455
456 /**
457 * At this point, the service should have been set by someone
458 * (either the originator of the MessageContext, or one of the
459 * transport or global Handlers). If it hasn't been set, we
460 * fault.
461 */
462 h = msgContext.getService();
463 if (h == null) {
464 // It's possible that we haven't yet parsed the
465 // message at this point. This is a kludge to
466 // make sure we have. There probably wants to be
467 // some kind of declarative "parse point" on the handler
468 // chain instead....
469 Message rm = msgContext.getRequestMessage();
470 if (rm != null) {
471 rm.getSOAPEnvelope().getFirstBody();
472 h = msgContext.getService();
473 }
474 if (h == null) {
475 throw new AxisFault(Constants.QNAME_NO_SERVICE_FAULT_CODE,
476 Messages.getMessage("noService05",
477 "" + msgContext.getTargetService()),
478 null, null );
479 }
480 }
481
482 h.generateWSDL(msgContext);
483
484 /* Process the Global Response Chain */
485 /***********************************/
486 if ((h = getGlobalResponse()) != null )
487 h.generateWSDL(msgContext);
488
489 /* Process the Transport Specific Response Chain */
490 /***********************************************/
491 if (transportChain != null) {
492 h = transportChain.getResponseHandler();
493 if (h != null) {
494 h.generateWSDL(msgContext);
495 }
496 }
497 }
498 } catch (AxisFault e) {
499 throw e;
500 } catch(Exception e) {
501 // Should we even bother catching it ?
502 throw AxisFault.makeFault(e);
503 } finally {
504 // restore previous state
505 setCurrentMessageContext(previousContext);
506 }
507
508 if (log.isDebugEnabled()) {
509 log.debug("Exit: AxisServer::generateWSDL");
510 }
511 }
512 }