Source Code Cross Referenced for Turbine.java in  » Web-Framework » TURBINE » org » apache » turbine » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » TURBINE » org.apache.turbine 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.apache.turbine;
0002:
0003:        /*
0004:         * Licensed to the Apache Software Foundation (ASF) under one
0005:         * or more contributor license agreements.  See the NOTICE file
0006:         * distributed with this work for additional information
0007:         * regarding copyright ownership.  The ASF licenses this file
0008:         * to you under the Apache License, Version 2.0 (the
0009:         * "License"); you may not use this file except in compliance
0010:         * with the License.  You may obtain a copy of the License at
0011:         *
0012:         *   http://www.apache.org/licenses/LICENSE-2.0
0013:         *
0014:         * Unless required by applicable law or agreed to in writing,
0015:         * software distributed under the License is distributed on an
0016:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0017:         * KIND, either express or implied.  See the License for the
0018:         * specific language governing permissions and limitations
0019:         * under the License.
0020:         */
0021:
0022:        import java.io.File;
0023:        import java.io.FileInputStream;
0024:        import java.io.FileNotFoundException;
0025:        import java.io.IOException;
0026:        import java.io.UnsupportedEncodingException;
0027:        import java.util.Properties;
0028:
0029:        import javax.servlet.ServletConfig;
0030:        import javax.servlet.ServletContext;
0031:        import javax.servlet.ServletException;
0032:        import javax.servlet.http.HttpServlet;
0033:        import javax.servlet.http.HttpServletRequest;
0034:        import javax.servlet.http.HttpServletResponse;
0035:
0036:        import org.apache.commons.configuration.Configuration;
0037:        import org.apache.commons.configuration.ConfigurationFactory;
0038:        import org.apache.commons.configuration.PropertiesConfiguration;
0039:        import org.apache.commons.lang.StringUtils;
0040:        import org.apache.commons.lang.exception.ExceptionUtils;
0041:        import org.apache.commons.logging.Log;
0042:        import org.apache.commons.logging.LogFactory;
0043:        import org.apache.log4j.PropertyConfigurator;
0044:        import org.apache.turbine.modules.ActionLoader;
0045:        import org.apache.turbine.modules.PageLoader;
0046:        import org.apache.turbine.services.ServiceManager;
0047:        import org.apache.turbine.services.TurbineServices;
0048:        import org.apache.turbine.services.avaloncomponent.AvalonComponentService;
0049:        import org.apache.turbine.services.rundata.RunDataService;
0050:        import org.apache.turbine.services.rundata.TurbineRunDataFacade;
0051:        import org.apache.turbine.services.template.TemplateService;
0052:        import org.apache.turbine.services.template.TurbineTemplate;
0053:        import org.apache.turbine.services.velocity.VelocityService;
0054:        import org.apache.turbine.util.RunData;
0055:        import org.apache.turbine.util.ServerData;
0056:        import org.apache.turbine.util.TurbineConfig;
0057:        import org.apache.turbine.util.TurbineException;
0058:        import org.apache.turbine.util.security.AccessControlList;
0059:        import org.apache.turbine.util.template.TemplateInfo;
0060:        import org.apache.turbine.util.uri.URIConstants;
0061:
0062:        /**
0063:         * Turbine is the main servlet for the entire system. It is <code>final</code>
0064:         * because you should <i>not</i> ever need to subclass this servlet.  If you
0065:         * need to perform initialization of a service, then you should implement the
0066:         * Services API and let your code be initialized by it.
0067:         * If you need to override something in the <code>doGet()</code> or
0068:         * <code>doPost()</code> methods, edit the TurbineResources.properties file and
0069:         * specify your own classes there.
0070:         * <p>
0071:         * Turbine servlet recognizes the following initialization parameters.
0072:         * <ul>
0073:         * <li><code>properties</code> the path to TurbineResources.properties file
0074:         * used by the default implementation of <code>ResourceService</code>, relative
0075:         * to the application root.</li>
0076:         * <li><code>basedir</code> this parameter is used <strong>only</strong> if your
0077:         * application server does not support web applications, or the or does not
0078:         * support <code>ServletContext.getRealPath(String)</code> method correctly.
0079:         * You can use this parameter to specify the directory within the server's
0080:         * filesystem, that is the base of your web application.</li>
0081:         * </ul>
0082:         *
0083:         * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
0084:         * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
0085:         * @author <a href="mailto:greg@shwoop.com">Greg Ritter</a>
0086:         * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
0087:         * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
0088:         * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
0089:         * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
0090:         * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
0091:         * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
0092:         * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
0093:         * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
0094:         * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
0095:         * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
0096:         * @version $Id: Turbine.java 543399 2007-06-01 06:15:17Z seade $
0097:         */
0098:        public class Turbine extends HttpServlet implements  TurbineConstants {
0099:            /** SerialVersionUID for serialization */
0100:            private static final long serialVersionUID = -6895381097045304308L;
0101:
0102:            /**
0103:             * Name of path info parameter used to indicate the redirected stage of
0104:             * a given user's initial Turbine request
0105:             */
0106:            public static final String REDIRECTED_PATHINFO_NAME = "redirected";
0107:
0108:            /** The base directory key */
0109:            public static final String BASEDIR_KEY = "basedir";
0110:
0111:            /**
0112:             * In certain situations the init() method is called more than once,
0113:             * somtimes even concurrently. This causes bad things to happen,
0114:             * so we use this flag to prevent it.
0115:             */
0116:            private static boolean firstInit = true;
0117:
0118:            /** Whether init succeeded or not. */
0119:            private static Throwable initFailure = null;
0120:
0121:            /**
0122:             * Should initialization activities be performed during doGet() execution?
0123:             */
0124:            private static boolean firstDoGet = true;
0125:
0126:            /**
0127:             * Keep all the properties of the web server in a convenient data
0128:             * structure
0129:             */
0130:            private static ServerData serverData = null;
0131:
0132:            /** The base from which the Turbine application will operate. */
0133:            private static String applicationRoot;
0134:
0135:            /** Servlet config for this Turbine webapp. */
0136:            private static ServletConfig servletConfig;
0137:
0138:            /** Servlet context for this Turbine webapp. */
0139:            private static ServletContext servletContext;
0140:
0141:            /**
0142:             * The webapp root where the Turbine application
0143:             * is running in the servlet container.
0144:             * This might differ from the application root.
0145:             */
0146:            private static String webappRoot;
0147:
0148:            /** Our internal configuration object */
0149:            private static Configuration configuration = null;
0150:
0151:            /** A reference to the Template Service */
0152:            private TemplateService templateService = null;
0153:
0154:            /** A reference to the RunData Service */
0155:            private RunDataService rundataService = null;
0156:
0157:            /** Default Input encoding if the servlet container does not report an encoding */
0158:            private String inputEncoding = null;
0159:
0160:            /** Logging class from commons.logging */
0161:            private static Log log = LogFactory.getLog(Turbine.class);
0162:
0163:            /**
0164:             * This init method will load the default resources from a
0165:             * properties file.
0166:             *
0167:             * This method is called by init(ServletConfig config)
0168:             *
0169:             * @exception ServletException a servlet exception.
0170:             */
0171:            public final void init() throws ServletException {
0172:                synchronized (this .getClass()) {
0173:                    super .init();
0174:                    ServletConfig config = getServletConfig();
0175:
0176:                    if (!firstInit) {
0177:                        log
0178:                                .info("Double initialization of Turbine was attempted!");
0179:                        return;
0180:                    }
0181:                    // executing init will trigger some static initializers, so we have
0182:                    // only one chance.
0183:                    firstInit = false;
0184:
0185:                    try {
0186:                        ServletContext context = config.getServletContext();
0187:
0188:                        configure(config, context);
0189:
0190:                        templateService = TurbineTemplate.getService();
0191:                        rundataService = TurbineRunDataFacade.getService();
0192:
0193:                        if (rundataService == null) {
0194:                            throw new TurbineException(
0195:                                    "No RunData Service configured!");
0196:                        }
0197:
0198:                    } catch (Exception e) {
0199:                        // save the exception to complain loudly later :-)
0200:                        initFailure = e;
0201:                        log.fatal("Turbine: init() failed: ", e);
0202:                        throw new ServletException("Turbine: init() failed", e);
0203:                    }
0204:                    log.info("Turbine: init() Ready to Rumble!");
0205:                }
0206:            }
0207:
0208:            /**
0209:             * Read the master configuration file in, configure logging
0210:             * and start up any early services.
0211:             *
0212:             * @param config The Servlet Configuration supplied by the container
0213:             * @param context The Servlet Context supplied by the container
0214:             *
0215:             * @throws Exception A problem occured while reading the configuration or performing early startup
0216:             */
0217:
0218:            private void configure(ServletConfig config, ServletContext context)
0219:                    throws Exception {
0220:                // Set the application root. This defaults to the webapp
0221:                // context if not otherwise set. This is to allow 2.1 apps
0222:                // to be developed from CVS. This feature will carry over
0223:                // into 3.0.
0224:                applicationRoot = findInitParameter(context, config,
0225:                        APPLICATION_ROOT_KEY, APPLICATION_ROOT_DEFAULT);
0226:
0227:                webappRoot = config.getServletContext().getRealPath("/");
0228:                // log.info("Web Application root is " + webappRoot);
0229:                // log.info("Application root is "     + applicationRoot);
0230:
0231:                if (applicationRoot == null
0232:                        || applicationRoot.equals(WEB_CONTEXT)) {
0233:                    applicationRoot = webappRoot;
0234:                    // log.info("got empty or 'webContext' Application root. Application root now: " + applicationRoot);
0235:                }
0236:
0237:                // Set the applicationRoot for this webapp.
0238:                setApplicationRoot(applicationRoot);
0239:
0240:                // Create any directories that need to be setup for
0241:                // a running Turbine application.
0242:                createRuntimeDirectories(context, config);
0243:
0244:                //
0245:                // Now we run the Turbine configuration code. There are two ways
0246:                // to configure Turbine:
0247:                //
0248:                // a) By supplying an web.xml init parameter called "configuration"
0249:                //
0250:                // <init-param>
0251:                //   <param-name>configuration</param-name>
0252:                //   <param-value>/WEB-INF/conf/turbine.xml</param-value>
0253:                // </init-param>
0254:                //
0255:                // This loads an XML based configuration file.
0256:                //
0257:                // b) By supplying an web.xml init parameter called "properties"
0258:                //
0259:                // <init-param>
0260:                //   <param-name>properties</param-name>
0261:                //   <param-value>/WEB-INF/conf/TurbineResources.properties</param-value>
0262:                // </init-param>
0263:                //
0264:                // This loads a Properties based configuration file. Actually, these are
0265:                // extended properties as provided by commons-configuration
0266:                //
0267:                // If neither a) nor b) is supplied, Turbine will fall back to the
0268:                // known behaviour of loading a properties file called
0269:                // /WEB-INF/conf/TurbineResources.properties relative to the
0270:                // web application root.
0271:
0272:                String confFile = findInitParameter(context, config,
0273:                        TurbineConfig.CONFIGURATION_PATH_KEY, null);
0274:
0275:                String confPath;
0276:                String confStyle = "unset";
0277:
0278:                if (StringUtils.isNotEmpty(confFile)) {
0279:                    confPath = getRealPath(confFile);
0280:                    ConfigurationFactory configurationFactory = new ConfigurationFactory(
0281:                            confPath);
0282:                    configurationFactory.setBasePath(getApplicationRoot());
0283:                    configuration = configurationFactory.getConfiguration();
0284:                    confStyle = "XML";
0285:                } else {
0286:                    confFile = findInitParameter(context, config,
0287:                            TurbineConfig.PROPERTIES_PATH_KEY,
0288:                            TurbineConfig.PROPERTIES_PATH_DEFAULT);
0289:
0290:                    confPath = getRealPath(confFile);
0291:
0292:                    // This should eventually be a Configuration
0293:                    // interface so that service and app configuration
0294:                    // can be stored anywhere.
0295:                    configuration = (Configuration) new PropertiesConfiguration(
0296:                            confPath);
0297:                    confStyle = "Properties";
0298:                }
0299:
0300:                //
0301:                // Set up logging as soon as possible
0302:                //
0303:                String log4jFile = configuration.getString(LOG4J_CONFIG_FILE,
0304:                        LOG4J_CONFIG_FILE_DEFAULT);
0305:
0306:                if (StringUtils.isNotEmpty(log4jFile)
0307:                        && !log4jFile.equalsIgnoreCase("none")) {
0308:                    log4jFile = getRealPath(log4jFile);
0309:
0310:                    //
0311:                    // Load the config file above into a Properties object and
0312:                    // fix up the Application root
0313:                    //
0314:                    Properties p = new Properties();
0315:                    try {
0316:                        p.load(new FileInputStream(log4jFile));
0317:                        p.setProperty(APPLICATION_ROOT_KEY,
0318:                                getApplicationRoot());
0319:                        PropertyConfigurator.configure(p);
0320:
0321:                        log.info("Configured log4j from " + log4jFile);
0322:                    } catch (FileNotFoundException fnf) {
0323:                        System.err
0324:                                .println("Could not open Log4J configuration file "
0325:                                        + log4jFile + ": ");
0326:                        fnf.printStackTrace();
0327:                    }
0328:                }
0329:
0330:                // Now report our successful configuration to the world
0331:                log.info("Loaded configuration  (" + confStyle + ") from "
0332:                        + confFile + " (" + confPath + ")");
0333:
0334:                setTurbineServletConfig(config);
0335:                setTurbineServletContext(context);
0336:
0337:                getServiceManager().setApplicationRoot(applicationRoot);
0338:
0339:                // We want to set a few values in the configuration so
0340:                // that ${variable} interpolation will work for
0341:                //
0342:                // ${applicationRoot}
0343:                // ${webappRoot}
0344:                configuration
0345:                        .setProperty(APPLICATION_ROOT_KEY, applicationRoot);
0346:                configuration.setProperty(WEBAPP_ROOT_KEY, webappRoot);
0347:
0348:                //
0349:                // Be sure, that our essential services get run early
0350:                //
0351:                configuration.setProperty(TurbineServices.SERVICE_PREFIX
0352:                        + AvalonComponentService.SERVICE_NAME + ".earlyInit",
0353:                        Boolean.TRUE);
0354:
0355:                getServiceManager().setConfiguration(configuration);
0356:
0357:                // Initialize the service manager. Services
0358:                // that have its 'earlyInit' property set to
0359:                // a value of 'true' will be started when
0360:                // the service manager is initialized.
0361:                getServiceManager().init();
0362:
0363:                // Get the default input encoding
0364:                inputEncoding = configuration.getString(
0365:                        TurbineConstants.PARAMETER_ENCODING_KEY,
0366:                        TurbineConstants.PARAMETER_ENCODING_DEFAULT);
0367:
0368:                if (log.isDebugEnabled()) {
0369:                    log
0370:                            .debug("Input Encoding has been set to "
0371:                                    + inputEncoding);
0372:                }
0373:            }
0374:
0375:            /**
0376:             * Create any directories that might be needed during
0377:             * runtime. Right now this includes:
0378:             *
0379:             * <ul>
0380:             *
0381:             * <li>The directory to write the log files to (relative to the
0382:             * web application root), or <code>null</code> for the default of
0383:             * <code>/logs</code>.  The directory is specified via the {@link
0384:             * TurbineConstants#LOGGING_ROOT} parameter.</li>
0385:             *
0386:             * </ul>
0387:             *
0388:             * @param context Global initialization parameters.
0389:             * @param config Initialization parameters specific to the Turbine
0390:             * servlet.
0391:             */
0392:            private static void createRuntimeDirectories(
0393:                    ServletContext context, ServletConfig config) {
0394:                String path = findInitParameter(context, config,
0395:                        LOGGING_ROOT_KEY, LOGGING_ROOT_DEFAULT);
0396:
0397:                File logDir = new File(getRealPath(path));
0398:                if (!logDir.exists()) {
0399:                    // Create the logging directory
0400:                    if (!logDir.mkdirs()) {
0401:                        System.err.println("Cannot create directory for logs!");
0402:                    }
0403:                }
0404:            }
0405:
0406:            /**
0407:             * Finds the specified servlet configuration/initialization
0408:             * parameter, looking first for a servlet-specific parameter, then
0409:             * for a global parameter, and using the provided default if not
0410:             * found.
0411:             */
0412:            protected static final String findInitParameter(
0413:                    ServletContext context, ServletConfig config, String name,
0414:                    String defaultValue) {
0415:                String path = null;
0416:
0417:                // Try the name as provided first.
0418:                boolean usingNamespace = name.startsWith(CONFIG_NAMESPACE);
0419:                while (true) {
0420:                    path = config.getInitParameter(name);
0421:                    if (StringUtils.isEmpty(path)) {
0422:                        path = context.getInitParameter(name);
0423:                        if (StringUtils.isEmpty(path)) {
0424:                            // The named parameter didn't yield a value.
0425:                            if (usingNamespace) {
0426:                                path = defaultValue;
0427:                            } else {
0428:                                // Try again using Turbine's namespace.
0429:                                name = CONFIG_NAMESPACE + '.' + name;
0430:                                usingNamespace = true;
0431:                                continue;
0432:                            }
0433:                        }
0434:                    }
0435:                    break;
0436:                }
0437:
0438:                return path;
0439:            }
0440:
0441:            /**
0442:             * Initializes the services which need <code>RunData</code> to
0443:             * initialize themselves (post startup).
0444:             *
0445:             * @param data The first <code>GET</code> request.
0446:             */
0447:            public final void init(RunData data) {
0448:                synchronized (Turbine.class) {
0449:                    if (firstDoGet) {
0450:                        // All we want to do here is save some servlet
0451:                        // information so that services and processes
0452:                        // that don't have direct access to a RunData
0453:                        // object can still know something about
0454:                        // the servlet environment.
0455:                        saveServletInfo(data);
0456:
0457:                        // Mark that we're done.
0458:                        firstDoGet = false;
0459:                        log.info("Turbine: first Request successful");
0460:                    }
0461:                }
0462:            }
0463:
0464:            /**
0465:             * Return the current configuration with all keys included
0466:             *
0467:             * @return a Configuration Object
0468:             */
0469:            public static Configuration getConfiguration() {
0470:                return configuration;
0471:            }
0472:
0473:            /**
0474:             * Return the server name.
0475:             *
0476:             * @return String server name
0477:             */
0478:            public static String getServerName() {
0479:                return getDefaultServerData().getServerName();
0480:            }
0481:
0482:            /**
0483:             * Return the server scheme.
0484:             *
0485:             * @return String server scheme
0486:             */
0487:            public static String getServerScheme() {
0488:                return getDefaultServerData().getServerScheme();
0489:            }
0490:
0491:            /**
0492:             * Return the server port.
0493:             *
0494:             * @return String server port
0495:             */
0496:            public static String getServerPort() {
0497:                return Integer.toString(getDefaultServerData().getServerPort());
0498:            }
0499:
0500:            /**
0501:             * Get the script name. This is the initial script name.
0502:             * Actually this is probably not needed any more. I'll
0503:             * check. jvz.
0504:             *
0505:             * @return String initial script name.
0506:             */
0507:            public static String getScriptName() {
0508:                return getDefaultServerData().getScriptName();
0509:            }
0510:
0511:            /**
0512:             * Return the context path.
0513:             *
0514:             * @return String context path
0515:             */
0516:            public static String getContextPath() {
0517:                return getDefaultServerData().getContextPath();
0518:            }
0519:
0520:            /**
0521:             * Return all the Turbine Servlet information (Server Name, Port,
0522:             * Scheme in a ServerData structure. This is generated from the
0523:             * values set when initializing the Turbine and may not be correct
0524:             * if you're running in a clustered structure. You can provide default
0525:             * values in your configuration for cases where access is requied before
0526:             * your application is first accessed by a user.  This might be used
0527:             * if you need a DataURI and have no RunData object handy.
0528:             *
0529:             * @return An initialized ServerData object
0530:             */
0531:            public static ServerData getDefaultServerData() {
0532:                if (serverData == null) {
0533:                    String serverName = configuration
0534:                            .getString(DEFAULT_SERVER_NAME_KEY);
0535:                    if (serverName == null) {
0536:                        log
0537:                                .error("ServerData Information requested from Turbine before first request!");
0538:                    } else {
0539:                        log
0540:                                .info("ServerData Information retrieved from configuration.");
0541:                    }
0542:                    // Will be overwritten once the first request is run;
0543:                    serverData = new ServerData(serverName, configuration
0544:                            .getInt(DEFAULT_SERVER_PORT_KEY,
0545:                                    URIConstants.HTTP_PORT), configuration
0546:                            .getString(DEFAULT_SERVER_SCHEME_KEY,
0547:                                    URIConstants.HTTP), configuration
0548:                            .getString(DEFAULT_SCRIPT_NAME_KEY), configuration
0549:                            .getString(DEFAULT_CONTEXT_PATH_KEY));
0550:                }
0551:                return serverData;
0552:            }
0553:
0554:            /**
0555:             * Set the servlet config for this turbine webapp.
0556:             *
0557:             * @param config New servlet config
0558:             */
0559:            public static void setTurbineServletConfig(ServletConfig config) {
0560:                servletConfig = config;
0561:            }
0562:
0563:            /**
0564:             * Get the servlet config for this turbine webapp.
0565:             *
0566:             * @return ServletConfig
0567:             */
0568:            public static ServletConfig getTurbineServletConfig() {
0569:                return servletConfig;
0570:            }
0571:
0572:            /**
0573:             * Set the servlet context for this turbine webapp.
0574:             *
0575:             * @param context New servlet context.
0576:             */
0577:            public static void setTurbineServletContext(ServletContext context) {
0578:                servletContext = context;
0579:            }
0580:
0581:            /**
0582:             * Get the servlet context for this turbine webapp.
0583:             *
0584:             * @return ServletContext
0585:             */
0586:            public static ServletContext getTurbineServletContext() {
0587:                return servletContext;
0588:            }
0589:
0590:            /**
0591:             * The <code>Servlet</code> destroy method.  Invokes
0592:             * <code>ServiceBroker</code> tear down method.
0593:             */
0594:            public final void destroy() {
0595:                // Shut down all Turbine Services.
0596:                getServiceManager().shutdownServices();
0597:                System.gc();
0598:
0599:                firstInit = true;
0600:                firstDoGet = true;
0601:                log.info("Turbine: Done shutting down!");
0602:            }
0603:
0604:            /**
0605:             * The primary method invoked when the Turbine servlet is executed.
0606:             *
0607:             * @param req Servlet request.
0608:             * @param res Servlet response.
0609:             * @exception IOException a servlet exception.
0610:             * @exception ServletException a servlet exception.
0611:             */
0612:            public final void doGet(HttpServletRequest req,
0613:                    HttpServletResponse res) throws IOException,
0614:                    ServletException {
0615:                // set to true if the request is to be redirected by the page
0616:                boolean requestRedirected = false;
0617:
0618:                // Placeholder for the RunData object.
0619:                RunData data = null;
0620:                try {
0621:                    // Check to make sure that we started up properly.
0622:                    if (initFailure != null) {
0623:                        throw initFailure;
0624:                    }
0625:
0626:                    //
0627:                    // If the servlet container gives us no clear indication about the
0628:                    // Encoding of the contents, set it to our default value.
0629:                    if (req.getCharacterEncoding() == null) {
0630:                        if (log.isDebugEnabled()) {
0631:                            log.debug("Changing Input Encoding to "
0632:                                    + inputEncoding);
0633:                        }
0634:
0635:                        try {
0636:                            req.setCharacterEncoding(inputEncoding);
0637:                        } catch (UnsupportedEncodingException uee) {
0638:                            log.warn("Could not change request encoding to "
0639:                                    + inputEncoding, uee);
0640:                        }
0641:                    }
0642:
0643:                    // Get general RunData here...
0644:                    // Perform turbine specific initialization below.
0645:                    data = rundataService.getRunData(req, res,
0646:                            getServletConfig());
0647:
0648:                    // If this is the first invocation, perform some
0649:                    // initialization.  Certain services need RunData to initialize
0650:                    // themselves.
0651:                    if (firstDoGet) {
0652:                        init(data);
0653:                    }
0654:
0655:                    // set the session timeout if specified in turbine's properties
0656:                    // file if this is a new session
0657:                    if (data.getSession().isNew()) {
0658:                        int timeout = configuration.getInt(SESSION_TIMEOUT_KEY,
0659:                                SESSION_TIMEOUT_DEFAULT);
0660:
0661:                        if (timeout != SESSION_TIMEOUT_DEFAULT) {
0662:                            data.getSession().setMaxInactiveInterval(timeout);
0663:                        }
0664:                    }
0665:
0666:                    // Fill in the screen and action variables.
0667:                    data.setScreen(data.getParameters().getString(
0668:                            URIConstants.CGI_SCREEN_PARAM));
0669:                    data.setAction(data.getParameters().getString(
0670:                            URIConstants.CGI_ACTION_PARAM));
0671:
0672:                    // Special case for login and logout, this must happen before the
0673:                    // session validator is executed in order either to allow a user to
0674:                    // even login, or to ensure that the session validator gets to
0675:                    // mandate its page selection policy for non-logged in users
0676:                    // after the logout has taken place.
0677:                    if (data.hasAction()) {
0678:                        String action = data.getAction();
0679:                        log.debug("action = " + action);
0680:
0681:                        if (action.equalsIgnoreCase(configuration.getString(
0682:                                ACTION_LOGIN_KEY, ACTION_LOGIN_DEFAULT))) {
0683:                            loginAction(data);
0684:                        } else if (action.equalsIgnoreCase(configuration
0685:                                .getString(ACTION_LOGOUT_KEY,
0686:                                        ACTION_LOGOUT_DEFAULT))) {
0687:                            logoutAction(data);
0688:                        }
0689:                    }
0690:
0691:                    // This is where the validation of the Session information
0692:                    // is performed if the user has not logged in yet, then
0693:                    // the screen is set to be Login. This also handles the
0694:                    // case of not having a screen defined by also setting the
0695:                    // screen to Login. If you want people to go to another
0696:                    // screen other than Login, you need to change that within
0697:                    // TurbineResources.properties...screen.homepage; or, you
0698:                    // can specify your own SessionValidator action.
0699:                    ActionLoader.getInstance().exec(
0700:                            data,
0701:                            configuration.getString(
0702:                                    ACTION_SESSION_VALIDATOR_KEY,
0703:                                    ACTION_SESSION_VALIDATOR_DEFAULT));
0704:
0705:                    // Put the Access Control List into the RunData object, so
0706:                    // it is easily available to modules.  It is also placed
0707:                    // into the session for serialization.  Modules can null
0708:                    // out the ACL to force it to be rebuilt based on more
0709:                    // information.
0710:                    ActionLoader.getInstance().exec(
0711:                            data,
0712:                            configuration.getString(
0713:                                    ACTION_ACCESS_CONTROLLER_KEY,
0714:                                    ACTION_ACCESS_CONTROLLER_DEFAULT));
0715:
0716:                    // Start the execution phase. DefaultPage will execute the
0717:                    // appropriate action as well as get the Layout from the
0718:                    // Screen and then execute that. The Layout is then
0719:                    // responsible for executing the Navigation and Screen
0720:                    // modules.
0721:                    //
0722:                    // Note that by default, this cannot be overridden from
0723:                    // parameters passed in via post/query data. This is for
0724:                    // security purposes.  You should really never need more
0725:                    // than just the default page.  If you do, add logic to
0726:                    // DefaultPage to do what you want.
0727:
0728:                    String defaultPage = (templateService == null) ? null
0729:                            : templateService.getDefaultPageName(data);
0730:
0731:                    if (defaultPage == null) {
0732:                        /*
0733:                         * In this case none of the template services are running.
0734:                         * The application may be using ECS for views, or a
0735:                         * decendent of RawScreen is trying to produce output.
0736:                         * If there is a 'page.default' property in the TR.props
0737:                         * then use that, otherwise return DefaultPage which will
0738:                         * handle ECS view scenerios and RawScreen scenerios. The
0739:                         * app developer can still specify the 'page.default'
0740:                         * if they wish but the DefaultPage should work in
0741:                         * most cases.
0742:                         */
0743:                        defaultPage = configuration.getString(PAGE_DEFAULT_KEY,
0744:                                PAGE_DEFAULT_DEFAULT);
0745:                    }
0746:
0747:                    PageLoader.getInstance().exec(data, defaultPage);
0748:
0749:                    // If a module has set data.acl = null, remove acl from
0750:                    // the session.
0751:                    if (data.getACL() == null) {
0752:                        try {
0753:                            data.getSession().removeAttribute(
0754:                                    AccessControlList.SESSION_KEY);
0755:                        } catch (IllegalStateException ignored) {
0756:                        }
0757:                    }
0758:
0759:                    // handle a redirect request
0760:                    requestRedirected = ((data.getRedirectURI() != null) && (data
0761:                            .getRedirectURI().length() > 0));
0762:                    if (requestRedirected) {
0763:                        if (data.getResponse().isCommitted()) {
0764:                            requestRedirected = false;
0765:                            log
0766:                                    .warn("redirect requested, response already committed: "
0767:                                            + data.getRedirectURI());
0768:                        } else {
0769:                            data.getResponse().sendRedirect(
0770:                                    data.getRedirectURI());
0771:                        }
0772:                    }
0773:
0774:                    if (!requestRedirected) {
0775:                        try {
0776:                            if (data.isPageSet() == false
0777:                                    && data.isOutSet() == false) {
0778:                                throw new Exception("Nothing to output");
0779:                            }
0780:
0781:                            // We are all done! if isPageSet() output that way
0782:                            // otherwise, data.getOut() has already been written
0783:                            // to the data.getOut().close() happens below in the
0784:                            // finally.
0785:                            if (data.isPageSet() && data.isOutSet() == false) {
0786:                                // Modules can override these.
0787:                                data.getResponse().setLocale(data.getLocale());
0788:                                data.getResponse().setContentType(
0789:                                        data.getContentType());
0790:
0791:                                // Set the status code.
0792:                                data.getResponse().setStatus(
0793:                                        data.getStatusCode());
0794:                                // Output the Page.
0795:                                data.getPage().output(data.getOut());
0796:                            }
0797:                        } catch (Exception e) {
0798:                            // The output stream was probably closed by the client
0799:                            // end of things ie: the client clicked the Stop
0800:                            // button on the browser, so ignore any errors that
0801:                            // result.
0802:                            log.debug("Output stream closed? ", e);
0803:                        }
0804:                    }
0805:                } catch (Exception e) {
0806:                    handleException(data, res, e);
0807:                } catch (Throwable t) {
0808:                    handleException(data, res, t);
0809:                } finally {
0810:                    // Return the used RunData to the factory for recycling.
0811:                    rundataService.putRunData(data);
0812:                }
0813:            }
0814:
0815:            /**
0816:             * In this application doGet and doPost are the same thing.
0817:             *
0818:             * @param req Servlet request.
0819:             * @param res Servlet response.
0820:             * @exception IOException a servlet exception.
0821:             * @exception ServletException a servlet exception.
0822:             */
0823:            public final void doPost(HttpServletRequest req,
0824:                    HttpServletResponse res) throws IOException,
0825:                    ServletException {
0826:                doGet(req, res);
0827:            }
0828:
0829:            /**
0830:             * This method is executed if the configured Login action should be
0831:             * executed by Turbine.
0832:             * <p>
0833:             * This Action must be performed before the Session validation or we
0834:             * get sent in an endless loop back to the Login screen before
0835:             * the action can be performed
0836:             *
0837:             * @param data a RunData object
0838:             *
0839:             * @throws Exception A problem while logging in occured.
0840:             */
0841:            private void loginAction(RunData data) throws Exception {
0842:                ActionLoader.getInstance().exec(data, data.getAction());
0843:                cleanupTemplateContext(data);
0844:                data.setAction(null);
0845:            }
0846:
0847:            /**
0848:             * This method is executed if the configured Logout action should be
0849:             * executed by Turbine.
0850:             * <p>
0851:             * This Action must be performed before the Session validation for the
0852:             * session validator to send us back to the Login screen.
0853:             * <p>
0854:             * The existing session is invalidated before the logout action is
0855:             * executed.
0856:             *
0857:             * @param data a RunData object
0858:             *
0859:             * @throws Exception A problem while logging out occured.
0860:             */
0861:            private void logoutAction(RunData data) throws Exception {
0862:                ActionLoader.getInstance().exec(data, data.getAction());
0863:                cleanupTemplateContext(data);
0864:                data.setAction(null);
0865:                data.getSession().invalidate();
0866:            }
0867:
0868:            /**
0869:             * cleans the Velocity Context if available.
0870:             *
0871:             * @param data A RunData Object
0872:             *
0873:             * @throws Exception A problem while cleaning out the Template Context occured.
0874:             */
0875:            private void cleanupTemplateContext(RunData data) throws Exception {
0876:                // This is Velocity specific and shouldn't be done here.
0877:                // But this is a band aid until we get real listeners
0878:                // here.
0879:                TemplateInfo ti = data.getTemplateInfo();
0880:                if (ti != null) {
0881:                    ti.removeTemp(VelocityService.CONTEXT);
0882:                }
0883:            }
0884:
0885:            /**
0886:             * Return the servlet info.
0887:             *
0888:             * @return a string with the servlet information.
0889:             */
0890:            public final String getServletInfo() {
0891:                return "Turbine Servlet";
0892:            }
0893:
0894:            /**
0895:             * This method is about making sure that we catch and display
0896:             * errors to the screen in one fashion or another. What happens is
0897:             * that it will attempt to show the error using your user defined
0898:             * Error Screen. If that fails, then it will resort to just
0899:             * displaying the error and logging it all over the place
0900:             * including the servlet engine log file, the Turbine log file and
0901:             * on the screen.
0902:             *
0903:             * @param data A Turbine RunData object.
0904:             * @param res Servlet response.
0905:             * @param t The exception to report.
0906:             */
0907:            private void handleException(RunData data, HttpServletResponse res,
0908:                    Throwable t) {
0909:                // make sure that the stack trace makes it the log
0910:                log.error("Turbine.handleException: ", t);
0911:
0912:                String mimeType = "text/plain";
0913:                try {
0914:                    // This is where we capture all exceptions and show the
0915:                    // Error Screen.
0916:                    data.setStackTrace(ExceptionUtils.getStackTrace(t), t);
0917:
0918:                    // setup the screen
0919:                    data.setScreen(configuration.getString(SCREEN_ERROR_KEY,
0920:                            SCREEN_ERROR_DEFAULT));
0921:
0922:                    // do more screen setup for template execution if needed
0923:                    if (data.getTemplateInfo() != null) {
0924:                        data.getTemplateInfo().setScreenTemplate(
0925:                                configuration.getString(TEMPLATE_ERROR_KEY,
0926:                                        TEMPLATE_ERROR_VM));
0927:                    }
0928:
0929:                    // Make sure to not execute an action.
0930:                    data.setAction("");
0931:
0932:                    PageLoader.getInstance().exec(
0933:                            data,
0934:                            configuration.getString(PAGE_DEFAULT_KEY,
0935:                                    PAGE_DEFAULT_DEFAULT));
0936:
0937:                    data.getResponse().setContentType(data.getContentType());
0938:                    data.getResponse().setStatus(data.getStatusCode());
0939:                    if (data.isPageSet()) {
0940:                        data.getOut().print(data.getPage().toString());
0941:                    }
0942:                }
0943:                // Catch this one because it occurs if some code hasn't been
0944:                // completely re-compiled after a change..
0945:                catch (java.lang.NoSuchFieldError e) {
0946:                    try {
0947:                        data.getResponse().setContentType(mimeType);
0948:                        data.getResponse().setStatus(200);
0949:                    } catch (Exception ignored) {
0950:                        // Ignored
0951:                    }
0952:
0953:                    try {
0954:                        data
0955:                                .getOut()
0956:                                .print(
0957:                                        "java.lang.NoSuchFieldError: "
0958:                                                + "Please recompile all of your source code.");
0959:                    } catch (IOException ignored) {
0960:                    }
0961:
0962:                    log.error(data.getStackTrace(), e);
0963:                }
0964:                // Attempt to do *something* at this point...
0965:                catch (Throwable reallyScrewedNow) {
0966:                    StringBuffer msg = new StringBuffer();
0967:                    msg.append("Horrible Exception: ");
0968:                    if (data != null) {
0969:                        msg.append(data.getStackTrace());
0970:                    } else {
0971:                        msg.append(t);
0972:                    }
0973:                    try {
0974:                        res.setContentType(mimeType);
0975:                        res.setStatus(200);
0976:                        res.getWriter().print(msg.toString());
0977:                    } catch (Exception ignored) {
0978:                    }
0979:
0980:                    log.error(reallyScrewedNow.getMessage(), reallyScrewedNow);
0981:                }
0982:            }
0983:
0984:            /**
0985:             * Save some information about this servlet so that
0986:             * it can be utilized by object instances that do not
0987:             * have direct access to RunData.
0988:             *
0989:             * @param data
0990:             */
0991:            public static synchronized void saveServletInfo(RunData data) {
0992:                // Store the context path for tools like ContentURI and
0993:                // the UIManager that use webapp context path information
0994:                // for constructing URLs.
0995:
0996:                //
0997:                // Bundle all the information above up into a convenient structure
0998:                //
0999:                serverData = (ServerData) data.getServerData().clone();
1000:            }
1001:
1002:            /**
1003:             * Set the application root for the webapp.
1004:             *
1005:             * @param val New app root.
1006:             */
1007:            public static void setApplicationRoot(String val) {
1008:                applicationRoot = val;
1009:            }
1010:
1011:            /**
1012:             * Get the application root for this Turbine webapp. This
1013:             * concept was started in 3.0 and will allow an app to be
1014:             * developed from a standard CVS layout. With a simple
1015:             * switch the app will work fully within the servlet
1016:             * container for deployment.
1017:             *
1018:             * @return String applicationRoot
1019:             */
1020:            public static String getApplicationRoot() {
1021:                return applicationRoot;
1022:            }
1023:
1024:            /**
1025:             * Used to get the real path of configuration and resource
1026:             * information. This can be used by an app being
1027:             * developed in a standard CVS layout.
1028:             *
1029:             * @param path path translated to the application root
1030:             * @return the real path
1031:             */
1032:            public static String getRealPath(String path) {
1033:                if (path.startsWith("/")) {
1034:                    path = path.substring(1);
1035:                }
1036:
1037:                return new File(getApplicationRoot(), path).getAbsolutePath();
1038:            }
1039:
1040:            /**
1041:             * Return an instance of the currently configured Service Manager
1042:             *
1043:             * @return A service Manager instance
1044:             */
1045:            private ServiceManager getServiceManager() {
1046:                return TurbineServices.getInstance();
1047:            }
1048:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.