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