View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.chain.web.javax;
18  
19  import java.net.URL;
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import javax.servlet.ServletContext;
24  
25  import org.apache.commons.chain.Catalog;
26  import org.apache.commons.chain.web.CheckedConsumer;
27  import org.apache.commons.chain.web.CheckedFunction;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  /**
32   * Utility methods for loading class loader and web application resources
33   * to configure a {@link Catalog}. These methods are shared between
34   * {@code ChainListener} and {@code ChainServlet}.
35   *
36   * @author Craig R. McClanahan
37   * @author Ted Husted
38   */
39  final class ChainResources {
40  
41      /**
42       * This class uses a private constructor because it is a utility class.
43       */
44      private ChainResources() {
45      }
46  
47      // ---------------------------------------------------------- Static Methods
48  
49      /**
50       * Parse the specified class loader resources.
51       *
52       * @param <E> the type of the exception from parse-function
53       * @param resources Comma-delimited list of resources (or {@code null})
54       * @param parse parse-function to parse the XML document
55       */
56      static <E extends Exception> void parseClassResources(String resources,
57                                      CheckedConsumer<URL, E> parse) {
58  
59          ClassLoader loader =
60              Thread.currentThread().getContextClassLoader();
61          if (loader == null) {
62              loader = ChainResources.class.getClassLoader();
63          }
64          parseResources(loader::getResource, resources, parse);
65      }
66  
67      /**
68       * Parse the specified web application resources.
69       *
70       * @param <E> the type of the exception from parse-function
71       * @param context {@code ServletContext} for this web application
72       * @param resources Comma-delimited list of resources (or {@code null})
73       * @param parse parse-function to parse the XML document
74       */
75      static <E extends Exception> void parseWebResources(ServletContext context,
76                                    String resources,
77                                    CheckedConsumer<URL, E> parse) {
78  
79          parseResources(context::getResource, resources, parse);
80      }
81  
82      /**
83       * Parse the specified resources with a resource-get-function.
84       *
85       * @param <ER> the type of the exception from resource-function
86       * @param <EP> the type of the exception from parse-function
87       * @param resourceFunction function to get the {@link URL} from a path
88       * @param resources Comma-delimited list of resources (or {@code null})
89       * @param parse parse-function to parse the XML document
90       */
91      private static <ER extends Exception, EP extends Exception> void parseResources(
92              CheckedFunction<String, URL, ER> resourceFunction, String resources,
93              CheckedConsumer<URL, EP> parse) {
94  
95          if (resources == null) {
96              return;
97          }
98          Logger logger = LoggerFactory.getLogger(ChainResources.class);
99          String[] paths = getResourcePaths(resources);
100         String path = null;
101         try {
102             for (String path2 : paths) {
103                 path = path2;
104                 URL url = resourceFunction.apply(path);
105                 if (url == null) {
106                     throw new IllegalStateException("Missing chain config resource '" + path + "'");
107                 }
108                 logger.debug("Loading chain config resource '{}'", path);
109                 parse.accept(url);
110             }
111         } catch (Exception e) {
112             throw new RuntimeException("Exception parsing chain config resource '" + path + "': "
113                  + e.getMessage());
114         }
115     }
116 
117     /**
118      * Parse the resource string into an array of paths. Empty entries will
119      * be skipped. (That is, all entries in the array are non-empty paths.)
120      *
121      * @param resources A comma-delimited list of resource paths (or
122      *        {@code null}).
123      *
124      * @return An array of non-empty paths. The array itself may be empty.
125      *
126      * @since Chain 1.1
127      */
128     static String[] getResourcePaths(String resources) {
129         final List<String> paths = new ArrayList<>();
130 
131         if (resources != null) {
132             String path;
133             int comma;
134 
135             int lastComma = 0;
136             while ((comma = resources.indexOf(',', lastComma)) >= 0) {
137                 path = resources.substring(lastComma, comma).trim();
138                 if (path.length() > 0) {
139                     paths.add(path);
140                 }
141                 lastComma = comma + 1;
142             }
143             path = resources.substring(lastComma).trim();
144             if (path.length() > 0) {
145                 paths.add(path);
146             }
147         }
148 
149         return paths.toArray(new String[0]);
150     }
151 }