KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > turbine > Turbine


1 package org.apache.turbine;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001-2002 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" and
29  * "Apache Turbine" must not be used to endorse or promote products
30  * derived from this software without prior written permission. For
31  * written permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * "Apache Turbine", nor may "Apache" appear in their name, without
35  * prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56
57 import java.io.BufferedReader JavaDoc;
58 import java.io.File JavaDoc;
59 import java.io.FileInputStream JavaDoc;
60 import java.io.FileNotFoundException JavaDoc;
61 import java.io.FileReader JavaDoc;
62 import java.io.InputStream JavaDoc;
63 import java.io.InputStreamReader JavaDoc;
64 import java.io.IOException JavaDoc;
65 import java.io.Reader JavaDoc;
66 import java.util.Date JavaDoc;
67 import java.util.Iterator JavaDoc;
68 import java.util.Properties JavaDoc;
69
70 import javax.servlet.ServletConfig JavaDoc;
71 import javax.servlet.ServletContext JavaDoc;
72 import javax.servlet.ServletException JavaDoc;
73 import javax.servlet.http.HttpServlet JavaDoc;
74 import javax.servlet.http.HttpServletRequest JavaDoc;
75 import javax.servlet.http.HttpServletResponse JavaDoc;
76
77 import org.apache.commons.configuration.Configuration;
78 import org.apache.commons.configuration.ConfigurationFactory;
79 import org.apache.commons.configuration.PropertiesConfiguration;
80 import org.apache.commons.http.HttpUtils;
81 import org.apache.commons.lang.StringUtils;
82 import org.apache.commons.lang.exception.ExceptionUtils;
83 import org.apache.commons.logging.Log;
84 import org.apache.commons.logging.LogFactory;
85 import org.apache.fulcrum.ServiceManager;
86 import org.apache.fulcrum.TurbineServices;
87 import org.apache.log4j.PropertyConfigurator;
88 import org.apache.turbine.modules.ModuleLoader;
89 import org.apache.turbine.pipeline.TurbinePipeline;
90 import org.apache.turbine.services.rundata.RunDataService;
91
92 import com.thoughtworks.xstream.XStream;
93 import com.thoughtworks.xstream.io.xml.DomDriver;
94
95 /**
96  * Turbine is the main servlet for the entire system. It is <code>final</code>
97  * because you should <i>not</i> ever need to subclass this servlet. If you
98  * need to perform initialization of a service, then you should implement the
99  * Services API and let your code be initialized by it.
100  * If you need to override something in the <code>doGet()</code> or
101  * <code>doPost()</code> methods, edit the TurbineResources.properties file and
102  * specify your own classes there.
103  *
104  * <p> Turbine servlet recognizes the following initialization parameters.
105  *
106  * <ul>
107  * <li><code>properties</code> the path to TurbineResources.properties file
108  * used by the default implementation of <code>ResourceService</code>, relative
109  * to the application root.</li>
110  * <li><code>basedir</code> this parameter is used <strong>only</strong> if your
111  * application server does not support web applications, or the or does not
112  * support <code>ServletContext.getRealPath(String)</code> method correctly.
113  * You can use this parameter to specify the directory within the server's
114  * filesystem, that is the base of your web application.</li>
115  * </ul><br>
116  *
117  * If this servlet will always be invoked from another, set the TR.prop
118  * turbine.mode = integrated. If this servlet will operate in a mixed
119  * case of standalone and integrated, set turbine.mode = standalone and
120  * integrated operation can be specified on a request basis by
121  * <code>request.setAttribute("org.apache.turbine.integrated.request.key",
122  * Boolean.TRUE);</code> prior to passing control to this servlet.
123  *
124  * @author <a HREF="mailto:jon@latchkey.com">Jon S. Stevens</a>
125  * @author <a HREF="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
126  * @author <a HREF="mailto:greg@shwoop.com">Greg Ritter</a>
127  * @author <a HREF="mailto:jmcnally@collab.net">John D. McNally</a>
128  * @author <a HREF="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
129  * @author <a HREF="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
130  * @author <a HREF="mailto:jvanzyl@apache.org">Jason van Zyl</a>
131  * @author <a HREF="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
132  * @author <a HREF="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
133  * @version $Id: Turbine.java,v 1.51 2004/11/03 08:56:41 epugh Exp $
134  */

