Austin Kottke's Code Site

Thoughts about Architecture – Java, C/C++, JS, Objective-C, Swift, Groovy, Grails, (RIP Flash)

January 28th, 2011

J2EE Filter that modifies a Stripes response for Velocity rendering

ajax, html, java, stripes, velocity, by austin.

I combined Stripes and Velocity into a J2EE filter that came out to be extremely useful, so I could have Stripes/JSPs and have Velocity rendering with every request.

I love the toolbox.xml concept of velocity so I couldnt live without it, but wanted to use stripes for its amazing action controller functionality. Here is a filter which modifies the stripes response and then parses the response through the Velocity Template Engine.

 
package org.adk.java.viewfilter;
 
import org.adk.java.locale.LocaleTool;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.adk.java.store.StoreWebApplication;
import org.adk.java.store.WebSessionBean;
import org.adk.java.log.KLogger;
import org.adk.java.secure.SecureRedirectorActionBean;
import org.adk.java.stripes.ActionBeanUrlManager;
import org.adk.java.viewfilter.tools.BaseTool;
import org.adk.java.viewfilter.tools.BreadCrumbTool;
import org.adk.java.viewfilter.tools.PropertyTool;
import org.adk.java.viewfilter.tools.RequestTool;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.tools.view.XMLToolboxManager;
 
/********************************************************************************************
 * <p>
 * Our basic filter, all it does is take our WebSessionBean which is a wrapper around
 * the current session and passes it in the request, so that all jsps and other objects
 * can access the data, such as the current users shopping cart, his user info, and
 * other pertinent details to the session for this user.
 * <p>
 * In addition to basic session addition, we also take the content and
 * add in the velocity template engine so the session can be accessed from
 * velocity, and all content, after stripes is done with it is modified
 * with velocity.
 * <p>
 * We perform the following steps:
 * -------------------------------
 * <ol>
 * <li>  Load in the velocity toolbox so these can be exposed and used throughout
 *    the web app.
 * 
 * <li> Add the session to the queue and attributes
 *
 * <li>  Perform the filter chain and take the modified content in the form
 *    of a PrintWriter
 *
 * <li>  Modify this content with the Velocity Engine.
 *
 * <li>  Using the localeTool, we can then render all translations loaded in
 *    the appropriate strings.xml file.
 *</ol>
 *
 * @author Austin Kottke
 ********************************************************************************************/
public class ViewFilterEngine implements Filter {
 
    private StoreWebApplication webApp = StoreWebApplication.getInstance();
    private KLogger logger = KLogger.getLogger(this.toString());
    private VelocityContext velocityContext = new VelocityContext();
    private static ViewFilterEngine instance ;
    private FilterConfig filterConfig;
    private ServletContext servletContext;
 
    // Security redirector
    private SecureRedirectorActionBean secureRedir = new SecureRedirectorActionBean();
 
    // The actual path of the primary servlet. From here we can load
    // in all other files based on this path.
    private String currentPath;
    private String toolboxPath;
    private XMLToolboxManager toolboxManager;
    private Map toolBox;
 
    // A reference to the locale tool.
    private LocaleTool localeTool;
    private RequestTool requestTool;
    private BreadCrumbTool breadCrumbTool;
 
    private boolean initialized = false;
 
    // Action url manager
    private ActionBeanUrlManager actionUrlManager ;
 
    private void ViewFilterEngine(){
 
    }
 
    /**
     *
     * @return
     */
    public static ViewFilterEngine getInstance(){
        if (instance == null ){
            return new ViewFilterEngine();
        }
        return instance;
    }
 
 
 
