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