135 public class Turbine
136     extends HttpServlet JavaDoc
137     implements TurbineConstants
138 {
139     /** Logging class from commons.logging */
140     private static Log log = LogFactory.getLog(Turbine.class);
141
142     /**
143      * In certain situations the init() method is called more than once,
144      * somtimes even concurrently. This causes bad things to happen,
145      * so we use this flag to prevent it.
146      */

147     private static boolean firstInit = true;
148
149     /**
150      * Whether init succeeded or not.
151      */

152     private static Throwable JavaDoc initFailure = null;
153
154     /**
155      * Should initialization activities be performed during doGet()
156      * execution?
157      */

158     private static boolean firstDoGet = true;
159
160     /**
161      * Turbine application configuration.
162      */

163     private static Configuration configuration;
164
165     /**
166      * This init method will load the default resources from a
167      * properties file.
168      *
169      * @param config typical Servlet initialization parameter.
170      * @exception ServletException a servlet exception.
171      */

172     public final void init(ServletConfig JavaDoc config)
173         throws ServletException JavaDoc
174     {
175         super.init(config);
176
177         synchronized ( this.getClass() )
178         {
179             if (!firstInit)
180             {
181                 log.warn("Double initializaton of Turbine was attempted!");
182                 return;
183             }
184             // executing init will trigger some static initializers, so we have
185
// only one chance.
186
firstInit = false;
187
188             try
189             {
190                 // Setup static configuration (using default properties file).
191
ServletContext JavaDoc context = config.getServletContext();
192
193                 configure(config, context);
194             }
195             catch ( Exception JavaDoc e )
196             {
197                 // save the exception to complain loudly later :-)
198
initFailure = e;
199                 System.err.println(ExceptionUtils.getStackTrace(e));
200                 log.info("init failed: " + ExceptionUtils.getStackTrace(e));
201                 return;
202             }
203             log.info("init complete, Ready to Rumble!");
204         }
205     }
206
207     /**
208      * Initializes the services which need <code>RunData</code> to
209      * initialize themselves (post startup).
210      *
211      * @param data The first <code>GET</code> request.
212      */

213     public final void init(RunData data)
214     {
215         synchronized (Turbine.class)
216         {
217             if (firstDoGet)
218             {
219                 // All we want to do here is save some servlet
220
// information so that services and processes
221
// that don't have direct access to a RunData
222
// object can still know something about
223
// the servlet environment.
224
saveServletInfo(data);
225
226                 // Mark that we're done.
227
firstDoGet = false;
228             }
229         }
230     }
231
232     /**
233      * The <code>Servlet</code> destroy method. Invokes
234      * <code>ServiceBroker</code> tear down method.
235      */

236     public final void destroy()
237     {
238         // Shut down all Turbine Services.
239
TurbineServices.getInstance().shutdownServices();
240         System.gc();
241
242         // Allow turbine to be started back up again.
243
firstInit = true;
244
245         log.info("Done shutting down!");
246     }
247
248     /**
249      * The primary method invoked when the Turbine servlet is executed.
250      *
251      * @param req Servlet request.
252      * @param res Servlet response.
253      * @exception IOException a servlet exception.
254      * @exception ServletException a servlet exception.
255      */

256     public final void doGet (HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
257         throws IOException JavaDoc,
258                ServletException JavaDoc
259     {
260         // Placeholder for the RunData object.
261
RunData data = null;
262         try
263         {
264             // Check to make sure that we started up properly.
265
if (initFailure != null)
266             {
267                 throw initFailure;
268             }
269
270             // Get general RunData here...
271
// Perform turbine specific initialization below.
272
// look for a RunData in the request, in the event this servlet
273
// was called from another servlet that already started
274
// processing the request
275
data = (RunData)req.getAttribute(RUNDATA_REQUEST_KEY);
276             if ( data == null )
277             {
278                 data = runDataService.getRunData(req, res, getServletConfig());
279             }
280             else
281             {
282                 data.setRequest(req);
283                 data.setResponse(res);
284             }
285
286
287             // If this is the first invocation, perform some
288
// initialization. Certain services need RunData to initialize
289
// themselves.
290
if (firstDoGet)
291             {
292                 init(data);
293             }
294
295             // Stages of Pipeline implementation execution
296
// configurable via attached Valve implementations in a
297
// XML properties file.
298
pipeline.invoke(data);
299
300             /*
301             TODO: Move this logic into the pipeline.
302
303             // Handle the case where a module may want to send
304             // a redirect.
305             if (( data.getStatusCode() == 301 ||
306                   data.getStatusCode() == 302 ) &&
307                   data.getRedirectURI() != null )
308             {
309                 data.getResponse().sendRedirect(data.getRedirectURI());
310             }
311             */

312         }
313         catch (Throwable JavaDoc t)
314         {
315             handleException(data, req, res, t);
316         }
317         finally
318         {
319             // if the RunData has been added to the request, we assume
320
// Turbine is being invoked from another servlet that will
321
// handle returning the RunData.
322
if ( req.getAttribute(RUNDATA_REQUEST_KEY) == null )
323             {
324                 // Return the used RunData to the factory for recycling.
325
runDataService.putRunData(data);
326             }
327         }
328     }
329
330     /**
331      * In this application doGet and doPost are the same thing.
332      *
333      * @param req Servlet request.
334      * @param res Servlet response.
335      * @exception IOException a servlet exception.
336      * @exception ServletException a servlet exception.
337      */

338     public final void doPost (HttpServletRequest JavaDoc req,
339                               HttpServletResponse JavaDoc res)
340         throws IOException JavaDoc,
341                ServletException JavaDoc
342     {
343         doGet(req, res);
344     }
345
346     /**
347      * Return the servlet info.
348      *
349      * @return a string with the servlet information.
350      */

351     public final String JavaDoc getServletInfo()
352     {
353         return "Turbine Servlet @VERSION@";
354     }
355
356     /**
357      * This method is about making sure that we catch and display
358      * errors to the screen in one fashion or another. What happens is
359      * that it will attempt to show the error using your user defined
360      * Error Screen. If that fails, then it will resort to just
361      * displaying the error and logging it all over the place
362      * including the servlet engine log file, the Turbine log file and
363      * on the screen.
364      *
365      * @param data A Turbine RunData object.
366      * @param req Servlet request.
367      * @param res Servlet response.
368      * @param t The exception to report.
369      */

370     private final void handleException(RunData data,
371                                        HttpServletRequest JavaDoc req,
372                                        HttpServletResponse JavaDoc res,
373                                        Throwable JavaDoc t)
374         throws ServletException JavaDoc
375     {
376         // make sure that the stack trace makes it the log
377
log.error("handleException: " + t.getMessage(), t);
378
379         try
380         {
381             exceptionHandler.handleException( data, t );
382         }
383         catch (ServletException JavaDoc e)
384         {
385             if ( INTEGRATED.equals(configuration.getString(MODE)) ||
386                  req.getAttribute(INTEGRATED_REQUEST_KEY) != null )
387             {
388                 // let the invoking application deal with it
389
throw e;
390             }
391             else
392             {
393                 handleExceptionHandlerException(data, res, e, t);
394             }
395         }
396         catch (Exception JavaDoc f)
397         {
398             handleExceptionHandlerException(data, res, f, t);
399         }
400     }
401
402     private void handleExceptionHandlerException(RunData data,
403                                                  HttpServletResponse JavaDoc res,
404                                                  Exception JavaDoc f,
405                                                  Throwable JavaDoc t)
406     {
407         log.error( "Failed to dispatch to exception handler", f );
408
409         String JavaDoc mimeType = "text/plain";
410         try
411         {
412             // TODO: Make output formatting more flexible --
413
// what's below was to remove the use of ECS.
414
String JavaDoc trace = ExceptionUtils.getStackTrace(t);
415             data.setStackTrace(trace,t);
416             res.setContentType(data.getContentType());
417             res.setStatus(data.getStatusCode());
418             data.getOut().print("<pre>\n" + trace + "\n</pre>");
419         }
420         // Catch this one because it occurs if some code hasn't been
421
// completely re-compiled after a change..
422
catch ( java.lang.NoSuchFieldError JavaDoc e )
423         {
424             try
425             {
426                 res.setContentType( mimeType );
427                 res.setStatus ( 200 );
428             }
429             catch (Exception JavaDoc ignored) {}
430
431             try
432             {
433                 data.getOut().print ("java.lang.NoSuchFieldError: " +
434                                      "Please recompile all of your " +
435                                      "source code.");
436             }
437             catch (IOException JavaDoc ignored) {}
438
439             log.info ( data.getStackTrace() );
440             log.error ( e.getMessage(), e );
441         }
442         // Attempt to do *something* at this point...
443
catch ( Throwable JavaDoc reallyScrewedNow )
444         {
445             StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
446             msg.append("Horrible Exception: ");
447             if (data != null)
448             {
449                 msg.append(data.getStackTrace());
450             }
451             else
452             {
453                 msg.append(t);
454             }
455             try
456             {
457                 res.setContentType( mimeType );
458                 res.setStatus ( 200 );
459                 res.getWriter().print (msg.toString());
460             }
461             catch (Exception JavaDoc ignored)
462             {
463             }
464             log.error(reallyScrewedNow.getMessage(), reallyScrewedNow);
465         }
466     }
467
468     // These can probably go into a helper class that
469
// the main Turbine class could use. It would probably
470
// be wise to build up an contract that is accessible
471
// via the Turbine class so that we can try to develop
472
// a single point of access for our users. We can
473
// slowly start closing off some of our exposed
474
// internals.
475
//
476
// This is information that is collected from
477
// the first request. This information is used by
478
// services that previously needed to be initialized
479
// with a RunData object. These values are in no
480
// way meant to be used on a per request basis.
481
//
482
// There are only a couple of services that needed
483
// RunData for initialization but these values are
484
// very useful to processes which have no direct
485
// access to a RunData object. A scheduled job,
486
// for example, might want to process something
487
// and place it within the webapp space. Having
488
// these values stored here makes this possible.
489

490     /**
491      * Server name.
492      */

493     private static String JavaDoc serverName;
494
495     /**
496      * Server port.
497      */

498     private static String JavaDoc serverPort;
499
500     /**
501      * Server scheme.
502      */

503     private static String JavaDoc serverScheme;
504
505     /**
506      * Script name.
507      */

508     private static String JavaDoc scriptName;
509
510     /**
511      * Application root. The base directory for the
512      * application. In this case the webapp root in
513      * the servlet container.
514      */

515     private static String JavaDoc applicationRoot;
516
517     /**
518      * Servlet config for this Turbine webapp.
519      */

520     private static ServletConfig JavaDoc servletConfig;
521
522     /**
523      * Servlet context for this Turbine webapp.
524      */

525     private static ServletContext JavaDoc servletContext;
526
527     /**
528      * ModuleLoader for this Turbine webapp. Eventually
529      * there will be one per app, but we want to
530      * move gradually.
531      */

532     private static ModuleLoader moduleLoader;
533
534     private static Resolver resolver;
535
536     private static ExceptionHandler exceptionHandler;
537
538     private static Pipeline pipeline;
539
540     private static RunDataService runDataService;
541
542     /**
543      * A static configuration method that is called by the Turbine servlet
544      * or by non-servlet applications for configuring Turbine. It loads
545      * the default resources from a properties file.
546      *
547      * @param config Initialization parameters specific to the Turbine
548      * servlet.
549      * @param context Servlet container communication channel.
550      * Provides access to global initialization parameters.
551      * @exception Exception a generic exception.
552      */

553     public static synchronized void configure(ServletConfig JavaDoc config,
554                                               ServletContext JavaDoc context)
555         throws Exception JavaDoc
556     {
557         try
558         {
559         // Set the application root. This defaults to the webapp
560
// context if not otherwise set.
561
applicationRoot =
562             findInitParameter(context, config, APPLICATION_ROOT, null);
563
564         if (applicationRoot == null || applicationRoot.equals(WEB_CONTEXT))
565         {
566             applicationRoot = config.getServletContext().getRealPath("");
567         }
568
569         // Set the applicationRoot for this webapp.
570
setApplicationRoot(applicationRoot);
571
572         // Once we have the application root, we will create
573
// any of the directories that are required during
574
// runtime. Right now this creates the directories
575
// for logging but we might have more of these
576
// directories in the future.
577
createRuntimeDirectories(context, config);
578
579
580
581
582
583         // We want to save the ServletConfig and
584
// ServletContext so that we can share these objects
585
// with parts of Turbine that may need access and
586
// have no direct contact with RunData. Right now
587
// the ServletService is providing this information,
588
// but that service could disappear and client code
589
// could use the methods now provided in the Turbine
590
// class.
591
setTurbineServletConfig(config);
592         setTurbineServletContext(context);
593
594         // Get the instance of the service manager
595
ServiceManager serviceManager = TurbineServices.getInstance();
596
597         // Set the service managers application root. In our
598
// case it is the webapp context.
599
serviceManager.setApplicationRoot(getApplicationRoot());
600
601
602         //
603
// Now we run the Turbine configuration code. There are two ways
604
// to configure Turbine:
605
//
606
// a) By supplying an web.xml init parameter called "configuration"
607
//
608
// <init-param>
609
// <param-name>configuration</param-name>
610
// <param-value>/WEB-INF/conf/turbine.xml</param-value>
611
// </init-param>
612
//
613
// This loads an XML based configuration file.
614
//
615
// b) By supplying an web.xml init parameter called "properties"
616
//
617
// <init-param>
618
// <param-name>properties</param-name>
619
// <param-value>/WEB-INF/conf/TurbineResources.properties</param-value>
620
// </init-param>
621
//
622
// This loads a Properties based configuration file. Actually, these are
623
// extended properties as provided by commons-configuration
624
//
625
// If neither a) nor b) is supplied, Turbine will fall back to the
626
// known behaviour of loading a properties file called
627
// /WEB-INF/conf/TurbineResources.properties relative to the
628
// web application root.
629

630         String JavaDoc confFile= findInitParameter(context, config,
631                 TurbineConfig.CONFIGURATION_PATH_KEY,
632                 null);
633
634         String JavaDoc confPath;
635         String JavaDoc confStyle = "unset";
636
637         if (StringUtils.isNotEmpty(confFile))
638         {
639             confPath = getRealPath(confFile);
640             ConfigurationFactory configurationFactory = new ConfigurationFactory(confPath);
641             configurationFactory.setBasePath(getApplicationRoot());
642             configuration = configurationFactory.getConfiguration();
643             confStyle = "XML";
644         }
645         else
646         {
647             confFile = findInitParameter(context, config,
648                     TurbineConfig.PROPERTIES_KEY,
649             "TurbineResources.properties");
650
651             confPath = getRealPath(confFile);
652
653             // This should eventually be a Configuration
654
// interface so that service and app configuration
655
// can be stored anywhere.
656
configuration = (Configuration) new PropertiesConfiguration(confPath);
657             confStyle = "Properties";
658         }
659
660         // We want to set a few values in the configuration so
661
// that ${variable} interpolation will work for
662
//
663
// ${applicationRoot}
664
// ${webappRoot}
665
configuration.setProperty(APPLICATION_ROOT, applicationRoot);
666         configuration.setProperty(WEBAPP_ROOT,
667             config.getServletContext().getRealPath(""));
668
669 //
670
// Set up logging as soon as possible
671
//
672
String JavaDoc log4jFile = configuration.getString(LOG4J_CONFIG_FILE,
673                 LOG4J_CONFIG_FILE_DEFAULT);
674
675         log4jFile = getRealPath(log4jFile);
676
677         //
678
// Load the config file above into a Properties object and
679
// fix up the Application root
680
//
681
Properties JavaDoc p = new Properties JavaDoc();
682         try
683         {
684             p.load(new FileInputStream JavaDoc(log4jFile));
685             p.setProperty(APPLICATION_ROOT, getApplicationRoot());
686             PropertyConfigurator.configure(p);
687
688             //
689
// Rebuild our log object with a configured commons-logging
690
log = LogFactory.getLog(Turbine.class.getName());
691
692             log.info("Configured log4j from " + log4jFile);
693         }
694         catch (FileNotFoundException JavaDoc fnf)
695         {
696             System.err.println("Could not open Log4J configuration file "
697                     + log4jFile + ": ");
698             fnf.printStackTrace();
699         }
700
701         serviceManager.setConfiguration(configuration);
702
703         // Initialize the service manager. Services
704
// that have its 'earlyInit' property set to
705
// a value of 'true' will be started when
706
// the service manager is initialized.
707
serviceManager.init();
708
709         // Set up the module loader for Turbine. Eventually
710
// an instance of ModuleLoader will be used for each
711
// application running under Turbine but we are trying,
712
// for the time being to work in a BC fashion.
713
moduleLoader = new ModuleLoader();
714         moduleLoader.setConfiguration(configuration);
715         moduleLoader.init();
716
717         // set up the resolver, should be done before the pipeline
718
String JavaDoc resolverClass;
719         resolverClass = configuration.getString(RESOLVER,
720                             "org.apache.turbine.pipeline.DefaultResolver");
721
722         log.debug("Using Resolver: " + resolverClass);
723         resolver = (Resolver) Class.forName(resolverClass).newInstance();
724         resolver.init();
725
726         // Create the error handler
727

728         String JavaDoc exceptionHandlerClass =
729             configuration.getString( EXCEPTION_HANDLER,
730                 "org.apache.turbine.exception.DefaultExceptionHandler" );
731         log.debug("Using error handler: " + exceptionHandlerClass);
732
733         exceptionHandler = ( ExceptionHandler )
734             Class.forName( exceptionHandlerClass ).newInstance();
735
736         // Set some system properties
737
Configuration systemProperties = configuration.subset(SYSTEM);
738
739         if (systemProperties != null)
740         {
741             for (Iterator JavaDoc k = systemProperties.getKeys(); k.hasNext();)
742             {
743                 String JavaDoc name = (String JavaDoc) k.next();
744                 String JavaDoc value = systemProperties.getString(name);
745                 log.debug("System Property: " + name + " => " + value);
746                 System.getProperties().setProperty(name, value);
747             }
748         }
749
750         // Setup the default pipeline. There will be a pipeline per
751
// (sub)app, just like there will be a module loader per app,
752
// but we'll set a standard one up here for now.
753
Class JavaDoc pipelineClass = Class.forName
754             (configuration.getString("pipeline.default", STANDARD_PIPELINE));
755
756         log.debug("Using Pipeline: " + pipelineClass.getName());
757         if (TurbinePipeline.class.isAssignableFrom(pipelineClass))
758         {
759             // Turbine's standard Pipeline implementation uses
760
// descriptors to define what Valves are attached to it.
761
Reader JavaDoc reader =null;
762             String JavaDoc descriptorPath = configuration.getString(
763                 "pipeline.default.descriptor", TurbinePipeline.CLASSIC_PIPELINE);
764             InputStream JavaDoc inputStream = Turbine.class.getClassLoader().getResourceAsStream(descriptorPath);
765             if(inputStream != null)
766             {
767                 reader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(inputStream));
768             }
769             else
770             {
771                 descriptorPath = getRealPath(descriptorPath);
772                 reader = new BufferedReader JavaDoc(new FileReader JavaDoc(descriptorPath));
773             }
774             log.debug("Using descriptor path: " + descriptorPath);
775             XStream pipelineMapper = new XStream(new DomDriver()); // does not require XPP3 library
776
pipeline = (Pipeline) pipelineMapper.fromXML(reader);
777         }
778         else
779         {
780             // Other Pipeline implementations are assumed to choose
781
// the Valves that they attach in another fashion (such as
782
// by hard-coding them).
783
pipeline = (Pipeline) pipelineClass.newInstance();
784         }
785
786         log.debug("Initializing pipeline");
787         pipeline.initialize();
788
789         log.debug("Getting rundataservice: ");
790         // Setup the RunData service for the application
791
runDataService = (RunDataService) TurbineServices.getInstance()
792             .getService(RunDataService.SERVICE_NAME);
793         log.debug("RunDataService: " + runDataService);
794         }
795         catch (Throwable JavaDoc e)
796         {
797             e.printStackTrace();
798             log.error(e);
799             throw new TurbineException(e);
800         }
801     }
802
803     /**
804      * Create any directories that might be needed during
805      * runtime. Right now this includes:
806      *
807      * <ul>
808      *
809      * <li>The directory to write the log files to (relative to the
810      * web application root), or <code>null</code> for the default of
811      * <code>/logs</code>. The directory is specified via the {@link
812      * TurbineConstants#LOGGING_ROOT} parameter.</li>
813      *
814      * </ul>
815      *
816      * @param context Global initialization parameters.
817      * @param config Initialization parameters specific to the Turbine
818      * servlet.
819      */

820     private static void createRuntimeDirectories(ServletContext JavaDoc context,
821                                                  ServletConfig JavaDoc config)
822     {
823         String JavaDoc path = findInitParameter(context, config, LOGGING_ROOT, "/logs");
824         File JavaDoc logDir = new File JavaDoc(getRealPath(path));
825         if (!logDir.exists())
826         {
827             // Create the logging directory
828
if (!logDir.mkdirs())
829             {
830                 System.err.println("Cannot create directory for logs!");
831             }
832         }
833     }
834
835     /**
836      * Finds the specified servlet configuration/initialization
837      * parameter, looking first for a servlet-specific parameter, then
838      * for a global parameter, and using the provided default if not
839      * found.
840      */

841     protected static final String JavaDoc findInitParameter(ServletContext JavaDoc context,
842                                                     ServletConfig JavaDoc config,
843                                                     String JavaDoc name,
844                                                     String JavaDoc defaultValue)
845     {
846         String JavaDoc path = null;
847
848         // Try the name as provided first.
849
boolean usingNamespace = name.startsWith(CONFIG_NAMESPACE);
850         while (true)
851         {
852             path = config.getInitParameter(name);
853             if (StringUtils.isEmpty(path))
854             {
855                 path = context.getInitParameter(name);
856                 if (StringUtils.isEmpty(path))
857                 {
858                     // The named parameter didn't yield a value.
859
if (usingNamespace)
860                     {
861                         path = defaultValue;
862                     }
863                     else
864                     {
865                         // Try again using Turbine's namespace.
866
name = CONFIG_NAMESPACE + '.' + name;
867                         usingNamespace = true;
868                         continue;
869                     }
870                 }
871             }
872             break;
873         }
874
875         return path;
876     }
877
878     /**
879      * Get the ModuleLoader for this Turbine webapp.
880      * Eventually we will want to be able to grab a ModuleLoader
881      * by app name, or app identifier.
882      *
883      * @return ModuleLoader
884      */

885     public static ModuleLoader getModuleLoader()
886     {
887         return moduleLoader;
888     }
889
890     /**
891      * Get the Resolver for this Turbine webapp.
892      * @return Resolver
893      */

894     public static Resolver getResolver()
895     {
896         return resolver;
897     }
898
899     /**
900      * Save some information about this servlet so that
901      * it can be utilized by object instances that do not
902      * have direct access to RunData.
903      *
904      * @param data
905      */

906     public static synchronized void saveServletInfo(RunData data)
907     {
908         serverName = data.getRequest().getServerName();
909         serverPort = new Integer JavaDoc(data.getRequest().getServerPort()).toString();
910         serverScheme = data.getRequest().getScheme();
911         scriptName = applicationRoot + data.getRequest().getServletPath();
912     }
913
914     /**
915      * Set the application root for the webapp.
916      *
917      * @param val New app root.
918      */

919     public static void setApplicationRoot(String JavaDoc val)
920     {
921         applicationRoot = val;
922     }
923
924     /**
925      * Get the application root.
926      *
927      * @return String app root.
928      */

929     public static String JavaDoc getApplicationRoot()
930     {
931         return applicationRoot;
932     }
933
934     /**
935      * Get the expanded path relative to the app root.
936      *
937      * @param path Relative path to translate.
938      */

939     public static String JavaDoc getRealPath(String JavaDoc path)
940     {
941         return getApplicationRoot() + '/' + path;
942     }
943
944     /**
945      * Get the server name.
946      *
947      * @return String server name.
948      */

949     public static String JavaDoc getServerName()
950     {
951         return serverName;
952     }
953
954     /**
955      * Get the server port.
956      *
957      * @return String server port.
958      */

959     public static String JavaDoc getServerPort()
960     {
961         return serverPort;
962     }
963
964     /**
965      * Get the server scheme.
966      *
967      * @return String server scheme.
968      */

969     public static String JavaDoc getServerScheme()
970     {
971         return serverScheme;
972     }
973
974     /**
975      * Get the script name. This is the initial script name.
976      * Actually this is probably not needed any more. I'll
977      * check. jvz.
978      *
979      * @return String initial script name.
980      */

981     public static String JavaDoc getScriptName()
982     {
983         return scriptName;
984     }
985
986     /**
987      * Set the servlet config for this turbine webapp.
988      *
989      * @param s New servlet config
990      */

991     public static void setTurbineServletConfig(ServletConfig JavaDoc s)
992     {
993         servletConfig = s;
994     }
995
996     /**
997      * Get the servlet config for this turbine webapp.
998      *
999      * @return ServletConfig
1000     */

1001    public static ServletConfig JavaDoc getTurbineServletConfig()
1002    {
1003        return servletConfig;
1004    }
1005
1006    /**
1007     * Set the servlet context for this turbine webapp.
1008     *
1009     * @param s New servlet context.
1010     */

1011    public static void setTurbineServletContext(ServletContext JavaDoc s)
1012    {
1013        servletContext = s;
1014    }
1015
1016    /**
1017     * Get the servlet context for this turbine webapp.
1018     *
1019     * @return ServletContext
1020     */

1021    public static ServletContext JavaDoc getTurbineServletContext()
1022    {
1023        return servletContext;
1024    }
1025
1026    /**
1027     * Get the configuration for this turbine webapp.
1028     *
1029     * @return Turbine configuration.
1030     */

1031    public static Configuration getConfiguration()
1032    {
1033        return configuration;
1034    }
1035
1036    /**
1037     * This method sets the required expiration headers in the response
1038     * for a given RunData object. This method attempts to set all
1039     * relevant headers, both for HTTP 1.0 and HTTP 1.1.
1040     *
1041     * @param data The RunData object we are setting cache information for.
1042     * @param expiry The number of seconds untill the document should expire,
1043     * <code>0</code> indicating immediate expiration (i.e. no caching).
1044     */

1045    public static void setCacheHeaders(RunData data, int expiry)
1046    {
1047        if ( expiry == 0 )
1048        {
1049            data.getResponse().setHeader("Pragma", "no-cache");
1050            data.getResponse().setHeader("Cache-Control", "no-cache");
1051            data.getResponse().setHeader(
1052                    "Expires", HttpUtils.formatHttpDate(new Date JavaDoc()));
1053        }
1054        else
1055        {
1056            Date JavaDoc expiryDate = new Date JavaDoc( System.currentTimeMillis() + expiry );
1057            data.getResponse().setHeader(
1058                    "Expires", HttpUtils.formatHttpDate(expiryDate));
1059        }
1060    }
1061}
1062
Popular Tags