Author: thorsten Date: Wed Mar 31 10:33:38 2010 New Revision: 929463 URL: http://svn.apache.org/viewvc?rev=929463&view=rev Log: Split of the RecursiveDirectoryTraversalAction into an abstract super class to reuse the common functionality for a new RecursiveDirectoryTraversalDualAction, which will not only fall back to the fallback structurer but always looks as well for the request name structurer
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/AbstractTraversal.java forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalDualAction.java Modified: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalAction.java Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/AbstractTraversal.java URL: http://svn.apache.org/viewvc/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/AbstractTraversal.java?rev=929463&view=auto ============================================================================== --- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/AbstractTraversal.java (added) +++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/AbstractTraversal.java Wed Mar 31 10:33:38 2010 @@ -0,0 +1,134 @@ +package org.apache.forrest.dispatcher.acting; + +import org.apache.avalon.framework.parameters.ParameterException; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.cocoon.acting.ServiceableAction; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceResolver; + +public abstract class AbstractTraversal extends ServiceableAction { + + + SourceResolver resolver = null; + String rest; + String projectFallback; + String projectDir; + String projectExtension; + String request; + + public AbstractTraversal() { + super(); + } + + /** + * @return Returns the projectDir. + */ + public String getProjectDir() { + return projectDir; + } + + /** + * @param projectDir + * The projectDir to set. + */ + public void setProjectDir(String projectDir) { + this.projectDir = projectDir; + } + + /** + * @return Returns the projectExtension. + */ + public String getProjectExtension() { + return projectExtension; + } + + /** + * @param projectExtension + * The projectExtension to set. + */ + public void setProjectExtension(String projectExtension) { + this.projectExtension = projectExtension; + } + + /** + * @return Returns the projectFallback. + */ + public String getProjectFallback() { + return projectFallback; + } + + /** + * @param projectFallback + * The projectFallback to set. + */ + public void setProjectFallback(String projectFallback) { + this.projectFallback = projectFallback; + } + + /** + * @return Returns the request. + */ + public String getRequest() { + return request; + } + + /** + * @param request + * The request to set. + */ + public void setRequest(String request) { + this.request = request; + } + + /** + * @return Returns the resolver. + */ + public SourceResolver getResolver() { + return resolver; + } + + /** + * @param resolver + * The resolver to set. + */ + public void setResolver(SourceResolver resolver) { + this.resolver = resolver; + } + + /** + * @return Returns the rest. + */ + public String getRest() { + return rest; + } + + /** + * @param rest + * The rest to set. + */ + public void setRest(String rest) { + this.rest = rest; + } + + protected String getFather() { + return this.getRest().substring(0, this.getRest().lastIndexOf("/")); + } + + /** + * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source) + */ + public void release(Source source) { + if (source != null) { + resolver.release(source); + } + } + + protected void prepare(Parameters parameters) throws ParameterException { + this.setRequest(parameters.getParameter("request")); + this.setProjectFallback(parameters.getParameter("projectFallback")); + this.setProjectExtension(parameters.getParameter("projectExtension")); + this.setProjectDir(parameters.getParameter("projectDir")); + this.setRest(this.getRequest()); + } + +} \ No newline at end of file Modified: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalAction.java URL: http://svn.apache.org/viewvc/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalAction.java?rev=929463&r1=929462&r2=929463&view=diff ============================================================================== --- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalAction.java (original) +++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalAction.java Wed Mar 31 10:33:38 2010 @@ -21,13 +21,11 @@ import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; -import org.apache.avalon.framework.parameters.ParameterException; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.thread.ThreadSafe; -import org.apache.cocoon.acting.ServiceableAction; import org.apache.cocoon.environment.Redirector; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceResolver; @@ -61,15 +59,12 @@ import org.apache.forrest.dispatcher.exc * </map:act> * */ -public class RecursiveDirectoryTraversalAction extends ServiceableAction +public class RecursiveDirectoryTraversalAction extends AbstractTraversal implements ThreadSafe, Serviceable { SourceResolver resolver = null; HashMap map = new HashMap(); - private String request, projectFallback, projectExtension, projectDir, - rest; - /** * Set the current <code>ComponentManager</code> instance used by this * <code>Composable</code>. @@ -78,7 +73,7 @@ public class RecursiveDirectoryTraversal */ public void service(ServiceManager manager) throws ServiceException { - this.resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); + setResolver((SourceResolver) manager.lookup(SourceResolver.ROLE)); } /* @@ -188,109 +183,4 @@ public class RecursiveDirectoryTraversal } } - /** - * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source) - */ - public void release(Source source) { - if(source!=null){ - resolver.release(source); - } - } - private void prepare(Parameters parameters) throws ParameterException { - this.setRequest(parameters.getParameter("request")); - this.setProjectFallback(parameters.getParameter("projectFallback")); - this.setProjectExtension(parameters.getParameter("projectExtension")); - this.setProjectDir(parameters.getParameter("projectDir")); - this.setRest(this.getRequest()); - } - - /** - * @return Returns the projectDir. - */ - public String getProjectDir() { - return projectDir; - } - - /** - * @param projectDir - * The projectDir to set. - */ - public void setProjectDir(String projectDir) { - this.projectDir = projectDir; - } - - /** - * @return Returns the projectExtension. - */ - public String getProjectExtension() { - return projectExtension; - } - - /** - * @param projectExtension - * The projectExtension to set. - */ - public void setProjectExtension(String projectExtension) { - this.projectExtension = projectExtension; - } - - /** - * @return Returns the projectFallback. - */ - public String getProjectFallback() { - return projectFallback; - } - - /** - * @param projectFallback - * The projectFallback to set. - */ - public void setProjectFallback(String projectFallback) { - this.projectFallback = projectFallback; - } - - /** - * @return Returns the request. - */ - public String getRequest() { - return request; - } - - /** - * @param request - * The request to set. - */ - public void setRequest(String request) { - this.request = request; - } - - /** - * @return Returns the resolver. - */ - public SourceResolver getResolver() { - return resolver; - } - - /** - * @param resolver - * The resolver to set. - */ - public void setResolver(SourceResolver resolver) { - this.resolver = resolver; - } - - /** - * @return Returns the rest. - */ - public String getRest() { - return rest; - } - - /** - * @param rest - * The rest to set. - */ - public void setRest(String rest) { - this.rest = rest; - } } Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalDualAction.java URL: http://svn.apache.org/viewvc/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalDualAction.java?rev=929463&view=auto ============================================================================== --- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalDualAction.java (added) +++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/acting/RecursiveDirectoryTraversalDualAction.java Wed Mar 31 10:33:38 2010 @@ -0,0 +1,175 @@ +/* + * 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.forrest.dispatcher.acting; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.environment.Redirector; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceResolver; +import org.apache.forrest.dispatcher.exception.DispatcherException; + +/** + * Calculates which location to return for a given directory. Here we are + * traversing the tree till we reach its root. + * <p> + * We are looking first in the request string and then using a fallback + * algorithm to find alternative fallbacks. + * <p> + * e.g. the request is "sample/index". First choice is to find: + * {$projectDir}sample/index{$projectExtension}<br> + * If the file does not exist we will try with the fallback file + * {$projectDir}sample/{$projectFallback}{$projectExtension}<br> + * The last file we will try in our example is + * {$projectDir}{$projectFallback}{$projectExtension}.<br> + * With this we have reached the root directory and we cannot find the requested + * file the action will return null. + * <p> + * <map:act type="RecursiveDirectoryTraversalAction"><br> + * <map:parameter value="{../1}{1}" name="request"/><br> + * <map:parameter value="{properties:dispatcher.theme}" + * name="projectFallback"/><br> + * <map:parameter value="{properties:dispatcher.theme-ext}" + * name="projectExtension"/><br> + * <map:parameter value="{properties:resources}structurer/url/" + * name="projectDir"/><br> + * <!-- url project-based theme-based = directory-based / parent-directory + * based (recursively) --><br> + * <map:location src="{uri}" /><br> + * </map:act> + * + */ +public class RecursiveDirectoryTraversalDualAction extends AbstractTraversal + implements ThreadSafe, Serviceable { + + HashMap map = new HashMap(); + private String firstMatchPattern; + + /** + * Set the current <code>ComponentManager</code> instance used by this + * <code>Composable</code>. + * + * @throws ServiceException + */ + + public void service(ServiceManager manager) throws ServiceException { + setResolver((SourceResolver) manager.lookup(SourceResolver.ROLE)); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.cocoon.acting.Action#act(org.apache.cocoon.environment.Redirector + * , org.apache.cocoon.environment.SourceResolver, java.util.Map, + * java.lang.String, org.apache.avalon.framework.parameters.Parameters) + */ + public Map act(Redirector redirector, + org.apache.cocoon.environment.SourceResolver resolver, + Map objectModel, String source, Parameters parameters) + throws Exception { + this.prepare(parameters); + map = new HashMap(); + Map returnMap = act(); + return returnMap; + } + + /** Return a Map if Source 'uri' resolves and exists. */ + public Map act() { + String uri = this.getProjectDir() + this.getRequest() + + this.getProjectExtension(); + Source src = null; + + // The locationmap module will return null if there is no match for + // the supplied hint, without the following the URI will be resolved to + // the context root, which always exists, but does not contain a valid + // resource. + if (uri == null || uri == "") { + return null; + } + + try { + int index = uri.lastIndexOf("/"); + int rest = getRequest().lastIndexOf("/"); + if (rest > -1){ + this.setRest(getFather()); + } + this.firstMatchPattern = uri.substring(index + 1); + this.computeResponseURIFirstMatch(uri, src); + + // src = resolver.resolveURI(uri); + if (this.map.containsKey("uri")) { + return this.map; + } else { + return null; + } + } catch (DispatcherException e) { + getLogger().warn( + "Error reading from source '" + uri + "': " + + e.getMessage()); + return null; + } finally { + release(src); + } + } + + private void computeResponseURIFirstMatch(String uri, Source src) + throws DispatcherException { + try { + src = resolver.resolveURI(uri); + if (src.exists()) { + this.map.put("uri", uri); + } else { + uri = replaceLast(uri); + src = resolver.resolveURI(uri); + if (src.exists()) { + this.map.put("uri", uri); + return; + } + if (this.getRest().lastIndexOf("/") > -1) { + this.setRest(getFather()); + uri = this.getProjectDir() + this.getRest() + "/" + + this.firstMatchPattern; + this.computeResponseURIFirstMatch(uri, src); + } + } + } catch (MalformedURLException e) { + throw new DispatcherException(e); + } catch (IOException e) { + throw new DispatcherException(e); + } finally { + release(src); + } + } + + private String replaceLast(String uri) { + String newUri = this.getProjectDir(); + int index = uri.lastIndexOf("/"); + if (index > -1) { + newUri =uri.substring(0, index)+ "/"; + } + return newUri + this.getProjectFallback() + this.getProjectExtension(); + } +}