001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.myfaces.tobago.config;
021    
022    /*
023     * Created 24.06.2003 08:53:35.
024     * $Id: TobagoConfigParser.java 1368577 2012-08-02 16:20:31Z lofwyr $
025     */
026    
027    import org.apache.commons.digester.Digester;
028    import org.apache.commons.io.IOUtils;
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    import org.apache.myfaces.tobago.context.MarkupConfig;
032    import org.apache.myfaces.tobago.context.RendererConfig;
033    import org.apache.myfaces.tobago.context.RenderersConfigImpl;
034    import org.xml.sax.SAXException;
035    
036    import javax.faces.FacesException;
037    import javax.servlet.ServletContext;
038    import java.io.IOException;
039    import java.io.InputStream;
040    import java.net.URL;
041    
042    public class TobagoConfigParser {
043    
044      private static final Log LOG = LogFactory.getLog(TobagoConfigParser.class);
045      private static final String TOBAGO_CONFIG_DTD_1_0 = "/org/apache/myfaces/tobago/config/tobago-config_1_0.dtd";
046      private static final String TOBAGO_CONFIG_DTD_1_0_29 = "/org/apache/myfaces/tobago/config/tobago-config-1.0.29.dtd";
047      private static final String TOBAGO_CONFIG_DTD_1_0_30 = "/org/apache/myfaces/tobago/config/tobago-config-1.0.30.dtd";
048      private static final String TOBAGO_CONFIG_DTD_1_0_34 = "/org/apache/myfaces/tobago/config/tobago-config-1.0.34.dtd";
049    
050      public TobagoConfig parse(ServletContext context)
051          throws IOException, SAXException, FacesException {
052    
053        TobagoConfig tobagoConfig = new TobagoConfig();
054        Digester digester = configure(tobagoConfig);
055        parse(context, digester);
056        return tobagoConfig;
057      }
058    
059      private Digester configure(TobagoConfig config) {
060        Digester digester = new Digester();
061        digester.setUseContextClassLoader(true);
062        digester.push(config);
063        digester.setValidating(true);
064    
065        // theme-config
066        digester.addCallMethod("tobago-config/theme-config/default-theme", "setDefaultThemeName", 0);
067        digester.addCallMethod("tobago-config/theme-config/supported-theme", "addSupportedThemeName", 0);
068    
069        // mapping rules
070        digester.addObjectCreate("tobago-config/mapping-rule", MappingRule.class);
071        digester.addSetNext("tobago-config/mapping-rule", "addMappingRule");
072        digester.addCallMethod(
073            "tobago-config/mapping-rule/request-uri", "setRequestUri", 0);
074        digester.addCallMethod(
075            "tobago-config/mapping-rule/forward-uri", "setForwardUri", 0);
076        digester.addObjectCreate(
077            "tobago-config/mapping-rule/attribute", Attribute.class);
078        digester.addSetNext(
079            "tobago-config/mapping-rule/attribute", "addAttribute");
080        digester.addCallMethod(
081            "tobago-config/mapping-rule/attribute/key", "setKey", 0);
082        digester.addCallMethod(
083            "tobago-config/mapping-rule/attribute/value", "setValue", 0);
084    
085        // XXX: deprecated! will ever be true (will be removed in next release after 1.0.7)
086        digester.addCallMethod("tobago-config/load-theme-resources-from-classpath", "setLoadThemesFromClasspath", 0);
087    
088        // resource dirs
089        digester.addCallMethod("tobago-config/resource-dir", "addResourceDir", 0);
090    
091        // enable ajax
092        digester.addCallMethod("tobago-config/ajax-enabled", "setAjaxEnabled", 0);
093    
094        // see bug TOBAGO-912
095        digester.addCallMethod("tobago-config/fix-resource-order", "setFixResourceOrder", 0);
096    
097        // see bug TOBAGO-916
098        digester.addCallMethod("tobago-config/fix-layout-transparency", "setFixLayoutTransparency", 0);
099    
100        // session secret
101        digester.addCallMethod("tobago-config/create-session-secret", "setCreateSessionSecret", 0);
102        digester.addCallMethod("tobago-config/check-session-secret", "setCheckSessionSecret", 0);
103    
104        digester.addObjectCreate("tobago-config/renderers", RenderersConfigImpl.class);
105        digester.addSetNext("tobago-config/renderers", "setRenderersConfig");
106        digester.addObjectCreate("tobago-config/renderers/renderer", RendererConfig.class);
107        digester.addSetNext("tobago-config/renderers/renderer", "addRenderer");
108        digester.addCallMethod("tobago-config/renderers/renderer/name", "setName", 0);
109        digester.addObjectCreate("tobago-config/renderers/renderer/supported-markup", MarkupConfig.class);
110        digester.addSetNext("tobago-config/renderers/renderer/supported-markup", "setMarkupConfig");
111        digester.addCallMethod("tobago-config/renderers/renderer/supported-markup/markup", "addMarkup", 0);
112    
113        return digester;
114      }
115    
116      // TODO: make it runnable without config file, using defaults
117      private void parse(ServletContext context, Digester digester)
118          throws IOException, SAXException, FacesException {
119    
120        String configPath = "/WEB-INF/tobago-config.xml";
121        InputStream input = null;
122        registerDtds(digester);
123        try {
124          input = context.getResourceAsStream(configPath);
125          if (input != null) {
126            digester.parse(input);
127          } else {
128            throw new FacesException(
129                "No config file found: '" + configPath + "'. Tobago can't run without configuration.");
130          }
131        } finally {
132          IOUtils.closeQuietly(input);
133        }
134      }
135    
136      private void registerDtds(Digester digester) {
137        registerDtd(digester, "-//Atanion GmbH//DTD Tobago Config 1.0//EN", TOBAGO_CONFIG_DTD_1_0);
138        registerDtd(digester, "-//The Apache Software Foundation//DTD Tobago Config 1.0//EN", TOBAGO_CONFIG_DTD_1_0);
139        registerDtd(digester, "-//The Apache Software Foundation//DTD Tobago Config 1.0.29//EN", TOBAGO_CONFIG_DTD_1_0_29);
140        registerDtd(digester, "-//The Apache Software Foundation//DTD Tobago Config 1.0.30//EN", TOBAGO_CONFIG_DTD_1_0_30);
141        registerDtd(digester, "-//The Apache Software Foundation//DTD Tobago Config 1.0.34//EN", TOBAGO_CONFIG_DTD_1_0_34);
142      }
143    
144      private void registerDtd(Digester digester, String publicId, String entityUrl) {
145        URL url = TobagoConfigParser.class.getResource(entityUrl);
146        if (LOG.isDebugEnabled()) {
147          LOG.debug("Registering dtd: url='" + url + "'");
148        }
149        if (null != url) {
150          digester.register(publicId, url.toString());
151        } else {
152          LOG.warn("Unable to retrieve local DTD '" + entityUrl + "'; trying external URL");
153        }
154      }
155    }