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  
22  package org.apache.struts.tiles;
23  
24  import java.io.IOException;
25  
26  import jakarta.servlet.ServletContext;
27  import jakarta.servlet.ServletException;
28  import jakarta.servlet.ServletRequest;
29  import jakarta.servlet.http.HttpServletRequest;
30  import jakarta.servlet.http.HttpServletResponse;
31  import jakarta.servlet.jsp.PageContext;
32  
33  /**
34   * Class containing utility methods for Tiles.
35   * Methods of this class are static and thereby accessible from anywhere.
36   * The underlying implementation can be changed with
37   * {@link #setTilesUtil(TilesUtilImpl)}.
38   * <br>
39   * Real implementation classes should derive from the {@link TilesUtilImpl} class.
40   * <br>
41   * Some methods are specified to throw the <code>UnsupportedOperationException</code>
42   * if the underlying implementation doesn't support the operation.
43   */
44  public class TilesUtil {
45  
46      /** The implementation of tilesUtilImpl */
47      protected static TilesUtilImpl tilesUtilImpl = new TilesUtilImpl();
48  
49      /**
50       * Get the real implementation.
51       * @return The underlying implementation object.
52       */
53      static public TilesUtilImpl getTilesUtil() {
54          return tilesUtilImpl;
55      }
56  
57      /**
58       * Set the real implementation.
59       * This method should be called only once.
60       * Successive calls have no effect.
61       * @param tilesUtil The implementation.
62       */
63      static public void setTilesUtil(TilesUtilImpl tilesUtil) {
64          if (implAlreadySet) {
65              return;
66          }
67          tilesUtilImpl = tilesUtil;
68          implAlreadySet = true;
69      }
70  
71      /**
72       * Getter to know if the underlying implementation is already set to another
73       * value than the default value.
74       * @return <code>true</code> if {@link #setTilesUtil} has already been called.
75       */
76      static boolean isTilesUtilImplSet() {
77          return implAlreadySet;
78      }
79  
80      /** Flag to know if internal implementation has been set by the setter method */
81      private static boolean implAlreadySet = false;
82  
83      /**
84       * Do a forward using request dispatcher.
85       *
86       * This method is used by the Tiles package anytime a forward is required.
87       * @param uri Uri or Definition name to forward.
88       * @param request Current page request.
89       * @param response Current page response.
90       * @param servletContext Current servlet context.
91       */
92      public static void doForward(
93          String uri,
94          HttpServletRequest request,
95          HttpServletResponse response,
96          ServletContext servletContext)
97          throws IOException, ServletException {
98  
99          tilesUtilImpl.doForward(uri, request, response, servletContext);
100     }
101 
102     /**
103      * Do an include using request dispatcher.
104      *
105      * This method is used by the Tiles package when an include is required.
106      * The Tiles package can use indifferently any form of this method.
107      * @param uri Uri or Definition name to forward.
108      * @param request Current page request.
109      * @param response Current page response.
110      * @param servletContext Current servlet context.
111      */
112     public static void doInclude(
113         String uri,
114         HttpServletRequest request,
115         HttpServletResponse response,
116         ServletContext servletContext)
117         throws IOException, ServletException {
118 
119         tilesUtilImpl.doInclude(uri, request, response, servletContext);
120     }
121 
122     /**
123      * Do an include using PageContext.include().
124      *
125      * This method is used by the Tiles package when an include is required.
126      * The Tiles package can use indifferently any form of this method.
127      * @param uri Uri or Definition name to forward.
128      * @param pageContext Current page context.
129      */
130     public static void doInclude(String uri, PageContext pageContext)
131         throws IOException, ServletException {
132         doInclude(uri, pageContext, true);
133     }
134 
135     /**
136      * Do an include using PageContext.include().
137      *
138      * This method is used by the Tiles package when an include is required.
139      * The Tiles package can use indifferently any form of this method.
140      * @param uri Uri or Definition name to forward.
141      * @param flush If the writer should be flushed before the include
142      * @param pageContext Current page context.
143      */
144     public static void doInclude(String uri, PageContext pageContext, boolean flush)
145         throws IOException, ServletException {
146         tilesUtilImpl.doInclude(uri, pageContext, flush);
147     }
148 
149     /**
150      * Get definition factory from appropriate servlet context.
151      * @return Definitions factory or <code>null</code> if not found.
152      */
153     public static DefinitionsFactory getDefinitionsFactory(
154         ServletRequest request,
155         ServletContext servletContext) {
156         return tilesUtilImpl.getDefinitionsFactory(request, servletContext);
157     }
158 
159     /**
160      * Create Definition factory from specified configuration object.
161      * Create a ConfigurableDefinitionsFactory and initialize it with the configuration
162      * object. This later can contain the factory classname to use.
163      * Factory is made accessible from tags.
164      * <p>
165      * Fallback of several factory creation methods.
166      *
167      * @param servletContext Servlet Context passed to newly created factory.
168      * @param factoryConfig Configuration object passed to factory.
169      * @return newly created factory of type ConfigurableDefinitionsFactory.
170      * @throws DefinitionsFactoryException If an error occur while initializing factory
171      */
172     public static DefinitionsFactory createDefinitionsFactory(
173         ServletContext servletContext,
174         DefinitionsFactoryConfig factoryConfig)
175         throws DefinitionsFactoryException {
176         return tilesUtilImpl.createDefinitionsFactory(servletContext, factoryConfig);
177     }
178 
179     /**
180      * Get a definition by its name.
181      * First, retrieve definition factory and then get requested definition.
182      * Throw appropriate exception if definition or definition factory is not found.
183      * @param definitionName Name of requested definition.
184      * @param request Current servelet request.
185      * @param servletContext current servlet context.
186      * @throws FactoryNotFoundException Can't find definition factory.
187      * @throws DefinitionsFactoryException General error in factory while getting definition.
188      * @throws NoSuchDefinitionException No definition found for specified name
189      */
190     public static ComponentDefinition getDefinition(
191         String definitionName,
192         ServletRequest request,
193         ServletContext servletContext)
194         throws FactoryNotFoundException, DefinitionsFactoryException {
195 
196         try {
197             return getDefinitionsFactory(request, servletContext).getDefinition(
198                 definitionName,
199                 (HttpServletRequest) request,
200                 servletContext);
201 
202         } catch (NullPointerException ex) { // Factory not found in context
203             throw new FactoryNotFoundException("Can't get definitions factory from context.");
204         }
205     }
206 
207     /**
208      * Reset internal state.
209      * This method is used by test suites to reset the class to its original state.
210      */
211     protected static void testReset() {
212         implAlreadySet = false;
213         tilesUtilImpl = new TilesUtilImpl();
214     }
215 }