View Javadoc
1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.util;
22  
23  import jakarta.servlet.ServletContext;
24  import jakarta.servlet.http.HttpServletRequest;
25  
26  import org.apache.struts.Globals;
27  import org.apache.struts.action.RequestProcessor;
28  import org.apache.struts.config.MessageResourcesConfig;
29  import org.apache.struts.config.ModuleConfig;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  /**
34   * General purpose utility methods related to module processing.
35   *
36   * @version $Rev$
37   * @since Struts 1.2
38   */
39  public class ModuleUtils {
40      /**
41       * The Singleton instance.
42       */
43      private static final ModuleUtils instance = new ModuleUtils();
44  
45      /**
46       * The {@code Log} instance for this class.
47       */
48      private final Logger log =
49          LoggerFactory.getLogger(ModuleUtils.class);
50  
51      /**
52       * Constructor for ModuleUtils.
53       */
54      protected ModuleUtils() {
55          super();
56      }
57  
58      /**
59       * Returns the Singleton instance of TagUtils.
60       */
61      public static ModuleUtils getInstance() {
62          return instance;
63      }
64  
65      /**
66       * Return the current ModuleConfig object stored in request, if it exists,
67       * null otherwise. This method can be used by plugin to retrieve the
68       * current module config object. If no moduleConfig is found, this means
69       * that the request haven't hit the server throught the struts servlet.
70       * The appropriate module config can be set and found with <code>{@link
71       * ModuleUtils#selectModule(HttpServletRequest, ServletContext)} </code>.
72       *
73       * @param request The servlet request we are processing
74       * @return the ModuleConfig object from request, or null if none is set in
75       *         the request.
76       */
77      public ModuleConfig getModuleConfig(HttpServletRequest request) {
78          return (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
79      }
80  
81      /**
82       * Return the desired ModuleConfig object stored in context, if it exists,
83       * null otherwise.
84       *
85       * @param prefix  The module prefix of the desired module
86       * @param context The ServletContext for this web application
87       * @return the ModuleConfig object specified, or null if not found in the
88       *         context.
89       */
90      public ModuleConfig getModuleConfig(String prefix, ServletContext context) {
91          if ((prefix == null) || "/".equals(prefix)) {
92              return (ModuleConfig) context.getAttribute(Globals.MODULE_KEY);
93          } else {
94              return (ModuleConfig) context.getAttribute(Globals.MODULE_KEY
95                  + prefix);
96          }
97      }
98  
99      /**
100      * Return the desired ModuleConfig object stored in context, if it exists,
101      * otherwise return the current ModuleConfig
102      *
103      * @param prefix  The module prefix of the desired module
104      * @param request The servlet request we are processing
105      * @param context The ServletContext for this web application
106      * @return the ModuleConfig object specified, or null if not found in the
107      *         context.
108      */
109     public ModuleConfig getModuleConfig(String prefix,
110         HttpServletRequest request, ServletContext context) {
111         ModuleConfig moduleConfig = null;
112 
113         if (prefix != null) {
114             //lookup module stored with the given prefix.
115             moduleConfig = this.getModuleConfig(prefix, context);
116         } else {
117             //return the current module if no prefix was supplied.
118             moduleConfig = this.getModuleConfig(request, context);
119         }
120 
121         return moduleConfig;
122     }
123 
124     /**
125      * Return the ModuleConfig object is it exists, null otherwise.
126      *
127      * @param request The servlet request we are processing
128      * @param context The ServletContext for this web application
129      * @return the ModuleConfig object
130      */
131     public ModuleConfig getModuleConfig(HttpServletRequest request,
132         ServletContext context) {
133         ModuleConfig moduleConfig = this.getModuleConfig(request);
134 
135         if (moduleConfig == null) {
136             moduleConfig = this.getModuleConfig("", context);
137             request.setAttribute(Globals.MODULE_KEY, moduleConfig);
138         }
139 
140         return moduleConfig;
141     }
142 
143     /**
144      * Get the module name to which the specified request belong.
145      *
146      * @param request The servlet request we are processing
147      * @param context The ServletContext for this web application
148      * @return The module prefix or ""
149      */
150     public String getModuleName(HttpServletRequest request,
151         ServletContext context) {
152         // Acquire the path used to compute the module
153         String matchPath =
154             (String) request.getAttribute(RequestProcessor.INCLUDE_SERVLET_PATH);
155 
156         if (matchPath == null) {
157             matchPath = request.getServletPath();
158         }
159 
160         return this.getModuleName(matchPath, context);
161     }
162 
163     /**
164      * Get the module name to which the specified uri belong.
165      *
166      * @param matchPath The uri from which we want the module name.
167      * @param context   The ServletContext for this web application
168      * @return The module prefix or ""
169      */
170     public String getModuleName(String matchPath, ServletContext context) {
171         log.debug("Get module name for path {}", matchPath);
172 
173         String prefix = ""; // Initialize prefix before we try lookup
174         String[] prefixes = getModulePrefixes(context);
175 
176         // Get all other possible prefixes
177         int lastSlash = 0; // Initialize before loop
178 
179         while (prefix.isEmpty()
180             && ((lastSlash = matchPath.lastIndexOf("/")) > 0)) {
181             // We may be in a non-default module.  Try to get it's prefix.
182             matchPath = matchPath.substring(0, lastSlash);
183 
184             // Match against the list of module prefixes
185             for (int i = 0; i < prefixes.length; i++) {
186                 if (matchPath.equals(prefixes[i])) {
187                     prefix = prefixes[i];
188 
189                     break;
190                 }
191             }
192         }
193 
194         if (log.isDebugEnabled()) {
195             log.debug("Module name found: {}",
196                 prefix.isEmpty() ? "default" : prefix);
197         }
198 
199         return prefix;
200     }
201 
202     /**
203      * Return the list of module prefixes that are defined for this web
204      * application.  <strong>NOTE</strong> - the "" prefix for the default
205      * module is not included in this list.
206      *
207      * @param context The ServletContext for this web application.
208      * @return An array of module prefixes.
209      */
210     public String[] getModulePrefixes(ServletContext context) {
211         return (String[]) context.getAttribute(Globals.MODULE_PREFIXES_KEY);
212     }
213 
214     /**
215      * Select the module to which the specified request belongs, and add
216      * corresponding request attributes to this request.
217      *
218      * @param request The servlet request we are processing
219      * @param context The ServletContext for this web application
220      */
221     public void selectModule(HttpServletRequest request, ServletContext context) {
222         // Compute module name
223         String prefix = getModuleName(request, context);
224 
225         // Expose the resources for this module
226         this.selectModule(prefix, request, context);
227     }
228 
229     /**
230      * Select the module to which the specified request belongs, and add
231      * corresponding request attributes to this request.
232      *
233      * @param prefix  The module prefix of the desired module
234      * @param request The servlet request we are processing
235      * @param context The ServletContext for this web application
236      */
237     public void selectModule(String prefix, HttpServletRequest request,
238         ServletContext context) {
239         // Expose the resources for this module
240         ModuleConfig config = getModuleConfig(prefix, context);
241 
242         if (config != null) {
243             request.setAttribute(Globals.MODULE_KEY, config);
244 
245             MessageResourcesConfig[] mrConfig =
246                 config.findMessageResourcesConfigs();
247 
248             for (int i = 0; i < mrConfig.length; i++) {
249                 String key = mrConfig[i].getKey();
250                 MessageResources resources =
251                     (MessageResources) context.getAttribute(key + prefix);
252 
253                 if (resources != null) {
254                     request.setAttribute(key, resources);
255                 } else {
256                     request.removeAttribute(key);
257                 }
258             }
259         } else {
260             request.removeAttribute(Globals.MODULE_KEY);
261         }
262     }
263 }