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
015package org.apache.tapestry.services.impl;
016
017import javax.servlet.ServletContext;
018import javax.servlet.http.HttpServlet;
019
020import org.apache.commons.logging.Log;
021import org.apache.hivemind.Resource;
022import org.apache.hivemind.util.ContextResource;
023import org.apache.tapestry.parse.ISpecificationParser;
024import org.apache.tapestry.services.ApplicationGlobals;
025import org.apache.tapestry.services.ApplicationInitializer;
026import org.apache.tapestry.services.ClasspathResourceFactory;
027import org.apache.tapestry.spec.ApplicationSpecification;
028import org.apache.tapestry.spec.IApplicationSpecification;
029import org.apache.tapestry.web.HttpServletWebActivator;
030
031/**
032 * Locates the application specification and informs the
033 * {@link org.apache.tapestry.services.ServletInfo}service about it.
034 * 
035 * @author Howard Lewis Ship
036 * @since 4.0
037 */
038public class ApplicationSpecificationInitializer implements ApplicationInitializer
039{
040    private Log _log;
041
042    private ClasspathResourceFactory _classpathResourceFactory;
043
044    private ApplicationGlobals _globals;
045
046    private ISpecificationParser _parser;
047
048    public static final String APP_SPEC_PATH_PARAM = "org.apache.tapestry.application-specification";
049
050    public void initialize(HttpServlet servlet)
051    {
052        IApplicationSpecification spec = null;
053
054        Resource specResource = findApplicationSpecification(servlet);
055
056        if (specResource == null)
057        {
058            _log.debug(ImplMessages.noApplicationSpecification(servlet));
059
060            spec = constructStandinSpecification(servlet);
061        }
062        else
063            spec = _parser.parseApplicationSpecification(specResource);
064
065        _globals.storeActivator(new HttpServletWebActivator(servlet));
066        _globals.storeSpecification(spec);
067    }
068
069    private Resource findApplicationSpecification(HttpServlet servlet)
070    {
071        String path = servlet.getInitParameter(APP_SPEC_PATH_PARAM);
072
073        if (path != null)
074            return _classpathResourceFactory.newResource(path);
075
076        ServletContext context = servlet.getServletContext();
077        String servletName = servlet.getServletName();
078        String expectedName = servletName + ".application";
079
080        Resource webInfLocation = new ContextResource(context, "/WEB-INF/");
081        Resource webInfAppLocation = webInfLocation.getRelativeResource(servletName + "/");
082
083        Resource result = check(webInfAppLocation, expectedName);
084        if (result != null)
085            return result;
086
087        return check(webInfLocation, expectedName);
088    }
089
090    private Resource check(Resource resource, String name)
091    {
092        Resource result = resource.getRelativeResource(name);
093
094        if (_log.isDebugEnabled())
095            _log.debug("Checking for existence of " + result);
096
097        if (result.getResourceURL() != null)
098        {
099            _log.debug("Found " + result);
100            return result;
101        }
102
103        return null;
104    }
105
106    private IApplicationSpecification constructStandinSpecification(HttpServlet servlet)
107    {
108        String servletName = servlet.getServletName();
109
110        ApplicationSpecification result = new ApplicationSpecification();
111
112        // Pretend the file exists in the most common expected location.
113
114        Resource virtualLocation = new ContextResource(servlet.getServletContext(), "/WEB-INF/"
115                + servletName + ".application");
116
117        result.setSpecificationLocation(virtualLocation);
118
119        result.setName(servletName);
120
121        return result;
122    }
123
124    public void setClasspathResourceFactory(ClasspathResourceFactory factory)
125    {
126        _classpathResourceFactory = factory;
127    }
128
129    public void setLog(Log log)
130    {
131        _log = log;
132    }
133
134    public void setGlobals(ApplicationGlobals globals)
135    {
136        _globals = globals;
137    }
138
139    public void setParser(ISpecificationParser parser)
140    {
141        _parser = parser;
142    }
143
144}