001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.services.impl;
016    
017    import javax.servlet.ServletContext;
018    import javax.servlet.http.HttpServlet;
019    
020    import org.apache.commons.logging.Log;
021    import org.apache.hivemind.Resource;
022    import org.apache.hivemind.util.ContextResource;
023    import org.apache.tapestry.parse.ISpecificationParser;
024    import org.apache.tapestry.services.ApplicationGlobals;
025    import org.apache.tapestry.services.ApplicationInitializer;
026    import org.apache.tapestry.services.ClasspathResourceFactory;
027    import org.apache.tapestry.spec.ApplicationSpecification;
028    import org.apache.tapestry.spec.IApplicationSpecification;
029    import org.apache.tapestry.web.HttpServletWebActivator;
030    
031    /**
032     * Locates the application specification and informs the servlet service about it.
033     * 
034     * @author Howard Lewis Ship
035     * @since 4.0
036     */
037    public class ApplicationSpecificationInitializer implements ApplicationInitializer
038    {
039        public static final String APP_SPEC_PATH_PARAM = "org.apache.tapestry.application-specification";
040    
041        private Log _log;
042    
043        private ClasspathResourceFactory _classpathResourceFactory;
044    
045        private ApplicationGlobals _globals;
046    
047        private ISpecificationParser _parser;
048    
049        public void initialize(HttpServlet servlet)
050        {
051            IApplicationSpecification spec = null;
052    
053            Resource specResource = findApplicationSpecification(servlet);
054    
055            if (specResource == null)
056            {
057                _log.warn(ImplMessages.noApplicationSpecification(servlet));
058                
059                spec = constructStandinSpecification(servlet);
060            } else
061                spec = _parser.parseApplicationSpecification(specResource);
062            
063            _globals.storeActivator(new HttpServletWebActivator(servlet));
064            _globals.storeSpecification(spec);
065        }
066    
067        private Resource findApplicationSpecification(HttpServlet servlet)
068        {
069            String path = servlet.getInitParameter(APP_SPEC_PATH_PARAM);
070    
071            if (path != null)
072                return _classpathResourceFactory.newResource(path);
073    
074            ServletContext context = servlet.getServletContext();
075            String servletName = servlet.getServletName();
076            String expectedName = servletName + ".application";
077    
078            Resource webInfLocation = new ContextResource(context, "/WEB-INF/");
079            Resource webInfAppLocation = webInfLocation.getRelativeResource(servletName + "/");
080    
081            Resource result = check(webInfAppLocation, expectedName);
082            if (result != null)
083                return result;
084            
085            result = check(webInfLocation, expectedName);
086            if (result != null)
087                return result;
088            
089            // Now look for it in classpath, just in case
090            
091            result = _classpathResourceFactory.newResource(expectedName);
092            if (result != null && result.getResourceURL() != null)
093                return result;
094            
095            return null;
096        }
097    
098        private Resource check(Resource resource, String name)
099        {
100            Resource result = resource.getRelativeResource(name);
101    
102            if (_log.isDebugEnabled())
103                _log.debug("Checking for existence of " + result);
104    
105            if (result.getResourceURL() != null)
106            {
107                _log.debug("Found " + result);
108                return result;
109            }
110    
111            return null;
112        }
113    
114        private IApplicationSpecification constructStandinSpecification(HttpServlet servlet)
115        {
116            String servletName = servlet.getServletName();
117    
118            ApplicationSpecification result = new ApplicationSpecification();
119    
120            // Pretend the file exists in the most common expected location.
121    
122            Resource virtualLocation = new ContextResource(servlet.getServletContext(), "/WEB-INF/" + servletName + ".application");
123    
124            result.setSpecificationLocation(virtualLocation);
125    
126            result.setName(servletName);
127    
128            return result;
129        }
130    
131        public void setClasspathResourceFactory(ClasspathResourceFactory factory)
132        {
133            _classpathResourceFactory = factory;
134        }
135    
136        public void setLog(Log log)
137        {
138            _log = log;
139        }
140    
141        public void setGlobals(ApplicationGlobals globals)
142        {
143            _globals = globals;
144        }
145    
146        public void setParser(ISpecificationParser parser)
147        {
148            _parser = parser;
149        }
150    
151    }