View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.config;
21  
22  import org.apache.myfaces.tobago.config.TobagoConfig;
23  import org.apache.myfaces.tobago.exception.TobagoConfigurationException;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  import org.xml.sax.SAXException;
27  
28  import javax.enterprise.context.ApplicationScoped;
29  import javax.enterprise.inject.Produces;
30  import javax.inject.Inject;
31  import javax.inject.Named;
32  import javax.servlet.ServletContext;
33  import javax.servlet.ServletException;
34  import javax.xml.parsers.ParserConfigurationException;
35  import java.io.IOException;
36  import java.lang.invoke.MethodHandles;
37  import java.net.URISyntaxException;
38  import java.net.URL;
39  import java.util.ArrayList;
40  import java.util.Enumeration;
41  import java.util.List;
42  
43  @Named
44  @ApplicationScoped
45  public class TobagoConfigBuilder {
46  
47    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
48  
49    private static final String WEB_INF_TOBAGO_CONFIG_XML = "WEB-INF/tobago-config.xml";
50    private static final String META_INF_TOBAGO_CONFIG_XML = "META-INF/tobago-config.xml";
51  
52    @Inject
53    private ServletContext servletContext;
54  
55    private TobagoConfigImpl tobagoConfig;
56  
57    @Produces
58    public TobagoConfig buildTobagoConfig() {
59      if (tobagoConfig == null) {
60        init();
61      }
62      return tobagoConfig;
63    }
64  
65    private void init() {
66      final List<TobagoConfigFragment> configFragmentList = new ArrayList<>();
67      try {
68        configFromClasspath(configFragmentList);
69        configFromWebInf(configFragmentList);
70        final TobagoConfigSorter sorter = new TobagoConfigSorter(configFragmentList);
71        final TobagoConfigMerger merger = new TobagoConfigMerger(sorter.topologicalSort());
72        tobagoConfig = merger.merge();
73        // prepare themes
74        tobagoConfig.resolveThemes();
75        tobagoConfig.initDefaultValidatorInfo();
76        tobagoConfig.lock();
77        servletContext.setAttribute(TobagoConfig.TOBAGO_CONFIG, tobagoConfig);
78      } catch (final Exception e) {
79        final String error = "Tobago can't be initialized! Application will not run correctly!";
80        LOG.error(error, e);
81        throw new TobagoConfigurationException(error, e);
82      }
83    }
84  
85    private void configFromWebInf(final List<TobagoConfigFragment> configFragmentList)
86        throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
87  
88      final URL url = servletContext.getResource("/" + WEB_INF_TOBAGO_CONFIG_XML);
89      if (url != null) {
90        configFragmentList.add(new TobagoConfigParser().parse(url));
91      }
92    }
93  
94    private void configFromClasspath(final List<TobagoConfigFragment> configFragmentList)
95        throws ServletException {
96  
97      try {
98        if (LOG.isInfoEnabled()) {
99          LOG.info("Searching for '" + META_INF_TOBAGO_CONFIG_XML + "'");
100       }
101       final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
102       final Enumeration<URL> urls = classLoader.getResources(META_INF_TOBAGO_CONFIG_XML);
103       while (urls.hasMoreElements()) {
104         final URL themeUrl = urls.nextElement();
105         try {
106           final TobagoConfigFragment fragment = new TobagoConfigParser().parse(themeUrl);
107           fragment.setUrl(themeUrl);
108           configFragmentList.add(fragment);
109 
110           // tomcat uses jar
111           // weblogic uses zip
112           // IBM WebSphere uses wsjar
113           final String protocol = themeUrl.getProtocol();
114           if (!"file".equals(protocol) && !"jar".equals(protocol)
115               && !"zip".equals(protocol) && !"wsjar".equals(protocol)) {
116             LOG.warn("Unknown protocol '" + themeUrl + "'");
117           }
118         } catch (final Exception e) {
119           throw new Exception(e.getClass().getName() + " on themeUrl: " + themeUrl, e);
120         }
121       }
122     } catch (final Exception e) {
123       final String msg = "while loading ";
124       LOG.error(msg, e);
125       throw new ServletException(msg, e);
126     }
127   }
128 }