Added tiles annotations, see WW-4594. Added tiles annotations, created StrutsTilesAnnotationProcessor to create Definitons from them and using it in TilesResult.
Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/9ac326aa Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/9ac326aa Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/9ac326aa Branch: refs/heads/master Commit: 9ac326aa2458fe43140c1b13b61c87752d282e3d Parents: d9f4054 Author: cnenning <cnenn...@apache.org> Authored: Fri Jan 22 15:27:09 2016 +0100 Committer: cnenning <cnenn...@apache.org> Committed: Fri Jan 22 15:27:09 2016 +0100 ---------------------------------------------------------------------- .../tiles/StrutsTilesAnnotationProcessor.java | 176 ++++++++++++ .../tiles/annotation/TilesAddAttribute.java | 30 ++ .../tiles/annotation/TilesAddListAttribute.java | 28 ++ .../tiles/annotation/TilesDefinition.java | 45 +++ .../tiles/annotation/TilesDefinitions.java | 36 +++ .../tiles/annotation/TilesPutAttribute.java | 32 +++ .../tiles/annotation/TilesPutListAttribute.java | 32 +++ .../apache/struts2/views/tiles/TilesResult.java | 279 +++++++++++-------- 8 files changed, 542 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java new file mode 100644 index 0000000..2ae3ba4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java @@ -0,0 +1,176 @@ +/* + * 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.commons.lang3.StringUtils; +import org.apache.struts2.tiles.annotation.TilesAddAttribute; +import org.apache.struts2.tiles.annotation.TilesAddListAttribute; +import org.apache.struts2.tiles.annotation.TilesDefinition; +import org.apache.struts2.tiles.annotation.TilesDefinitions; +import org.apache.struts2.tiles.annotation.TilesPutAttribute; +import org.apache.struts2.tiles.annotation.TilesPutListAttribute; +import org.apache.tiles.Attribute; +import org.apache.tiles.Definition; +import org.apache.tiles.Expression; +import org.apache.tiles.ListAttribute; + +/** + * Processes tiles annotations to create {@link Definition}s and + * {@link Attribute}s in a way as close to <code>tiles.xml</code> as possible. + * + */ +public class StrutsTilesAnnotationProcessor { + + /** + * Search strategy is as follows: + * <ul> + * <li>Check if action has Annotation {@link TilesDefinition}</li> + * <li>If not, check if action has Annotation {@link TilesDefinitions}</li> + * <li>If given tileName is not null and present in {@link TilesDefinitions}, return it</li> + * <li>Return first element of {@link TilesDefinitions}</li> + * <li>Return null</li> + * </ul> + * + * @param action + * Annotated action. + * @param tileName + * Tilename to search for. May be null in some circumstances. + * @return {@link TilesDefinition} + */ + public TilesDefinition findAnnotation(Object action, String tileName) { + Class<? extends Object> clazz = action.getClass(); + TilesDefinition tilesDefinition = clazz.getAnnotation(TilesDefinition.class); + TilesDefinitions tilesDefinitions = clazz.getAnnotation(TilesDefinitions.class); + + if (tilesDefinition == null && tilesDefinitions != null) { + if (!StringUtils.isEmpty(tileName)) { + for (TilesDefinition i : tilesDefinitions.value()) { + if (i.name() != null && i.name().equals(tileName)) { + tilesDefinition = i; + break; + } + } + } + if (tilesDefinitions.value().length > 0) { + tilesDefinition = tilesDefinitions.value()[0]; + } + } + + return tilesDefinition; + } + + /** + * Builds a {@link Definition} based on given {@link TilesDefinition} with + * given name. + * + * @param tileName + * name for resulting {@link Definition}. + * @param tilesDefinition + * {@link TilesDefinition} to process. + * @return {@link Definition} represented by given {@link TilesDefinition}. + */ + public Definition buildTilesDefinition(String tileName, TilesDefinition tilesDefinition) { + Definition definition = new Definition(); + + definition.setName(tileName); + + String extend = getValueOrNull(tilesDefinition.extend()); + if (extend != null) { + definition.setExtends(extend); + } + String preparer = getValueOrNull(tilesDefinition.preparer()); + if (preparer != null) { + definition.setPreparer(preparer); + } + definition.setTemplateAttribute(buildTemplateAttribute(tilesDefinition)); + + for (TilesPutAttribute putAttribute : tilesDefinition.putAttributes()) { + Attribute attribute = buildPutAttribute(putAttribute); + definition.putAttribute(putAttribute.name(), attribute, putAttribute.cascade()); + } + for (TilesPutListAttribute putListAttribute : tilesDefinition.putListAttributes()) { + Attribute attribute = buildPutListAttribute(putListAttribute); + definition.putAttribute(putListAttribute.name(), attribute, putListAttribute.cascade()); + } + + return definition; + } + + protected Attribute buildTemplateAttribute(TilesDefinition tilesDef) { + // see tiles DigesterDefinitionsReader + Attribute attribute = Attribute.createTemplateAttribute(getValueOrNull(tilesDef.template())); + String templateExpression = getValueOrNull(tilesDef.templateExpression()); + Expression expression = Expression.createExpressionFromDescribedExpression(templateExpression); + attribute.setExpressionObject(expression); + attribute.setRole(getValueOrNull(tilesDef.role())); + String templateType = getValueOrNull(tilesDef.templateType()); + if (templateType != null) { + attribute.setRenderer(templateType); + } else if (getValueOrNull(tilesDef.extend()) != null && templateType == null) { + attribute.setRenderer(null); + } + return attribute; + } + + protected Attribute buildPutAttribute(TilesPutAttribute putAttribute) { + Attribute attribute = new Attribute(); + attribute.setValue(getValueOrNull(putAttribute.value())); + String expression = getValueOrNull(putAttribute.expression()); + attribute.setExpressionObject(Expression.createExpressionFromDescribedExpression(expression)); + attribute.setRole(getValueOrNull(putAttribute.role())); + attribute.setRenderer(getValueOrNull(putAttribute.type())); + return attribute; + } + + protected Attribute buildPutListAttribute(TilesPutListAttribute putListAttribute) { + ListAttribute attribute = new ListAttribute(); + attribute.setRole(getValueOrNull(putListAttribute.role())); + attribute.setInherit(putListAttribute.inherit()); + for (TilesAddAttribute addAttribute : putListAttribute.addAttributes()) { + attribute.add(buildAddAttribute(addAttribute)); + } + for (TilesAddListAttribute addListAttribute : putListAttribute.addListAttributes()) { + attribute.add(buildAddListAttribute(addListAttribute)); + } + return attribute; + } + + protected Attribute buildAddAttribute(TilesAddAttribute addAttribute) { + Attribute attribute = new Attribute(); + attribute.setValue(getValueOrNull(addAttribute.value())); + String expression = getValueOrNull(addAttribute.expression()); + attribute.setExpressionObject(Expression.createExpressionFromDescribedExpression(expression)); + attribute.setRole(getValueOrNull(addAttribute.role())); + attribute.setRenderer(getValueOrNull(addAttribute.type())); + return attribute; + } + + protected Attribute buildAddListAttribute(TilesAddListAttribute addListAttribute) { + ListAttribute attribute = new ListAttribute(); + attribute.setRole(getValueOrNull(addListAttribute.role())); + for (TilesAddAttribute addAttribute : addListAttribute.addAttributes()) { + attribute.add(buildAddAttribute(addAttribute)); + } + return attribute; + } + + protected String getValueOrNull(String value) { + return value != null && value.length() > 0 ? value : null; + } +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddAttribute.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddAttribute.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddAttribute.java new file mode 100644 index 0000000..0e668de --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddAttribute.java @@ -0,0 +1,30 @@ +/* + * 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.annotation; + +/** + * Represents a <code><add-attribute></code> element in <code>tiles.xml</code>. + * + */ +public @interface TilesAddAttribute { + String expression() default ""; + String role() default ""; + String type() default ""; + String value() default ""; +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddListAttribute.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddListAttribute.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddListAttribute.java new file mode 100644 index 0000000..d65066f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesAddListAttribute.java @@ -0,0 +1,28 @@ +/* + * 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.annotation; + +/** + * Represents a <code><add-list-attribute></code> element in <code>tiles.xml</code>. + * + */ +public @interface TilesAddListAttribute { + String role() default ""; + TilesAddAttribute[] addAttributes() default {}; +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinition.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinition.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinition.java new file mode 100644 index 0000000..a71bbc3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinition.java @@ -0,0 +1,45 @@ +/* + * 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Represents a <code><definition></code> element in <code>tiles.xml</code>. + * + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.TYPE }) +@Inherited +public @interface TilesDefinition { + + String extend() default ""; + String name() default ""; + String preparer() default ""; + String role() default ""; + String template() default ""; + String templateExpression() default ""; + String templateType() default ""; + TilesPutAttribute[] putAttributes() default {}; + TilesPutListAttribute[] putListAttributes() default {}; +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinitions.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinitions.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinitions.java new file mode 100644 index 0000000..fb5cc95 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesDefinitions.java @@ -0,0 +1,36 @@ +/* + * 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An array of {@link TilesDefinition}s. + * + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.TYPE }) +@Inherited +public @interface TilesDefinitions { + TilesDefinition[] value(); +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutAttribute.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutAttribute.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutAttribute.java new file mode 100644 index 0000000..c31d49e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutAttribute.java @@ -0,0 +1,32 @@ +/* + * 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.annotation; + +/** + * Represents a <code><put-attribute></code> element in <code>tiles.xml</code>. + * + */ +public @interface TilesPutAttribute { + boolean cascade() default false; + String expression() default ""; + String name() default ""; + String role() default ""; + String type() default ""; + String value() default ""; +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutListAttribute.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutListAttribute.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutListAttribute.java new file mode 100644 index 0000000..be7a507 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/annotation/TilesPutListAttribute.java @@ -0,0 +1,32 @@ +/* + * 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.annotation; + +/** + * Represents a <code><put-list-attribute></code> element in <code>tiles.xml</code>. + * + */ +public @interface TilesPutListAttribute { + boolean cascade() default false; + boolean inherit() default false; + String name() default ""; + String role() default ""; + TilesAddAttribute[] addAttributes() default {}; + TilesAddListAttribute[] addListAttributes() default {}; +} http://git-wip-us.apache.org/repos/asf/struts/blob/9ac326aa/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java ---------------------------------------------------------------------- diff --git a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java index a402869..da00765 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java @@ -1,116 +1,163 @@ -/* - * $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.views.tiles; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.struts2.ServletActionContext; -import org.apache.struts2.result.ServletDispatcherResult; -import org.apache.tiles.TilesContainer; - -import com.opensymphony.xwork2.ActionInvocation; -import org.apache.tiles.access.TilesAccess; -import org.apache.tiles.request.ApplicationContext; -import org.apache.tiles.request.Request; -import org.apache.tiles.request.servlet.ServletRequest; -import org.apache.tiles.request.servlet.ServletUtil; - -/** - * <!-- START SNIPPET: description --> - * Renders a view using struts-tiles. - * <!-- END SNIPPET: description --> - * - * <!-- START SNIPPET: webxml --> - * In your web.xml file, you need to add a servlet entry for TilesServlet to load the tiles - * definitions into the ServletContext. - * - * <servlet> - * <servlet-name>tiles</servlet-name> - * <servlet-class>org.apache.tiles.servlets.TilesServlet</servlet-class> - * <init-param> - * <param-name>definitions-config</param-name> - * <param-value>/WEB-INF/tiles-config.xml</param-value> - * </init-param> - * <load-on-startup>1</load-on-startup> - * </servlet> - * <!-- END SNIPPET: webxml --> - * - * <!-- START SNIPPET: strutsxml --> - * In struts.xml, use type="tiles" on your <result>. - * - * <action name="editUser" class="userAction" method="edit"> - * <result name="success" type="tiles">userForm</result> - * <result name="input" type="tiles">userList</result> - * </action> - * <!-- END SNIPPET: strutsxml --> - * - * - * <!-- START SNIPPET: packageconfig --> - * - * Making this result type the default for the current package. - * - * <result-types> - * <result-type name="tiles" - * class="org.apache.struts2.views.tiles.TilesResult" default="true" /> - * </result-types> - * <!-- END SNIPPET: packageconfig --> - * - */ -public class TilesResult extends ServletDispatcherResult { - - private static final long serialVersionUID = -3806939435493086244L; - - public TilesResult() { - super(); - } - - public TilesResult(String location) { - super(location); - } - - /** - * Dispatches to the given location. Does its forward via a RequestDispatcher. If the - * dispatch fails a 404 error will be sent back in the http response. - * - * @param location the location to dispatch to. - * @param invocation the execution state of the action - * @throws Exception if an error occurs. If the dispatch fails the error will go back via the - * HTTP request. - */ - public void doExecute(String location, ActionInvocation invocation) throws Exception { - setLocation(location); - - ServletContext servletContext = ServletActionContext.getServletContext(); - - ApplicationContext applicationContext = ServletUtil.getApplicationContext(servletContext); - TilesContainer container = TilesAccess.getContainer(applicationContext); - - HttpServletRequest httpRequest = ServletActionContext.getRequest(); - HttpServletResponse httpResponse = ServletActionContext.getResponse(); - - Request request = new ServletRequest(applicationContext, httpRequest, httpResponse); - - container.render(location, request); - } -} +/* + * $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.views.tiles; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.result.ServletDispatcherResult; +import org.apache.struts2.tiles.StrutsTilesAnnotationProcessor; +import org.apache.struts2.tiles.annotation.TilesDefinition; +import org.apache.tiles.Definition; +import org.apache.tiles.TilesContainer; +import org.apache.tiles.TilesException; + +import com.opensymphony.xwork2.ActionInvocation; +import org.apache.tiles.access.TilesAccess; +import org.apache.tiles.mgmt.MutableTilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; + +/** + * <!-- START SNIPPET: description --> + * Renders a view using struts-tiles. + * <!-- END SNIPPET: description --> + * + * <!-- START SNIPPET: webxml --> + * In your web.xml file, you need to add a TilesListener. + * + * <listener> + * <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class> + * </listener> + * <!-- END SNIPPET: webxml --> + * + * <!-- START SNIPPET: strutsxml --> + * In struts.xml, use type="tiles" on your <result>. + * + * <action name="editUser" class="userAction" method="edit"> + * <result name="success" type="tiles">userForm</result> + * <result name="input" type="tiles">userList</result> + * </action> + * <!-- END SNIPPET: strutsxml --> + * + * + * <!-- START SNIPPET: packageconfig --> + * + * Making this result type the default for the current package. + * + * <result-types> + * <result-type name="tiles" + * class="org.apache.struts2.views.tiles.TilesResult" default="true" /> + * </result-types> + * <!-- END SNIPPET: packageconfig --> + * + * + * <!-- START SNIPPET: tilesconfig --> + * You have to configure tiles itself. Therefore you can add <code>tiles.xml</code> either + * to resources or WEB-INF. You may also use annotations like {@link TilesDefinition}. + * + * <!-- END SNIPPET: tilesconfig --> + * + */ +public class TilesResult extends ServletDispatcherResult { + + private static final long serialVersionUID = -3806939435493086244L; + + private static final Logger LOG = LogManager.getLogger(TilesResult.class); + + public TilesResult() { + super(); + } + + public TilesResult(String location) { + super(location); + } + + /** + * Dispatches to the given location. Does its forward via a RequestDispatcher. If the + * dispatch fails a 404 error will be sent back in the http response. + * + * @param location the location to dispatch to. + * @param invocation the execution state of the action + * @throws Exception if an error occurs. If the dispatch fails the error will go back via the + * HTTP request. + */ + public void doExecute(String location, ActionInvocation invocation) throws Exception { + StrutsTilesAnnotationProcessor annotationProcessor = new StrutsTilesAnnotationProcessor(); + TilesDefinition tilesDefinition = null; + Object action = invocation.getAction(); + String actionName = invocation.getInvocationContext().getName(); + + if (StringUtils.isEmpty(location)) { + // location not set -> action must have one @TilesDefinition + tilesDefinition = annotationProcessor.findAnnotation(action, null); + String tileName = StringUtils.isNotEmpty(tilesDefinition.name()) ? tilesDefinition.name() : actionName; + location = tileName; + LOG.debug("using new location name '{}' and @TilesDefinition '{}'", location, tilesDefinition); + } + setLocation(location); + + ServletContext servletContext = ServletActionContext.getServletContext(); + + ApplicationContext applicationContext = ServletUtil.getApplicationContext(servletContext); + TilesContainer container = TilesAccess.getContainer(applicationContext); + + HttpServletRequest httpRequest = ServletActionContext.getRequest(); + HttpServletResponse httpResponse = ServletActionContext.getResponse(); + + Request request = new ServletRequest(applicationContext, httpRequest, httpResponse); + + boolean definitionValid = false; + try { + LOG.debug("checking if tiles definition exists '{}'", location); + definitionValid = container.isValidDefinition(location, request); + } catch (TilesException e) { + LOG.warn("got TilesException while checking if definiton exists, ignoring it", e); + } + if (!definitionValid) { + if (tilesDefinition == null) { + // tilesDefinition not found yet, search in action + tilesDefinition = annotationProcessor.findAnnotation(action, location); + } + if (tilesDefinition != null) { + Definition definition = annotationProcessor.buildTilesDefinition(location, tilesDefinition); + if (container instanceof MutableTilesContainer) { + LOG.debug("registering tiles definition with name '{}'", definition.getName()); + ((MutableTilesContainer)container).register(definition, request); + } else { + LOG.error("cannot register tiles definition as tiles container is not mutable!"); + } + } else { + LOG.warn("could not find @TilesDefinition for action: {}", actionName); + } + } + + container.render(location, request); + } +}