WW-1508 Supporting tiles/freemarker integration.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@477379 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David H. DeWolf
2006-11-20 22:41:56 +00:00
parent 380203a73b
commit a7bbcaea01
11 changed files with 319 additions and 19 deletions
@@ -13,6 +13,10 @@
<result name="success" type="tiles">showcase.index</result>
</action>
<action name="freemarker">
<result type="tiles">showcase.freemarker</result>
</action>
<action name="sanity">
<result type="redirect">/tiles/layout.jsp</result>
<result type="redirect" name="success">/tiles/layout.jsp</result>
@@ -21,16 +21,22 @@
*/
-->
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://struts.apache.org/dtds/tiles-config_2_0.dtd">
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://struts.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="showcase.index" template="/tiles/layout.jsp">
<put name="title" value="Tiles Showcase" />
<put name="header" value="/tiles/header.jsp" />
<put name="body" value="/tiles/body.jsp" />
</definition>
<definition name="showcase.index" template="/tiles/layout.jsp">
<put name="title" value="Tiles Showcase"/>
<put name="header" value="/tiles/header.jsp"/>
<put name="body" value="/tiles/body.jsp"/>
</definition>
<definition name="showcase.freemarker" template="/tiles/layout.jsp">
<put name="title" value="Tiles/Freemarker Showcase"/>
<put name="header" value="/tiles/header.jsp"/>
<put name="body" value="/tiles/body.ftl"/>
</definition>
</tiles-definitions>
@@ -0,0 +1,6 @@
<div>
<p>This example illustrates the freemarker support in the Struts/Tiles Plugin.</p>
<p>Tiles 2 is an effort to extract the Tiles library from Struts. It is currently housed
in the Sandbox area of the Apache Struts Subversion repository.</p>
</div>
@@ -1,6 +1,15 @@
<%@taglib prefix="s" uri="/struts-tags" %>
<div>
<p>This example illustrates the Struts/Tiles Plugin.</p>
<p>Tiles 2 is an effort to extract the Tiles library from Struts. It is currently housed
in the Sandbox area of the Apache Struts Subversion repository.</p>
<h4>Features</h4>
<ul>
<li>
<a href="freemarker.action">View FreeMarker Example</a>
</li>
</ul>
</div>
@@ -13,4 +13,3 @@
</p>
</body>
</html>
@@ -101,6 +101,7 @@ public class FreemarkerResult extends StrutsResultSupport {
protected Configuration configuration;
protected ObjectWrapper wrapper;
protected FreemarkerManager freemarkerManager;
private Writer writer;
/*
* Struts results are constructed for each result execution
@@ -199,10 +200,18 @@ public class FreemarkerResult extends StrutsResultSupport {
return configuration.getObjectWrapper();
}
public void setWriter(Writer writer) {
this.writer = writer;
}
/**
* The default writer writes directly to the response writer.
*/
protected Writer getWriter() throws IOException {
if(writer != null) {
return writer;
}
return ServletActionContext.getResponse().getWriter();
}
@@ -48,8 +48,7 @@ public class FacesResult extends StrutsResultSupport implements Result {
* config and then renders the result by delegating to the
* FacesRender.render().
*
* @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String,
* com.opensymphony.
* @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(String, ActionInvocation)
*/
protected void doExecute(String finalLocation, ActionInvocation invocation)
throws Exception {
@@ -0,0 +1,185 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.struts2.tiles;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
/**
* ServletContext implementation which allows Struts
* to inject initialization parameters into the context
* in order to reduce the amount of configuration required
* within web.xml for using Tiles.
*
* The specified init parameters are only utilized if
* they are not explicitaly defined in the web.xml
*
* @version $Rev$
* @since Struts 2.0.1
*/
@SuppressWarnings("deprecation")
public class ConfiguredServletContext implements ServletContext {
private ServletContext rootContext;
private Map<String, String> initParameters;
public ConfiguredServletContext(ServletContext context, Map<String, String> initParameters) {
this.rootContext = context;
this.initParameters = initParameters;
}
public ServletContext getContext(String string) {
return rootContext.getContext(string);
}
public int getMajorVersion() {
return rootContext.getMajorVersion();
}
public int getMinorVersion() {
return rootContext.getMinorVersion();
}
public String getMimeType(String string) {
return rootContext.getMimeType(string);
}
public Set getResourcePaths(String string) {
return rootContext.getResourcePaths(string);
}
public URL getResource(String string) throws MalformedURLException {
return rootContext.getResource(string);
}
public InputStream getResourceAsStream(String string) {
return rootContext.getResourceAsStream(string);
}
public RequestDispatcher getRequestDispatcher(String string) {
return rootContext.getRequestDispatcher(string);
}
public RequestDispatcher getNamedDispatcher(String string) {
return rootContext.getNamedDispatcher(string);
}
@SuppressWarnings("deprecation")
public Servlet getServlet(String string) throws ServletException {
return rootContext.getServlet(string);
}
@SuppressWarnings("deprecation")
public Enumeration getServlets() {
return rootContext.getServlets(); //To change body of implemented methods use File | Settings | File Templates.
}
@SuppressWarnings("deprecation")
public Enumeration getServletNames() {
return rootContext.getServletNames();
}
public void log(String string) {
rootContext.log(string);
}
@SuppressWarnings("deprecation")
public void log(Exception exception, String string) {
rootContext.log(exception, string);
}
public void log(String string, Throwable throwable) {
rootContext.log(string, throwable);
}
public String getRealPath(String string) {
return rootContext.getRealPath(string);
}
public String getServerInfo() {
return rootContext.getServerInfo();
}
public String getInitParameter(String string) {
String parm = rootContext.getInitParameter(string);
if (parm == null) {
return initParameters.get(string);
}
return parm;
}
public Enumeration getInitParameterNames() {
return new CompositeEnumeration(
rootContext.getInitParameterNames(),
initParameters.keySet().iterator());
}
public Object getAttribute(String string) {
return rootContext.getAttribute(string);
}
public Enumeration getAttributeNames() {
return rootContext.getAttributeNames();
}
public void setAttribute(String string, Object object) {
rootContext.setAttribute(string, object);
}
public void removeAttribute(String string) {
rootContext.removeAttribute(string);
}
public String getServletContextName() {
return rootContext.getServletContextName();
}
class CompositeEnumeration implements Enumeration {
private Enumeration first;
private Iterator second;
public CompositeEnumeration(Enumeration first, Iterator second) {
this.first = first;
this.second = second;
}
public boolean hasMoreElements() {
return first.hasMoreElements() || second.hasNext();
}
public Object nextElement() {
if (first.hasMoreElements()) {
return first.nextElement();
}
return second.next();
}
}
}
@@ -73,7 +73,7 @@ public class StrutsTilesContainerFactory extends TilesContainerFactory {
}
/**
* Wrapper factory, used to wrap the TilesRequestContext with a
* Wrapper factory, used to decorate the TilesRequestContext with a
* FreemarkerResult aware version.
*
*/
@@ -0,0 +1,73 @@
/*
* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts2.tiles;
import org.apache.tiles.listener.TilesListener;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.TilesException;
import org.apache.tiles.factory.TilesContainerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.ServletContext;
import java.util.Map;
import java.util.HashMap;
/**
* Listener used to automatically inject ServletContext
* init parameters so that they don't need to be configured
* explicitly for tiles integration. This is provided
* mainly for backwards compatibility with Struts 2.0.1
* configuration.
*
* @since Struts 2.0.2
* @version $Rev$
*
*/
public class StrutsTilesListener extends TilesListener {
private static final Log LOG =
LogFactory.getLog(StrutsTilesListener.class);
private static final Map<String, String> INIT;
static {
INIT = new HashMap<String, String>();
INIT.put(TilesContainerFactory.CONTAINER_FACTORY_INIT_PARAM,
StrutsTilesContainerFactory.class.getName());
}
protected TilesContainer createContainer(ServletContext context)
throws TilesException {
if(context.getInitParameter(TilesContainerFactory.CONTEXT_FACTORY_INIT_PARAM) == null) {
context = decorate(context);
}
else {
LOG.warn("Tiles container factory is explicitly set. Not injecting struts configuration.");
}
return super.createContainer(context);
}
protected ServletContext decorate(ServletContext context) {
return new ConfiguredServletContext(context, INIT);
}
}
@@ -21,16 +21,18 @@
package org.apache.struts2.tiles;
import com.opensymphony.xwork2.ActionInvocation;
import freemarker.template.TemplateException;
import com.opensymphony.xwork2.inject.Container;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.views.freemarker.FreemarkerResult;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.context.TilesRequestContextWrapper;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
@@ -49,6 +51,7 @@ public class StrutsTilesRequestContext extends TilesRequestContextWrapper {
private static final Log LOG =
LogFactory.getLog(StrutsTilesRequestContext.class);
/**
* The mask used to detect requests which should be intercepted.
*/
@@ -86,8 +89,6 @@ public class StrutsTilesRequestContext extends TilesRequestContextWrapper {
* be used in order to setup the appropriate model.
*
* @throws IOException
* @throws ServletException
* @throws Exception
*/
public void include(String include) throws IOException {
if (include.endsWith(mask)) {
@@ -95,20 +96,29 @@ public class StrutsTilesRequestContext extends TilesRequestContextWrapper {
LOG.debug("Intercepting tiles include '" + include + "'. Processing as freemarker result.");
}
HttpServletRequest request = (HttpServletRequest) getRequest();
HttpServletResponse response = (HttpServletResponse) getResponse();
ActionInvocation invocation =
ServletActionContext.getActionContext(request).getActionInvocation();
FreemarkerResult result = new FreemarkerResult();
try {
FreemarkerResult result = new FreemarkerResult();
result.setWriter(response.getWriter());
Container container = Dispatcher.getInstance()
.getConfigurationManager()
.getConfiguration().getContainer();
container.inject(result);
result.doExecute(include, invocation);
} catch (TemplateException e) {
} catch (Exception e) {
LOG.error("Error invoking Freemarker template", e);
throw new IOException("Error invoking Freemarker template."+ e.getMessage());
throw new IOException("Error invoking Freemarker template." + e.getMessage());
}
} else {
super.include(include);
}
}
}