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 }