1/*2 * $Id: SharedVariableLoaderFreemarkerServlet.java 1306435 2012-03-28 15:39:11Z nlebas $3 *4 * Licensed to the Apache Software Foundation (ASF) under one5 * or more contributor license agreements. See the NOTICE file6 * distributed with this work for additional information7 * regarding copyright ownership. The ASF licenses this file8 * to you under the Apache License, Version 2.0 (the9 * "License"); you may not use this file except in compliance10 * with the License. You may obtain a copy of the License at11 *12 * http://www.apache.org/licenses/LICENSE-2.013 *14 * Unless required by applicable law or agreed to in writing,15 * software distributed under the License is distributed on an16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY17 * KIND, either express or implied. See the License for the18 * specific language governing permissions and limitations19 * under the License.20 */2122package org.apache.tiles.request.freemarker.servlet;
2324import java.util.Enumeration;
25import java.util.LinkedHashMap;
26import java.util.Map;
2728import javax.servlet.ServletConfig;
29import javax.servlet.ServletContext;
30import javax.servlet.ServletException;
3132import org.apache.tiles.request.reflect.ClassUtil;
3334import freemarker.cache.TemplateLoader;
35import freemarker.ext.servlet.FreemarkerServlet;
36import freemarker.template.Configuration;
3738/**39 * Extends FreemarkerServlet to load Tiles directives as a shared variable.40 *41 * @version $Rev: 1306435 $ $Date: 2012-03-29 02:39:11 +1100 (Thu, 29 Mar 2012) $42 */43publicclassSharedVariableLoaderFreemarkerServletextends FreemarkerServlet {
4445/**46 * The serial UID.47 */48privatestaticfinallong serialVersionUID = 4301098067909854507L;
4950/**51 * The init parameter under which the factories will be put. The value of the parameter52 * must be a semicolon (;) separated list of couples, each member of the couple must53 * be separated by commas (,).54 */55publicstaticfinal String CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM =
56"org.apache.tiles.request.freemarker.CUSTOM_SHARED_VARIABLE_FACTORIES";
5758/**59 * Maps a name of a shared variable to its factory.60 */61private Map<String, SharedVariableFactory> name2variableFactory =
62new LinkedHashMap<String, SharedVariableFactory>();
6364 @Override
65publicvoid init(ServletConfig config) throws ServletException {
66 String param = config.getInitParameter(CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM);
67if (param != null) {
68 String[] couples = param.split("\\s*;\\s*");
69for (int i = 0; i < couples.length; i++) {
70 String[] couple = couples[i].split("\\s*,\\s*");
71if (couple == null || couple.length != 2) {
72thrownew ServletException(
73"Cannot parse custom shared variable partial init param: '"74 + couples[i] + "'");
75 }
76 name2variableFactory.put(couple[0],
77 (SharedVariableFactory) ClassUtil.instantiate(couple[1]));
78 }
79 }
80super.init(newExcludingParameterServletConfig(config));
81 }
8283/**84 * Adds anew shared variable factory in a manual way.85 *86 * @param variableName The name of the shared variable.87 * @param factory The shared variable factory.88 */89publicvoid addSharedVariableFactory(String variableName, SharedVariableFactory factory) {
90 name2variableFactory.put(variableName, factory);
91 }
9293/** {@inheritDoc} */94 @Override
95protected Configuration createConfiguration() {
96 Configuration configuration = super.createConfiguration();
9798for (Map.Entry<String, SharedVariableFactory> entry : name2variableFactory.entrySet()) {
99 configuration.setSharedVariable(entry.getKey(), entry.getValue().create());
100 }
101return configuration;
102 }
103104/** {@inheritDoc} */105106 @Override
107protected TemplateLoader createTemplateLoader(String templatePath) {
108returnnewWebappClassTemplateLoader(getServletContext());
109 }
110111/**112 * Servlet configuration that excludes some parameters. It is useful to adapt to113 * FreemarkerServlet behaviour, because it gets angry if it sees some extra114 * parameters that it does not recognize.115 */116privateclassExcludingParameterServletConfigimplements ServletConfig {
117118/**119 * The servlet configuration.120 */121private ServletConfig config;
122123/**124 * Constructor.125 *126 * @param config The servlet configuration.127 */128publicExcludingParameterServletConfig(ServletConfig config) {
129this.config = config;
130 }
131132 @Override
133public String getServletName() {
134return config.getServletName();
135 }
136137 @Override
138public ServletContext getServletContext() {
139return config.getServletContext();
140 }
141142 @Override
143public String getInitParameter(String name) {
144if (CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM.equals(name)) {
145returnnull;
146 }
147return config.getInitParameter(name);
148 }
149150 @SuppressWarnings({ "rawtypes", "unchecked" })
151 @Override
152public Enumeration getInitParameterNames() {
153returnnewSkippingEnumeration(config.getInitParameterNames());
154 }
155156 }
157158/**159 * An enumeration that skip just160 * {@link SharedVariableLoaderFreemarkerServlet#CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM},161 * again not to let the FreemarkerServlet be angry about it.162 */163privatestaticclassSkippingEnumerationimplements Enumeration<String> {
164165/**166 * The original enumeration.167 */168private Enumeration<String> enumeration;
169170/**171 * The next element.172 */173private String next = null;
174175/**176 * Constructor.177 *178 * @param enumeration The original enumeration.179 */180publicSkippingEnumeration(Enumeration<String> enumeration) {
181this.enumeration = enumeration;
182 updateNextElement();
183 }
184185 @Override
186publicboolean hasMoreElements() {
187return next != null;
188 }
189190 @Override
191public String nextElement() {
192 String retValue = next;
193 updateNextElement();
194return retValue;
195 }
196197/**198 * Updates the next element that will be passed.199 */200privatevoid updateNextElement() {
201 String value = null;
202boolean done = false;
203while (this.enumeration.hasMoreElements() && !done) {
204 value = this.enumeration.nextElement();
205if (value.equals(CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM)) {
206 value = null;
207 } else {
208 done = true;
209 }
210 }
211 next = value;
212 }
213214 }
215 }