Author: dgeary Date: Tue Jul 5 17:58:35 2005 New Revision: 209369 URL: http://svn.apache.org/viewcvs?rev=209369&view=rev Log: This commit contains an optional integration layer for working with standalone Tiles. That integration, like Shale's Spring integration, is optional. If you specify a property named tiles.home in build.properties, and build Shale's core library, Shale will create a shale-tiles.jar file in core-library/dist/lib. To use the Tiles integration, you include that JAR file in your WEB-INF/lib directory.
Shale's Tiles integration is pretty simple. There's a JSF view handler (org.apache.shale.tiles.TilesViewHandler) that preprocesses navigation view IDs and looks for a matching tile. See the package description for org.apache.shale.tiles for more information. Added: struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/ struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/TilesViewHandler.java struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/faces-config.xml struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/package.html Modified: struts/shale/trunk/core-library/build.xml struts/shale/trunk/core-library/src/java/org/apache/shale/Bundle.properties struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Dialog.java struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Globals.java Modified: struts/shale/trunk/core-library/build.xml URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/build.xml?rev=209369&r1=209368&r2=209369&view=diff ============================================================================== --- struts/shale/trunk/core-library/build.xml (original) +++ struts/shale/trunk/core-library/build.xml Tue Jul 5 17:58:35 2005 @@ -65,6 +65,7 @@ value="${spring.home}/dist/spring-context.jar"/> <property name="spring-core.jar" value="${spring.home}/dist/spring-core.jar"/> <property name="spring-web.jar" value="${spring.home}/dist/spring-web.jar"/> + <property name="tiles.jar" value="${tiles.home}/core-library/dist/lib/tiles-core.jar"/> <!-- Build Defaults --> @@ -111,6 +112,7 @@ <pathelement location="${spring-core.jar}"/> <pathelement location="${spring-web.jar}"/> <pathelement location="${build.home}/classes"/> + <pathelement location="${tiles.jar}"/> </path> @@ -156,6 +158,7 @@ <pathelement location="${spring-web.jar}"/> <pathelement location="${build.home}/classes"/> <pathelement location="${build.home}/test-classes"/> + <pathelement location="${tiles.jar}"/> </path> <!-- Conditional Processing Flags --> @@ -165,6 +168,9 @@ <available property="myfaces.present" classname="org.apache.myfaces.config.MyfacesConfig" classpath="${jsf-impl.jar}"/> + <available property="tiles.present" + classname="org.apache.tiles.servlets.TilesServlet" + classpathref="compile.classpath"/> <condition property="spring.present"> <and> <available classname="org.springframework.core.Constants" @@ -250,6 +256,8 @@ <classpath refid="compile.classpath" /> <exclude name="org/apache/shale/spring/**" unless="spring.present"/> + <exclude name="org/apache/shale/tiles/**" + unless="tiles.present"/> </javac> <!-- Copy non-Java Sources --> @@ -285,7 +293,7 @@ <jar jarfile="${build.home}/lib/shale-core.jar" basedir="${build.home}/classes" manifest="${build.home}/conf/MANIFEST.MF" - excludes="org/apache/shale/spring/** **/package.html"/> + excludes="org/apache/shale/spring/** org/apache/shale/tiles/** **/package.html"/> </target> @@ -305,8 +313,23 @@ </jar> </target> + <target name="library-tiles" depends="compile" if="tiles.present" + description="Package Tiles integration library"> + <mkdir dir="${build.home}/shale-tiles"/> + <mkdir dir="${build.home}/shale-tiles/META-INF"/> + <copy todir="${build.home}/shale-tiles/META-INF" + file="src/java/org/apache/shale/tiles/faces-config.xml"/> + <jar jarfile="${build.home}/lib/shale-tiles.jar" + manifest="${build.home}/conf/MANIFEST.MF"> + <fileset dir="${build.home}/shale-tiles"/> + <fileset dir="${build.home}/classes" + includes="org/apache/shale/tiles/**" + excludes="**/faces-config.xml **/package.html"/> + </jar> + </target> + - <target name="library" depends="library-core,library-spring" + <target name="library" depends="library-core, library-spring, library-tiles" description="Package all libraries"/> Modified: struts/shale/trunk/core-library/src/java/org/apache/shale/Bundle.properties URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/Bundle.properties?rev=209369&r1=209368&r2=209369&view=diff ============================================================================== --- struts/shale/trunk/core-library/src/java/org/apache/shale/Bundle.properties (original) +++ struts/shale/trunk/core-library/src/java/org/apache/shale/Bundle.properties Tue Jul 5 17:58:35 2005 @@ -44,3 +44,9 @@ # org.apache.shale.component.Token token.invalid=Invalid resubmit of the same form + +# org.apache.shale.tiles.TilesViewHandler +tiles.renderingView=Rendering view {0}, looking for tile {1} +tiles.dispatchingToTile=Dispatching to tile {0} +tiles.dispatchingToViewHandler=Dispatching {0} to the default view handler + Modified: struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Dialog.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Dialog.java?rev=209369&r1=209368&r2=209369&view=diff ============================================================================== --- struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Dialog.java (original) +++ struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Dialog.java Tue Jul 5 17:58:35 2005 @@ -18,7 +18,7 @@ /** * <p>Overall configuration of an individual dialog. During application - * execution, this information is immutabe (so that simultaneous execution + * execution, this information is immutable (so that simultaneous execution * threads may be processing states or transitions through this dialog). * Therefore, access to configuration information is not synchronized.</p> * Modified: struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Globals.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Globals.java?rev=209369&r1=209368&r2=209369&view=diff ============================================================================== --- struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Globals.java (original) +++ struts/shale/trunk/core-library/src/java/org/apache/shale/dialog/Globals.java Tue Jul 5 17:58:35 2005 @@ -27,7 +27,7 @@ /** * <p>Context initialization parameter used to specify a comma delimited - * list of context relative resource paths to resources continaing our + * list of context relative resource paths to resources containing our * dialog configuration information.</p> */ public static final String CONFIGURATION_PARAM = Added: struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/TilesViewHandler.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/TilesViewHandler.java?rev=209369&view=auto ============================================================================== --- struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/TilesViewHandler.java (added) +++ struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/TilesViewHandler.java Tue Jul 5 17:58:35 2005 @@ -0,0 +1,289 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation. + * + * Licensed 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.shale.tiles; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; +import java.util.List; +import java.util.Locale; + +import javax.faces.application.ViewHandler; + +import javax.faces.FacesException; +import javax.faces.application.ViewHandler; +import javax.faces.component.UIOutput; +import javax.faces.component.UIViewRoot; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; +import javax.servlet.ServletContext; +import javax.servlet.ServletRequest; + +import org.apache.tiles.*; + +import org.apache.shale.util.Messages; + +/** + * This view handler strips the suffix off of the view ID and looks + * for a tile whose name matches the resulting string. For example, if the + * view ID is /tiles/test.jsp, this view handler will look for a tile named + * /tiles/test. If the tile is found, it is rendered; otherwise, this view handler + * delegates to the default JSF view handler. + * <p/> + * To render a tile, this view handler first locates the tile by name. Then it + * creates or accesses the Tile Context, and stores the tile's attributes + * in the context. Finally, it dispatches the request to the tile's layout + * by calling JSF's <code>ExternalContext.dispatch()</code>. Layouts typically + * contain <tiles:insert> tags that include dynamic content. + * <p/> + * If the request does not reference a tile, this view handler delegates + * view rendering to the default view handler. That means that URLs like this: + * <code>http://localhost:8080/example/index.faces</code> will work as + * expected. + *<p/> + * Most of the methods in this class simply delegate to the default view + * handler, which JSF passes to this view handler's constructor. The only + * method that has a meaningful implementation is <code>void + * renderView(FacesContext, UIViewRoot)</code>, which renders the current + * view in accordance with the algorithm discussed above. + * + * <strong>Note:</strong> This Tiles view handler is tied to the standalone + * version of Tiles, which resides in the Struts sandbox. This view handler + * will not work with Struts Tiles. + */ +public class TilesViewHandler extends ViewHandler { + + + // ------------------------------------------------------------- Constructor + + + /** + * <p>Stores the reference to the default view handler for later use.</p> + * + * @param defaultViewHandler The default view handler + */ + public TilesViewHandler(ViewHandler defaultViewHandler) { + this.defaultViewHandler = defaultViewHandler; + } + + + // -------------------------------------------------------- Static Variables + + + /** + * <p>Log instance for this class.</p> + */ + private static final Log log = LogFactory.getLog( + TilesViewHandler.class.getName()); + /** + * <p>Message resources for this class.</p> + */ + private static Messages messages = + new Messages("org.apache.shale.Bundle", + TilesViewHandler.class.getClassLoader()); + + /** + * <p>The default JSF view handler.</p> + */ + private ViewHandler defaultViewHandler = null; + + + // ----------------------------------------------------- ViewHandler Methods + + + /** + * <p>Render a view according to the algorithm described in this class's + * description: Based on the view Id of the <code>viewToRender</code>, + * this method either renders a tile or delegates rendering to the default + * view handler, which takes care of business as usual.</p> + * + * @param facesContext The faces context object for this request + * @param viewToRender The view that we're rendering + */ + public void renderView(FacesContext facesContext, UIViewRoot viewToRender) + throws IOException, FacesException { + String viewId = viewToRender.getViewId(); + String tileName = getTileName(viewId); + ComponentDefinition tile = getTile(tileName); + + if (log.isDebugEnabled()) { + log.debug(messages.getMessage("tiles.renderingView", + new Object[] { viewId, tileName })); + } + + if (tile != null) { + if (log.isDebugEnabled()) { + log.debug(messages.getMessage("tiles.dispatchingToTile", + new Object[] { tileName })); + } + dispatchToTile(facesContext.getExternalContext(), tile); + } + else { + if (log.isDebugEnabled()) { + log.debug(messages.getMessage("tiles.dispatchingToViewHandler", + new Object[] { viewId })); + } + defaultViewHandler.renderView(facesContext, viewToRender); + } + } + + /** + * <p>Pass through to the default view handler</p> + * + */ + public UIViewRoot createView(FacesContext context, String viewId) { + return defaultViewHandler.createView(context, viewId); + } + + + /** + * <p>Pass through to the default view handler</p> + * + */ + public Locale calculateLocale(FacesContext context) { + return defaultViewHandler.calculateLocale(context); + } + + + /** + * <p>Pass through to the default view handler + * + */ + public String calculateRenderKitId(FacesContext context) { + return defaultViewHandler.calculateRenderKitId(context); + } + + + /** + * <p>Pass through to the default view handler</p> + * + */ + public String getActionURL(FacesContext context, String viewId) { + return defaultViewHandler.getActionURL(context, viewId); + } + + + /** + * <p>Pass through to the default view handler</p> + * + */ + public String getResourceURL(FacesContext context, String path) { + return defaultViewHandler.getResourceURL(context, path); + } + + + /** + * <p>Pass through to the default view handler</p> + * + */ + public UIViewRoot restoreView(FacesContext context, String viewId) { + return defaultViewHandler.restoreView(context, viewId); + } + + + /** + * <p>Pass through to the default view handler</p> + * + */ + public void writeState(FacesContext context) throws IOException { + defaultViewHandler.writeState(context); + } + + + // --------------------------------------------------------- Private Methods + + + /** + * <p>Looks up a tile, given a name. If the tile does not exist, and the + * <code>name</code> begins with a slash ('/'), look for a tile + * without the slash. If no tile is found, return <code>null</code>.</p> + * + * @param name The tile to lookup + */ + private ComponentDefinition getTile(String name) { + if (name == null) + return null; + + ExternalContext externalContext = FacesContext.getCurrentInstance() + .getExternalContext(); + ServletRequest request = (ServletRequest)externalContext.getRequest(); + ServletContext servletContext = (ServletContext)externalContext. + getContext(); + DefinitionsFactory factory = TilesUtil.getDefinitionsFactory(request, + servletContext); + if (factory == null) + return null; + + ComponentDefinition tile = null; + try { + tile = factory.getDefinition(name, request, servletContext); + } + catch(NoSuchDefinitionException nsex) { /* not here */ } + catch(DefinitionsFactoryException dex) { /* not here */ } + + if (tile == null && name.startsWith("/")) { // try again w/o slash... + try { + tile = factory.getDefinition(name.substring(1), + request, servletContext); + } + catch(NoSuchDefinitionException nsdex) { /* not here */ } + catch(DefinitionsFactoryException dfex) { /* not here */ } + } + return tile; + } + + /** + * <p>Given a view ID, returns the name of the corresponding tile. For + * example, for a view ID of /tiles/example/main.jsp, the tile name + * returned by this method would be /tiles/example/main.</p> + * + * @param viewId The view ID + */ + private String getTileName(String viewId) { + int suffixIndex = viewId.lastIndexOf('.'); + return suffixIndex != -1 ? viewId.substring(0, suffixIndex) + : viewId; + } + + /** + * <p>Dispatches to a tile's layout. Layouts typically contain + * <tiles:insert> tags that include content, so dispatching + * to the tile's layout will automatically build the tile.</p> + * <p> + * Before dispatching to the tile, this method sets up the Tile + * context.</p> + * + * @param externalContext The JSF external context + * @param tile The tile definition + */ + private void dispatchToTile(ExternalContext externalContext, + ComponentDefinition tile) + throws java.io.IOException { + ServletRequest request = (ServletRequest)externalContext.getRequest(); + ComponentContext tileContext = ComponentContext.getContext(request); + if (tileContext == null) { + tileContext = new ComponentContext(tile.getAttributes()); + ComponentContext.setContext(tileContext, request); + } + else + tileContext.addMissing(tile.getAttributes()); + + // dispatch to the tile's layout + externalContext.dispatch(tile.getPath()); + } +} Added: struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/faces-config.xml URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/faces-config.xml?rev=209369&view=auto ============================================================================== --- struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/faces-config.xml (added) +++ struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/faces-config.xml Tue Jul 5 17:58:35 2005 @@ -0,0 +1,39 @@ +<?xml version="1.0"?> + + +<!DOCTYPE faces-config PUBLIC + "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" + "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> + + +<!-- + + Copyright 2004-2005 The Apache Software Foundation. + + Licensed 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. + + $Id$ + +--> + + +<faces-config> + + <application> + <!-- Tiles Integration --> + <view-handler> + org.apache.shale.tiles.TilesViewHandler + </view-handler> + </application> + +</faces-config> Added: struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/package.html URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/package.html?rev=209369&view=auto ============================================================================== --- struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/package.html (added) +++ struts/shale/trunk/core-library/src/java/org/apache/shale/tiles/package.html Tue Jul 5 17:58:35 2005 @@ -0,0 +1,33 @@ +<!-- + * Copyright 2004-2005 The Apache Software Foundation. + * + * Licensed 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. +--> + +<!-- $Id$ --> + +<body> + +<p>This package contains an optional integration layer for working with standalone Tiles. +<p> +<strong>Note:</strong><i> Shale's Tiles integration works only with standalone Tiles, which currently resides in the Struts sandbox. Shale's Tiles integration does not work with Struts Tiles.</i> +<p> +Using Shale's Tiles integration is easy: you just include <code>shale-tiles.jar</code> in <code>WEB-INF/lib</code>. For your efforts, for every view ID that you specify for JSF navigation, Shale: +<ol><li>Strips off the view ID's suffix (eg: "/tiles/test.jsp" becomes "/tiles/test")</li> +<li>Searches for a tile with the resulting name, with or without the leading slash (eg: "/tiles/test" or "tiles/test")</li> +<li>Loads the tile if found; otherwise, delegates to the default JSF navigation handler</li> +</ol> +<p> +With Shale's Tiles integration, you can use a tile or a single JSP page to represent a JSF view and your view IDs for navigation are the same for both. For example, you could have a JSP page <code>/login.jsp</code>, that you specify as a view ID for navigation. Later on, you can replace that JSP page with a tile simply by specifying a tile named <code>login</code> in your Tiles definition file. Shale will strip off the <code>.jsp</code> suffix and load the tile instead of the JSP page. + +</body> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]