    /**
     *
     * @param aConfig
     * @throws ServletException
     */
    public void init(FilterConfig aConfig) throws ServletException {
        this.filterConfig=aConfig;
        this.currentPath = filterConfig.getServletContext().getRealPath("");
        this.toolboxPath = currentPath + filterConfig.getInitParameter("ToolBoxPath");
        this.servletContext = filterConfig.getServletContext() ;
 
        logger.initFilters( currentPath );
        instance = this;
        try {
 
            toolboxManager = new XMLToolboxManager();
            Velocity.init(currentPath + "/WEB-INF/classes/velocity.properties");
            logger.debug("Loading velocity toolbox: " );
            toolboxManager.load( toolboxPath );
 
            // Initialize the velocity tools and add them to the
            // velocity context so they can be used in the app
            initVelocityTools();
 
        } catch (Exception ex) {
            Logger.getLogger(ViewFilterEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
 
    /**
     * Propery loads and initializes all of the velocity tools so they can be used
     * throughout the application.
     */
    public void initVelocityTools()
    {
         // Retrieve the toolbox
         toolBox = toolboxManager.getToolbox(null);
         Set keys = toolBox.keySet();
         if( keys.size() <= 0 ) return;
 
         for( Object key : keys )
         {
            String k  = key.toString();
            Object obj = toolBox.get(k);
            logger.debug("Tool object ["+k+"] = " + obj);
 
            velocityContext.put(k, obj);
 
            try
            {
                if( obj.getClass().getSuperclass().toString().indexOf("BaseTool") >= 0  )
                {
                    logger.debug("Setting tool properties: " + obj);
                    BaseTool t = (BaseTool ) obj;
                    logger.debug("Property set!");
                    t.setServletFilePath(currentPath);
                    t.setContext(velocityContext);
                    t.setServletContext(servletContext);
                }
            } catch(Exception e){}
        }
         try
         {
 
             if( toolBox.get("breadcrumbTool") != null )
             breadCrumbTool = (BreadCrumbTool) toolBox.get("breadcrumbTool");
 
             if( toolBox.get("locale") != null)
             localeTool = (LocaleTool) toolBox.get("locale");
 
             if( toolBox.get("requestTool") != null)
             requestTool = (RequestTool) toolBox.get("requestTool");
 
         } catch( Exception e )
         {
             logger.error("Error - missing locale tool and / or request tool in the toolbox.xml");
         }
    }
 
    /**========================================================================
     * Here we add the session to the webApp singleton and add the user to the
     * session queue if he is not already there. We also modify the content
     * with VTL.
     * 
     * @param request
     * @param response
     * @param chain
     * @throws java.io.IOException
     * @throws javax.servlet.ServletException
     *========================================================================*/
 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        HttpServletRequest req =  (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        PropertyTool p  = (PropertyTool) toolBox.get("propertyTool");
        /*********************************************************************
         * Initalize the tools that need the current request object.
         *********************************************************************/
 
        doRequestInitialization(p,req,resp);
        p.initProperties(req.getContextPath(),  req.getRequestURI() );
        if( ! initialized )
        {
                webApp.doInitialization();
                actionUrlManager = ActionBeanUrlManager.getActionUrlManager();
                initialized = true;
        }
 
        /*********************************************************************
         * Take the current session, and if it is not already added to
         * to the current request, add this to the current session.
         *********************************************************************/
        HttpSession s = addSessionToQueue( req, resp);
 
        /*********************************************************************
         * Check if the page should be redirected to Https.
         *********************************************************************/
       if( doHttpsCheck(p, req,resp)  )
           return;
 
        /*********************************************************************
         * Return the html stream.
         *********************************************************************/
        CharArrayWriter caw = new CharArrayWriter();
 
        logger.debug("Retrieving html stream... ["+req.getRequestURI()+"]");
 
        try
        {
 
         PrintWriter out = getHtmlStream(chain, req, resp, caw );
 
        /*********************************************************************
         * render the html stream with velocity and persist the session
         * so velocity can access this.
         *********************************************************************/
 
        velocityContext.put( "velocitySession", s );
 
        out.write(  renderVelocity( caw.toString() ).toString() );
        } catch(Exception e )
        {
            logger.error("Error: " + e.toString() );
        }
 
    }
 
    /***
     * Initializes the tools and the property tool for requests that need the
     * information. It also initializes all of the tools that are instances
     * of base tools, including setting the current request and setting the
     * current locale for the localeTool.
     * 
     * @param p
     * @param request
     * @param response
     */
    public void doRequestInitialization(PropertyTool p, HttpServletRequest request, HttpServletResponse response)
    {
        try
        {
            breadCrumbTool.setServletContextPath( request.getContextPath() );
            String curLocale = request.getParameter("locale");
            if( curLocale != null ) {
                Locale l = null;
                String lang = curLocale.split("_")[0];
                if( curLocale.indexOf("_") >= 0)
                {
                    String country = curLocale.split("_")[1];
                    l = new Locale(lang, country);
                }
                else
                {
                    if( lang.indexOf("en") >=0 )
                    l = new Locale(lang, "US");
                    else
                    l = new Locale(lang,lang);
 
                }
                localeTool.setCurrentLocale( l );
            }
 
 
 
            Collection c = toolBox.values();
            Iterator i = c.iterator();
            while( i.hasNext() )
            {
                try
                {
                     Object o = i.next();
 
                     if( o.getClass().getSuperclass().toString().indexOf("BaseTool") >= 0  )
                     {
                         //logger.debug("Base tool! " + o);
                         BaseTool t = (BaseTool) o;
                         t.setRequest(request);
                     }
 
                }catch(Exception e ){}
            }
 
 
 
        } catch(Exception e ){
            logger.error("Did you not load in the propertyTool ? - Check your velocity toolbox.xml file.");
            logger.error("Error: you might be missing a /global.properties in the site root! " + e.toString());
        }
    }
    /***
     * Modifys the request if this page should be secured or not. If it is
     * supposed to be secured, based on the global properties 'securePage' we
     * then forward to Https. If it is not supposed to be secured, then
     * we redirect to a regular url.
     *
     * @param p The property tool for lookup of the securePage property.
     * @param request The current request
     * @param response The response request.
     * @return
     */
 
    public boolean doHttpsCheck(PropertyTool p, HttpServletRequest request, HttpServletResponse response)
    {
 
        logger.debug("Secure page: " + p.get("securePage") );
 
        try
        {
            if( p.get("securePage").equals("1") && request.isSecure() == false)
            {
                logger.debug("This page should be secured...");
                String securedUrl = secureRedir.returnSecureUrl(request, request.getRequestURI() );
                logger.debug("Secure url: "  + securedUrl );
                try {
                    response.sendRedirect(securedUrl);
                    return true;
                } catch (Exception ex) {
                    logger.error("Error redirecting to url...");
                    return false;
                }
            }
 
            // Do check for if this should not be a secure page, but is in https mode.
 
 
            if( p.get("securePage").equals("0") && request.isSecure() == true)
            {
                logger.debug("This page should be NOT be secured!");
                 String regularUrl = secureRedir.returnRegularUrl(request, request.getRequestURI() );
                 try {
                    logger.debug("Redirecting to: " + regularUrl);
                    response.sendRedirect(regularUrl);
                    return true;
                } catch (Exception ex) {
                    logger.error("Error redirecting to url... " +ex.toString());
                    return false;
                }
            }
        }
        catch(Exception e ){
            return false;
        }
        return false;
    }
 
    /*
     *
     * Adds the session bean to our web app session queue, so this can be
     * referred to throughout the application
     *
     * @param request
     * @param response
     * @return Returns the HttpSession instance
     **/
 
    public HttpSession addSessionToQueue(HttpServletRequest request, HttpServletResponse response )
    {
        HttpSession currentSession = (HttpSession) request.getSession();
        WebSessionBean cartSession = null;
 
        logger.debug("Total sessions: " + webApp.getActiveSessions());
 
        boolean isSessioninQueue = webApp.isSessionInQueue(currentSession.getId() );
 
        if( ! isSessioninQueue ) {
            cartSession = new WebSessionBean ( currentSession );
            webApp.addSession( cartSession );
        }
 
        if( isSessioninQueue ) cartSession = (WebSessionBean) webApp.getSession(currentSession.getId());
 
        // on the request for this particular user, make sure the session is included
        // with the shopping info, etc.
        request.setAttribute( "sessionBean", cartSession );
 
        return cartSession;
 
    }
 
 
 
    /**
     * Returns a PrintWriter with the current Html stream, after it has gone
     * through all redirects and filters.
     *
     * We do this by making a wrapper around the current html response and then
     * writing the current content after the  filters have been performed.
     * Once we have a writer we can then modify the response with whatever is
     * needed. Currently we modify the current response with the
     * velocity template engine, so we can also use VTL in a jsp or html.
     *
     * @param chain
     * @param request
     * @param response
     * @param writer
     * @return A PrintWriter with the modified html content.
     **/
 
    public PrintWriter getHtmlStream(FilterChain chain, HttpServletRequest request, HttpServletResponse response, CharArrayWriter writer ){
        /****************************************************************
         * Add in our custom response wrapper, so all filters and content
         * are written to, then we can add in our own content once we
         * have the outputted content in string form.
         ****************************************************************/
        PrintWriter out = null;
 
        try
        {
            out = response.getWriter();
            CharRequestWrapper reqWrapper = new CharRequestWrapper( request, request.getRequestURI(), request.getRequestURL() );
            CharResponseWrapper respWrapper = new CharResponseWrapper( response );
 
            /****************************************************************
             * If what was requested was an html page, then we need to
             * still retrieve the content based on the request, since we use
             * jsp as our presentation technology we still want to serve
             * up the content based on an html string.
             ****************************************************************/
 
            chain.doFilter(reqWrapper, respWrapper);
 
            /****************************************************************
             * If we have a 404, then we forward to the error pages...
             ****************************************************************/
            boolean sendErrorPage = false;
            if( respWrapper.getErrorCode() == HttpServletResponse.SC_NOT_FOUND ) sendErrorPage = true;
            if( respWrapper.getErrorCode() == HttpServletResponse.SC_INTERNAL_SERVER_ERROR ) sendErrorPage = true;
 
            if( sendErrorPage ) respWrapper.sendRedirect(reqWrapper.getContextPath() + "/engine/error/error.jsp");
 
 
            writer.write( respWrapper.getContent());
 
 
        } catch (Throwable ex) {
            Logger.getLogger(ViewFilterEngine.class.getName()).log(Level.SEVERE, null, ex);
        } 
 
        return out;
    }
 
    /**
     *
     * @param htmlContent
     * @return
     */
    public CharArrayWriter renderVelocity(String htmlContent)
    {
 
        CharArrayWriter outputVelocity = new CharArrayWriter();
        try {
 
 
            Velocity.evaluate(velocityContext, outputVelocity, "log", htmlContent);
        } catch (Throwable ex) {
            Logger.getLogger(ViewFilterEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
 
        return outputVelocity;
    }
 
    /**
     *
     * @return
     */
    public XMLToolboxManager getToolboxManager() {
        return toolboxManager;
    }
 
    /**
     *
     * @param t
     */
    public void setToolboxManager(XMLToolboxManager t) {
         toolboxManager = t;
    }
 
    /**
     *
     */
    public void destroy() {
        webApp.clearSessions();
    }
 
    /**
     *
     * @return
     */
    public Map getToolBox() {
        return toolBox;
    }
 
    /**
     *
     * @param toolBox
     */
    public void setToolBox(Map toolBox) {
        this.toolBox = toolBox;
    }
 
 
}

A bread crumb tool, for creating breadcrumbs from a site map:

 
package org.adk.java.viewfilter.tools;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.adk.java.log.KLogger;
import org.adk.java.web.sitemap.SiteDirectory;
import org.adk.java.web.sitemap.SiteMapBuilder;
import org.adk.java.web.sitemap.SitePage;
import org.jdom.Attribute;
 
/***===============================================================================
 * The BreadCrumbTool generates a tree structure based on a site map xml file
 * located in the WEB-INF directory.
 * <p>
 * The way we do this, is through first using the {@link SiteMapBuilder} class which
 * generates a tree structure full of SiteDirectory and SitePage classes including
 * sub directories.
 * <p>
 * Then using the {@link SiteMapBuilder} class, we can retrieve the entire structure
 * in a TreeMap.
 * <p>
 * We then use velocity to create the breadcrumb as follows:<br>
 * =========================================================
 * <p>
 *   #set( $requestUri =  "$requestTool.getRequest().getRequestURI()" )
 *   #set ( $pageTitle = "")
 *   #set ( $dirs = $breadcrumbTool.getDirectory( $requestUri  ) )
 *
 *    <span  style="font-size: 10px; font-family: verdana">
 *    #foreach ($dir in $dirs )
 *       #set ( $isDisplayed = "$!dir.isDisplayed()")
 *
 *       <a href="$dir.getFinalTreeUrl()">$locale.get( "$dir.getId()" )</a>
 *    #end
 *
 *<p>
 * What this does:<br>
 * ===============
 *<p>
 * It retrieves the entire directory object and puts it in $dirs.
 *<p>
 * We then loop through each directory and generate a link and we pull the
 * title of the directory using the $locale tool.
 *<br>
 * As a note - this class needs major refactoring. I recommend another
 * version that handles dynamic directory creation.
 *
 * @see SiteMapBuilder
 * 
 * @version 0.1
 * @author Austin Kottke
 * ===============================================================================*/
 
public class BreadCrumbTool extends BaseTool {
 
    private KLogger logger = KLogger.getLogger(this.toString());
    private SiteMapBuilder primarySiteMap  = new SiteMapBuilder();
    private String siteMapXmlPath;
 
    /**
     *
     */
    public void BreadCrumbTool(){
    }
 
    /**
     *
     * @param params
     */
    public void configure(Map params)
    {
        logger.debug("configure() called.");
        siteMapXmlPath = params.get("siteMapXmlPath").toString() ;
 
    }
 
    /**
     *
     * @param requestUri
     */
    public void get( String requestUri ){
        if( ! primarySiteMap.isInitialized() ) {
            primarySiteMap.buildSiteMap( this.getServletFilePath() + siteMapXmlPath );
        }
 
        generateBreadcrumb(requestUri);
    }
 
    /**===============================================================================
     * This is the primary entry point to retrieve the breadcrumb directory.
     *
     * It returns an arraylist based on where the page request is coming
     * from.
     *
     * @param requestUri
     * @return
     *===============================================================================*/
 
    public ArrayList getDirectory( String requestUri ){
        logger.debug("getDirectory() called.");
 
        if( ! primarySiteMap.isInitialized() )
            primarySiteMap.buildSiteMap( this.getServletFilePath() + siteMapXmlPath );
 
        logger.debug("Servlet context name: " + getServletContext().getServletContextName() );
 
        String uriContextPath = this.getServletContextPath();
        String requestPath = requestUri.replace(uriContextPath, "");
        ArrayList b = generateBreadcrumb(requestPath);
 
        // Build urls...
        String url = "";
 
        for( int i=0; i<b.size(); i++ )
        {
 
            try
            {
                SiteDirectory dir = (SiteDirectory) b.get(i);
                if( dir.getDynamicPageId() != null) continue;
 
 
                url += dir.getUrl();
                SitePage p = null;
 
                if( dir.getPages().size() >= 1 )
                {
                    String pageKey = dir.getDefaultPage();
                    p = dir.getPages().get(pageKey);
                    url += "/"+p.getUrl();
                }
 
                dir.setFinalTreeUrl(url.replace(".jsp", ".html"));
 
                if( dir.getPages().size() >= 1) {
 
                    url = url.replace("/"+p.getUrl(), "");
                   // logger.debug("Modified url: " + url );
                }
 
 
            } catch (Exception e ) { }
 
        }
 
        List newbreadcrumb = (List) getRequest().getAttribute("additionalbreadcrumb");
        if( newbreadcrumb != null )
        {
            for( int j=0; j<newbreadcrumb.size(); j++)
                b.add( newbreadcrumb.get(j));
        }
 
        return b;
    }
 
    /**===============================================================================
     * Let us say that you are adding in dynamic directories and do not want to
     * use the site map, you can add urls at request time so that the bread crumb
     * shows up properly.
     *
     * This is recommended to use in case of very dynamic cases, but otherwise you
     * should configure the SiteMap.xml file.
     *
     * @param localeId The current page locale id to be displayed to the end user
     * @param urlPath the Path to the service or url being generated.
     *===============================================================================*/
 
    public void addDirectory(String localeId, String urlPath){
        logger.debug("addUrl() called.");
 
        List breadcrumb = getAdditionalBreadcrumb();
 
        SiteDirectory dir = new SiteDirectory();
        dir.setId(localeId);
        dir.setFinalTreeUrl( urlPath );
        dir.setDynamicPageId( "dynamic" );
        breadcrumb.add(dir);
 
        getRequest().setAttribute("additionalbreadcrumb", breadcrumb);
    }
 
    /***
     * Adds a page using the localeId as the name, this is primarily
     * used for static pages that do not change.
     * 
     * @param localeId
     */
 
    public void addPage(String localeId ){
        List breadcrumb = getAdditionalBreadcrumb();
 
        SitePage p = new SitePage();
        p.setId( localeId );
 
        breadcrumb.add(p);
    }
 
    /***
     * Used for dynamic pages that change the title based on a specific
     * attribute passed.
     * 
     * @param localeId
     * @param dynamicPageTitleAttribute
     */
 
     public void addPage(String localeId, String dynamicPageTitleAttribute ){
        List breadcrumb = getAdditionalBreadcrumb();
 
        SitePage p = new SitePage();
        p.setId( localeId );
        p.setDynamicPageTitle( dynamicPageTitleAttribute );
 
        breadcrumb.add(p);
    }
    /***
     * Stores a bread crumb in the request attributes. Used primarily for
     * creating directories that are marked as dynamic. We then can
     * add on additional directories and subdirectories at will. Particularly
     * useful for pages that have very dynamic page structures.
     * 
     * @return List A breadcrumb list that will be added on to the end of the breadcrumb
     */
    public List getAdditionalBreadcrumb(){
        List breadcrumb = null ;
        try {
            if( getRequest().getAttribute("additionalbreadcrumb") != null )
                breadcrumb = (List)getRequest().getAttribute("additionalbreadcrumb");
            else
                breadcrumb = new ArrayList();
 
        } catch(Exception e ){}
        return breadcrumb;
    }
 
 
    /**
     *
     * @return
     */
    public SitePage getPage(){
 
        return null;
    }
 
    /****************************************************************************
     * Creates the bread crumb.
     * 
     * @param requestUri
     * @return
     ****************************************************************************/
    public ArrayList generateBreadcrumb(String requestUri){
 
        logger.debug("generateBreadcrumb for: " + requestUri);
        TreeMap<String,SiteDirectory>  map = this.primarySiteMap.getSiteMap();
        Set directorySet = map.entrySet();
        String reqUri = requestUri;
 
        // Check if the action is in the request uri, which needs to be taken
        // out as this is not a top level directory
        if( requestUri.indexOf("action") >= 0 )
            reqUri = requestUri.split("/action")[1];
 
        String [] directories = reqUri.split("/");
 
        SiteDirectory parentDir = null;
        ArrayList breadcrumb = new ArrayList();
 
        breadcrumb.add(map.get("dir_home"));
 
        logger.debug("Directory size: " + directorySet.size());
 
        for( int i=0; i<directorySet.size(); i++ )  {
            String key = directorySet.toArray()[i].toString().split("=")[0];
            SiteDirectory d = map.get(key);
            String topLeveldirectoryName = d.getUrl().replace("/", "");
 
            for( int k=0; k<directories.length; k++ )
            {
                String directoryToFind = directories[1].toString().trim();
 
                if( directoryToFind.length() > 1 ) {
 
                    if( topLeveldirectoryName.equals(directoryToFind))
                    {
                        logger.debug("Matching top level directory: " + topLeveldirectoryName );
                        getFinalDirectoryStructure(d, directories, breadcrumb, 0);
                        return breadcrumb;
                    }
                }
            }
 
        }
 
 
 
        return breadcrumb;
    }
 
    /***===============================================================================
     * Generates the final directory used for the breadcrumb, this can include
     * any number of directories and a single page to send the url to.
     * 
     * @param dir 
     * @param requestPath
     * @param intDirIndex
     * @param breadcrumb
     * ===============================================================================*/
 
    public void getFinalDirectoryStructure(SiteDirectory dir, String[] requestPath, ArrayList breadcrumb, int intDirIndex)
    {
        breadcrumb.add( dir );
 
        for( int k=0; k<requestPath.length; k++ )
        {
            String pathToFind = requestPath[k].toString().trim();
 
            int dirLength = dir.getSubcategories().size();
            int pageLength = dir.getPages().size();
 
            Set pages = dir.getPages().entrySet();
            Set directories = dir.getSubcategories().entrySet();
 
            //logger.debug("Current dir index: " + dir.getId() );
            // Check directories and then check pages.
            for( int i=0; i<dirLength; i++ )
            {
                String dirKey = directories.toArray()[i].toString().split("=")[0];
                SiteDirectory d = dir.getSubcategories().get(dirKey);
 
                if( pathToFind.equals( d.getUrl().replace("/", "") ) )  {
                    logger.debug("Directory: " + d.getDynamicPageId() );
                    getFinalDirectoryStructure(d, requestPath, breadcrumb, i);
                    return;
                }
 
            }
 
            // Now go through the last few pages...
            for( int m=0; m<pageLength; m++ )
            {
                String pageKey = pages.toArray()[m].toString().split("=")[0];
                SitePage p =  dir.getPages().get(pageKey);
 
                String url = p.getUrl();
 
                if( url.equals( requestPath[k]) || url.equals( requestPath[k].replace(".html", ".jsp") ) ){
                    logger.debug("Found a page match: ["+p.getUrl()+"] in directory: ["+dir.getId()+"]");
 
                    breadcrumb.add(p);
                    return;
                }
            }
        }
 
    }
 
    /****************************************************************************
     * Builds a dynamic directory based on the requestUri. A store has
     * many categories and sub categories which are generated dynamically
     * and are not in the site map.
     * <p>
     * As a result of this, it is impossible if not tedious to create an entire
     * directory structure based on a possible directory structure that has
     * many infinite possibilities of shopping options.
     *<p>
     * So to generate the dynamic directory we simply build the structure based
     * on the uri and let the action handler correctly go to the correct directory
     * structure.
     *<p>
     * Example of a Directory:
     * ------------------------
     * <p>
     *
     * Home > Store > Books > Fiction > New and Used > Foundation Series
     * <p>
     * As you can see the directory structure is very long and the categories
     * are built within Books to Fiction to New and Used.
     *
     * @deprecated Not used, use the addDirectory and addPage methods as these
     *             are less messy.
     ****************************************************************************/
 
    public void addDynamicDirectoryToBreadCrumb( ArrayList breadcrumb, SiteDirectory d, Object[] requestDirectories)
    {
        logger.debug("addDynamicDirectoryToBreadCrumb() called: " + d );
 
        // ==============================================================================
        // We need to first find what the directory name is and in the current path array
        // contains the requestUri. We find the index into this path array so we can then
        // parse the remaining part of the array and build a dynamic directory with all
        // path info taken into account.
        // ==============================================================================
        String currentDirPathName = d.getUrl().split("/")[1];
        int currentDirectoryIndex = 0;
        for( int k=0; k<requestDirectories.length; k++ ) {
            if( requestDirectories[k].toString().equals( currentDirPathName ) ) currentDirectoryIndex=k;
        }
        // ==============================================================================
        // Now we have the current directory index, we now need to build the correct
        // dynamic directory.
        //
        // The remaining directory names correspond to localeIds and refer to
        // an action service.
        // ==============================================================================
        Attribute e = d.getAttributeById("dynamicUrl");
        String previousUrl = d.getAttributeById("previousUrl").getValue();
 
        SiteDirectory dynamicDir = new SiteDirectory();
        if( previousUrl != null )
        dynamicDir.setFinalTreeUrl( getServletContextPath() + previousUrl + requestDirectories[currentDirectoryIndex+1] );
        dynamicDir.setId( requestDirectories[currentDirectoryIndex+1].toString() );
        dynamicDir.setDynamicPageId("dynamic");
        breadcrumb.add( dynamicDir );
 
        for( int i=currentDirectoryIndex+2; i<requestDirectories.length; i++)
        {
            SiteDirectory newDynamicDir = new SiteDirectory();
 
            if( requestDirectories[i].toString().indexOf(".html") <= -1 )
            {
                newDynamicDir.setId( requestDirectories[i].toString() );
                newDynamicDir.setFinalTreeUrl( getServletContextPath() + e.getValue() + "/" + requestDirectories[i] );
                newDynamicDir.setDynamicPageId("dynamic");
                logger.debug("Directories: " +requestDirectories[i] );
                breadcrumb.add( newDynamicDir );
            }
 
            // This is a page, add a site page to the breadcrumb.
            if( requestDirectories[i].toString().indexOf(".html") >= 0 )
            {
                SitePage p = new SitePage();
                p.setId(requestDirectories[i].toString().split(".html")[0]);
                breadcrumb.add(p);
            }
 
        }
 
        logger.debug("Index: " + currentDirectoryIndex );
    }
}

If anyone wants the source let me know =)

Austin

Back Top

Responses to “J2EE Filter that modifies a Stripes response for Velocity rendering”

  1. test

Leave a Reply

Your email address will not be published. Required fields are marked *

*