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