1 /*
2 * $Id: TilesUtilImpl.java 54929 2004-10-16 16:38:42Z germuska $
3 *
4 * Copyright 1999-2004 The Apache Software Foundation.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.struts.tiles;
20
21 import java.io.IOException;
22 import java.io.Serializable;
23
24 import javax.servlet.ServletContext;
25 import javax.servlet.ServletException;
26 import javax.servlet.ServletRequest;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletResponse;
29 import javax.servlet.jsp.PageContext;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.struts.tiles.definition.ComponentDefinitionsFactoryWrapper;
34 import org.apache.struts.util.RequestUtils;
35
36 /**
37 * Default implementation of TilesUtil.
38 * This class contains default implementation of utilities. This implementation
39 * is intended to be used without Struts.
40 */
41 public class TilesUtilImpl implements Serializable {
42
43 /** Commons Logging instance.*/
44 protected Log log = LogFactory.getLog(TilesUtil.class);
45
46 /** Constant name used to store factory in servlet context */
47 public static final String DEFINITIONS_FACTORY =
48 "org.apache.struts.tiles.DEFINITIONS_FACTORY";
49
50 /**
51 * Do a forward using request dispatcher.
52 *
53 * This method is used by the Tiles package anytime a forward is required.
54 * @param uri Uri or Definition name to forward.
55 * @param request Current page request.
56 * @param servletContext Current servlet context.
57 */
58 public void doForward(
59 String uri,
60 HttpServletRequest request,
61 HttpServletResponse response,
62 ServletContext servletContext)
63 throws IOException, ServletException {
64
65 request.getRequestDispatcher(uri).forward(request, response);
66 }
67
68 /**
69 * Do an include using request dispatcher.
70 *
71 * This method is used by the Tiles package when an include is required.
72 * The Tiles package can use indifferently any form of this method.
73 * @param uri Uri or Definition name to forward.
74 * @param request Current page request.
75 * @param response Current page response.
76 * @param servletContext Current servlet context.
77 */
78 public void doInclude(
79 String uri,
80 HttpServletRequest request,
81 HttpServletResponse response,
82 ServletContext servletContext)
83 throws IOException, ServletException {
84
85 request.getRequestDispatcher(uri).include(request, response);
86 }
87
88 /**
89 * Do an include using PageContext.include().
90 *
91 * This method is used by the Tiles package when an include is required.
92 * The Tiles package can use indifferently any form of this method.
93 * @param uri Uri or Definition name to forward.
94 * @param pageContext Current page context.
95 */
96 public void doInclude(String uri, PageContext pageContext)
97 throws IOException, ServletException {
98
99 pageContext.include(uri);
100 }
101
102 /**
103 * Get definition factory from appropriate servlet context.
104 * @return Definitions factory or <code>null</code> if not found.
105 */
106 public DefinitionsFactory getDefinitionsFactory(
107 ServletRequest request,
108 ServletContext servletContext) {
109
110 return (DefinitionsFactory) servletContext.getAttribute(DEFINITIONS_FACTORY);
111 }
112
113 /**
114 * Create Definition factory from specified configuration object.
115 * Create an instance of the factory with the class specified in the config
116 * object. Then, initialize this factory and finally store the factory in
117 * appropriate context by calling
118 * {@link #makeDefinitionsFactoryAccessible(DefinitionsFactory, ServletContext)}.
119 * Factory creation is done by {@link #createDefinitionFactoryInstance(String)}.
120 * <p>
121 *
122 * @param servletContext Servlet Context passed to newly created factory.
123 * @param factoryConfig Configuration object passed to factory.
124 * @return newly created factory of type specified in the config object.
125 * @throws DefinitionsFactoryException If an error occur while initializing factory
126 */
127 public DefinitionsFactory createDefinitionsFactory(
128 ServletContext servletContext,
129 DefinitionsFactoryConfig factoryConfig)
130 throws DefinitionsFactoryException {
131
132 // Create configurable factory
133 DefinitionsFactory factory =
134 createDefinitionFactoryInstance(factoryConfig.getFactoryClassname());
135
136 factory.init(factoryConfig, servletContext);
137
138 // Make factory accessible from jsp tags (push it in appropriate context)
139 makeDefinitionsFactoryAccessible(factory, servletContext);
140 return factory;
141 }
142
143 /**
144 * Create Definition factory of specified classname.
145 * Factory class must extend the {@link DefinitionsFactory} class.
146 * The factory is wrapped appropriately with {@link ComponentDefinitionsFactoryWrapper}
147 * if it is an instance of the deprecated ComponentDefinitionsFactory class.
148 * @param classname Class name of the factory to create.
149 * @return newly created factory.
150 * @throws DefinitionsFactoryException If an error occur while initializing factory
151 */
152 protected DefinitionsFactory createDefinitionFactoryInstance(String classname)
153 throws DefinitionsFactoryException {
154
155 try {
156 Class factoryClass = RequestUtils.applicationClass(classname);
157 Object factory = factoryClass.newInstance();
158
159 // Backward compatibility : if factory classes implements old interface,
160 // provide appropriate wrapper
161 if (factory instanceof ComponentDefinitionsFactory) {
162 factory =
163 new ComponentDefinitionsFactoryWrapper(
164 (ComponentDefinitionsFactory) factory);
165 }
166 return (DefinitionsFactory) factory;
167
168 } catch (ClassCastException ex) { // Bad classname
169 throw new DefinitionsFactoryException(
170 "Error - createDefinitionsFactory : Factory class '"
171 + classname
172 + " must implement 'TilesDefinitionsFactory'.",
173 ex);
174
175 } catch (ClassNotFoundException ex) { // Bad classname
176 throw new DefinitionsFactoryException(
177 "Error - createDefinitionsFactory : Bad class name '"
178 + classname
179 + "'.",
180 ex);
181
182 } catch (InstantiationException ex) { // Bad constructor or error
183 throw new DefinitionsFactoryException(ex);
184
185 } catch (IllegalAccessException ex) {
186 throw new DefinitionsFactoryException(ex);
187 }
188 }
189
190 /**
191 * Make definition factory accessible to Tags.
192 * Factory is stored in servlet context.
193 * @param factory Factory to be made accessible.
194 * @param servletContext Current servlet context.
195 */
196 protected void makeDefinitionsFactoryAccessible(
197 DefinitionsFactory factory,
198 ServletContext servletContext) {
199
200 servletContext.setAttribute(DEFINITIONS_FACTORY, factory);
201 }
202
203 }