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 995980 2010-09-10 20:49:00Z 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    
046      public TobagoConfig parse(ServletContext context)
047          throws IOException, SAXException, FacesException {
048    
049        TobagoConfig tobagoConfig = new TobagoConfig();
050        Digester digester = configure(tobagoConfig);
051        parse(context, digester);
052        return tobagoConfig;
053      }
054    
055      private Digester configure(TobagoConfig config) {
056        Digester digester = new Digester();
057        digester.setUseContextClassLoader(true);
058        digester.push(config);
059        digester.setValidating(true);
060    
061        // theme-config
062        digester.addCallMethod("tobago-config/theme-config/default-theme", "setDefaultThemeName", 0);
063        digester.addCallMethod("tobago-config/theme-config/supported-theme", "addSupportedThemeName", 0);
064    
065        // mapping rules
066        digester.addObjectCreate("tobago-config/mapping-rule", MappingRule.class);
067        digester.addSetNext("tobago-config/mapping-rule", "addMappingRule");
068        digester.addCallMethod(
069            "tobago-config/mapping-rule/request-uri", "setRequestUri", 0);
070        digester.addCallMethod(
071            "tobago-config/mapping-rule/forward-uri", "setForwardUri", 0);
072        digester.addObjectCreate(
073            "tobago-config/mapping-rule/attribute", Attribute.class);
074        digester.addSetNext(
075            "tobago-config/mapping-rule/attribute", "addAttribute");
076        digester.addCallMethod(
077            "tobago-config/mapping-rule/attribute/key", "setKey", 0);
078        digester.addCallMethod(
079            "tobago-config/mapping-rule/attribute/value", "setValue", 0);
080    
081        // XXX: deprecated! will ever be true (will be removed in next release after 1.0.7)
082        digester.addCallMethod("tobago-config/load-theme-resources-from-classpath", "setLoadThemesFromClasspath", 0);
083    
084        // resource dirs
085        digester.addCallMethod("tobago-config/resource-dir", "addResourceDir", 0);
086    
087        // enable ajax
088        digester.addCallMethod("tobago-config/ajax-enabled", "setAjaxEnabled", 0);
089    
090        // see bug TOBAGO-912
091        digester.addCallMethod("tobago-config/fix-resource-order", "setFixResourceOrder", 0);
092    
093        digester.addObjectCreate("tobago-config/renderers", RenderersConfigImpl.class);
094        digester.addSetNext("tobago-config/renderers", "setRenderersConfig");
095        digester.addObjectCreate("tobago-config/renderers/renderer", RendererConfig.class);
096        digester.addSetNext("tobago-config/renderers/renderer", "addRenderer");
097        digester.addCallMethod("tobago-config/renderers/renderer/name", "setName", 0);
098        digester.addObjectCreate("tobago-config/renderers/renderer/supported-markup", MarkupConfig.class);
099        digester.addSetNext("tobago-config/renderers/renderer/supported-markup", "setMarkupConfig");
100        digester.addCallMethod("tobago-config/renderers/renderer/supported-markup/markup", "addMarkup", 0);
101    
102        return digester;
103      }
104    
105      // TODO: make it runnable without config file, using defaults
106      private void parse(ServletContext context, Digester digester)
107          throws IOException, SAXException, FacesException {
108    
109        String configPath = "/WEB-INF/tobago-config.xml";
110        InputStream input = null;
111        registerDtds(digester);
112        try {
113          input = context.getResourceAsStream(configPath);
114          if (input != null) {
115            digester.parse(input);
116          } else {
117            throw new FacesException(
118                "No config file found: '" + configPath + "'. Tobago can't run without configuration.");
119          }
120        } finally {
121          IOUtils.closeQuietly(input);
122        }
123      }
124    
125      private void registerDtds(Digester digester) {
126        registerDtd(digester, "-//Atanion GmbH//DTD Tobago Config 1.0//EN", TOBAGO_CONFIG_DTD_1_0);
127        registerDtd(digester, "-//The Apache Software Foundation//DTD Tobago Config 1.0//EN", TOBAGO_CONFIG_DTD_1_0);
128        registerDtd(digester, "-//The Apache Software Foundation//DTD Tobago Config 1.0.29//EN", TOBAGO_CONFIG_DTD_1_0_29);
129      }
130    
131      private void registerDtd(Digester digester, String publicId, String entityUrl) {
132        URL url = TobagoConfigParser.class.getResource(entityUrl);
133        if (LOG.isDebugEnabled()) {
134          LOG.debug("Registering dtd: url='" + url + "'");
135        }
136        if (null != url) {
137          digester.register(publicId, url.toString());
138        } else {
139          LOG.warn("Unable to retrieve local DTD '" + entityUrl + "'; trying external URL");
140        }
141      }
142    }