Clover coverage report - Code Coverage for tapestry release 4.0-rc-2
Coverage timestamp: Sat Dec 17 2005 09:39:46 PST
file stats: LOC: 312   Methods: 11
NCLOC: 155   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
PageSpecificationResolverImpl.java 100% 100% 100% 100%
coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.tapestry.resolver;
 16   
 17    import org.apache.commons.logging.Log;
 18    import org.apache.hivemind.ApplicationRuntimeException;
 19    import org.apache.hivemind.Resource;
 20    import org.apache.hivemind.impl.LocationImpl;
 21    import org.apache.tapestry.INamespace;
 22    import org.apache.tapestry.IRequestCycle;
 23    import org.apache.tapestry.PageNotFoundException;
 24    import org.apache.tapestry.Tapestry;
 25    import org.apache.tapestry.services.ComponentPropertySource;
 26    import org.apache.tapestry.spec.ComponentSpecification;
 27    import org.apache.tapestry.spec.IComponentSpecification;
 28   
 29    /**
 30    * Performs the tricky work of resolving a page name to a page specification. The search for pages
 31    * in the application namespace is the most complicated, since Tapestry searches for pages that
 32    * aren't explicitly defined in the application specification. The search, based on the
 33    * <i>simple-name </i> of the page, goes as follows:
 34    * <ul>
 35    * <li>As declared in the application specification
 36    * <li><i>simple-name </i>.page in the same folder as the application specification
 37    * <li><i>simple-name </i> page in the WEB-INF/ <i>servlet-name </i> directory of the context root
 38    * <li><i>simple-name </i>.page in WEB-INF
 39    * <li><i>simple-name </i>.page in the application root (within the context root)
 40    * <li><i>simple-name </i>.html as a template in the application root, for which an implicit
 41    * specification is generated
 42    * <li>By searching the framework namespace
 43    * <li>By invoking
 44    * {@link org.apache.tapestry.resolver.ISpecificationResolverDelegate#findPageSpecification(IRequestCycle, INamespace, String)}
 45    * </ul>
 46    * <p>
 47    * Pages in a component library are searched for in a more abbreviated fashion:
 48    * <ul>
 49    * <li>As declared in the library specification
 50    * <li><i>simple-name </i>.page in the same folder as the library specification
 51    * <li>By searching the framework namespace
 52    * <li>By invoking
 53    * {@link org.apache.tapestry.resolver.ISpecificationResolverDelegate#findPageSpecification(IRequestCycle, INamespace, String)}
 54    * </ul>
 55    *
 56    * @see org.apache.tapestry.engine.IPageSource
 57    * @author Howard Lewis Ship
 58    * @since 3.0
 59    */
 60   
 61    public class PageSpecificationResolverImpl extends AbstractSpecificationResolver implements
 62    PageSpecificationResolver
 63    {
 64    private static final String WEB_INF = "/WEB-INF/";
 65   
 66    /** set by container */
 67    private Log _log;
 68   
 69    /** Set by resolve() */
 70    private String _simpleName;
 71   
 72    /** @since 4.0 * */
 73    private INamespace _applicationNamespace;
 74   
 75    /** @since 4.0 * */
 76    private INamespace _frameworkNamespace;
 77   
 78    /** @since 4.0 */
 79   
 80    private ComponentPropertySource _componentPropertySource;
 81   
 82  108 public void initializeService()
 83    {
 84  108 _applicationNamespace = getSpecificationSource().getApplicationNamespace();
 85  108 _frameworkNamespace = getSpecificationSource().getFrameworkNamespace();
 86   
 87  108 super.initializeService();
 88    }
 89   
 90  137 protected void reset()
 91    {
 92  137 _simpleName = null;
 93   
 94  137 super.reset();
 95    }
 96   
 97    /**
 98    * Resolve the name (which may have a library id prefix) to a namespace (see
 99    * {@link #getNamespace()}) and a specification (see {@link #getSpecification()}).
 100    *
 101    * @throws ApplicationRuntimeException
 102    * if the name cannot be resolved
 103    */
 104   
 105  137 public void resolve(IRequestCycle cycle, String prefixedName)
 106    {
 107  137 reset();
 108   
 109  137 INamespace namespace = null;
 110   
 111  137 int colonx = prefixedName.indexOf(':');
 112   
 113  137 if (colonx > 0)
 114    {
 115  5 _simpleName = prefixedName.substring(colonx + 1);
 116  5 String namespaceId = prefixedName.substring(0, colonx);
 117   
 118  5 namespace = findNamespaceForId(_applicationNamespace, namespaceId);
 119    }
 120    else
 121    {
 122  132 _simpleName = prefixedName;
 123   
 124  132 namespace = _applicationNamespace;
 125    }
 126   
 127  137 setNamespace(namespace);
 128   
 129  137 if (namespace.containsPage(_simpleName))
 130    {
 131  43 setSpecification(namespace.getPageSpecification(_simpleName));
 132  43 return;
 133    }
 134   
 135    // Not defined in the specification, so it's time to hunt it down.
 136   
 137  94 searchForPage(cycle);
 138   
 139  92 if (getSpecification() == null)
 140  2 throw new PageNotFoundException(ResolverMessages.noSuchPage(_simpleName, namespace));
 141    }
 142   
 143  133 public String getSimplePageName()
 144    {
 145  133 return _simpleName;
 146    }
 147   
 148  94 private void searchForPage(IRequestCycle cycle)
 149    {
 150  94 INamespace namespace = getNamespace();
 151   
 152  94 if (_log.isDebugEnabled())
 153  8 _log.debug(ResolverMessages.resolvingPage(_simpleName, namespace));
 154   
 155    // Check with and without the leading slash
 156   
 157  94 if (_simpleName.regionMatches(true, 0, WEB_INF, 0, WEB_INF.length())
 158    || _simpleName.regionMatches(true, 0, WEB_INF, 1, WEB_INF.length() - 1))
 159  2 throw new ApplicationRuntimeException(ResolverMessages.webInfNotAllowed(_simpleName));
 160   
 161  92 String expectedName = _simpleName + ".page";
 162   
 163  92 Resource namespaceLocation = namespace.getSpecificationLocation();
 164   
 165    // See if there's a specification file in the same folder
 166    // as the library or application specification that's
 167    // supposed to contain the page.
 168   
 169  92 if (found(namespaceLocation, expectedName))
 170  43 return;
 171   
 172  49 if (namespace.isApplicationNamespace())
 173    {
 174   
 175    // The application namespace gets some extra searching.
 176   
 177  47 if (found(getWebInfAppLocation(), expectedName))
 178  1 return;
 179   
 180  46 if (found(getWebInfLocation(), expectedName))
 181  1 return;
 182   
 183  45 if (found(getContextRoot(), expectedName))
 184  1 return;
 185   
 186    // The wierd one ... where we see if there's a template in the application root
 187    // location.
 188   
 189  44 String templateName = _simpleName + "." + getTemplateExtension();
 190   
 191  44 Resource templateResource = getContextRoot().getRelativeResource(templateName);
 192   
 193  44 if (_log.isDebugEnabled())
 194  2 _log.debug(ResolverMessages.checkingResource(templateResource));
 195   
 196  44 if (templateResource.getResourceURL() != null)
 197    {
 198  18 setupImplicitPage(templateResource, namespaceLocation);
 199  18 return;
 200    }
 201   
 202    // Not found in application namespace, so maybe its a framework page.
 203   
 204  26 if (_frameworkNamespace.containsPage(_simpleName))
 205    {
 206  25 if (_log.isDebugEnabled())
 207  1 _log.debug(ResolverMessages.foundFrameworkPage(_simpleName));
 208   
 209  25 setNamespace(_frameworkNamespace);
 210   
 211    // Note: This implies that normal lookup rules don't work
 212    // for the framework! Framework pages must be
 213    // defined in the framework library specification.
 214   
 215  25 setSpecification(_frameworkNamespace.getPageSpecification(_simpleName));
 216  25 return;
 217    }
 218    }
 219   
 220    // Not found by any normal rule, so its time to
 221    // consult the delegate.
 222   
 223  3 IComponentSpecification specification = getDelegate().findPageSpecification(
 224    cycle,
 225    namespace,
 226    _simpleName);
 227   
 228  3 if (specification != null)
 229    {
 230  1 setSpecification(specification);
 231  1 install();
 232    }
 233    }
 234   
 235  18 private void setupImplicitPage(Resource resource, Resource namespaceLocation)
 236    {
 237  18 if (_log.isDebugEnabled())
 238  1 _log.debug(ResolverMessages.foundHTMLTemplate(resource));
 239   
 240    // TODO The SpecFactory in Specification parser should be used in some way to
 241    // create an IComponentSpecification!
 242   
 243    // The virtual location of the page specification is relative to the
 244    // namespace (typically, the application specification). This will be used when
 245    // searching for the page's message catalog or other related assets.
 246   
 247  18 Resource pageResource = namespaceLocation.getRelativeResource(_simpleName + ".page");
 248   
 249  18 IComponentSpecification specification = new ComponentSpecification();
 250  18 specification.setPageSpecification(true);
 251  18 specification.setSpecificationLocation(pageResource);
 252  18 specification.setLocation(new LocationImpl(resource));
 253   
 254  18 setSpecification(specification);
 255   
 256  18 install();
 257    }
 258   
 259  230 private boolean found(Resource baseResource, String expectedName)
 260    {
 261  230 Resource resource = baseResource.getRelativeResource(expectedName);
 262   
 263  230 if (_log.isDebugEnabled())
 264  20 _log.debug(ResolverMessages.checkingResource(resource));
 265   
 266  230 if (resource.getResourceURL() == null)
 267  184 return false;
 268   
 269  46 setSpecification(getSpecificationSource().getPageSpecification(resource));
 270   
 271  46 install();
 272   
 273  46 return true;
 274    }
 275   
 276  65 private void install()
 277    {
 278  65 INamespace namespace = getNamespace();
 279  65 IComponentSpecification specification = getSpecification();
 280   
 281  65 if (_log.isDebugEnabled())
 282  4 _log.debug(ResolverMessages.installingPage(_simpleName, namespace, specification));
 283   
 284  65 namespace.installPageSpecification(_simpleName, specification);
 285    }
 286   
 287    /**
 288    * If the namespace defines the template extension (as property
 289    * {@link Tapestry#TEMPLATE_EXTENSION_PROPERTY}, then that is used, otherwise the default is
 290    * used.
 291    */
 292   
 293  44 private String getTemplateExtension()
 294    {
 295  44 return _componentPropertySource.getNamespaceProperty(
 296    getNamespace(),
 297    Tapestry.TEMPLATE_EXTENSION_PROPERTY);
 298    }
 299   
 300    /** @since 4.0 */
 301   
 302  104 public void setLog(Log log)
 303    {
 304  104 _log = log;
 305    }
 306   
 307    /** @since 4.0 */
 308  97 public void setComponentPropertySource(ComponentPropertySource componentPropertySource)
 309    {
 310  97 _componentPropertySource = componentPropertySource;
 311    }
 312    }