Clover coverage report - Code Coverage for tapestry release 4.0-beta-4
Coverage timestamp: Wed Aug 10 2005 21:19:31 EDT
file stats: LOC: 302   Methods: 11
NCLOC: 150   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    /** set by container */
 65    private Log _log;
 66   
 67    /** Set by resolve() */
 68    private String _simpleName;
 69   
 70    /** @since 4.0 * */
 71    private INamespace _applicationNamespace;
 72   
 73    /** @since 4.0 * */
 74    private INamespace _frameworkNamespace;
 75   
 76    /** @since 4.0 */
 77   
 78    private ComponentPropertySource _componentPropertySource;
 79   
 80  114 public void initializeService()
 81    {
 82  114 _applicationNamespace = getSpecificationSource().getApplicationNamespace();
 83  114 _frameworkNamespace = getSpecificationSource().getFrameworkNamespace();
 84   
 85  114 super.initializeService();
 86    }
 87   
 88  144 protected void reset()
 89    {
 90  144 _simpleName = null;
 91   
 92  144 super.reset();
 93    }
 94   
 95    /**
 96    * Resolve the name (which may have a library id prefix) to a namespace (see
 97    * {@link #getNamespace()}) and a specification (see {@link #getSpecification()}).
 98    *
 99    * @throws ApplicationRuntimeException
 100    * if the name cannot be resolved
 101    */
 102   
 103  144 public void resolve(IRequestCycle cycle, String prefixedName)
 104    {
 105  144 reset();
 106   
 107  144 INamespace namespace = null;
 108   
 109  144 int colonx = prefixedName.indexOf(':');
 110   
 111  144 if (colonx > 0)
 112    {
 113  5 _simpleName = prefixedName.substring(colonx + 1);
 114  5 String namespaceId = prefixedName.substring(0, colonx);
 115   
 116  5 namespace = findNamespaceForId(_applicationNamespace, namespaceId);
 117    }
 118    else
 119    {
 120  139 _simpleName = prefixedName;
 121   
 122  139 namespace = _applicationNamespace;
 123    }
 124   
 125  144 setNamespace(namespace);
 126   
 127  144 if (namespace.containsPage(_simpleName))
 128    {
 129  43 setSpecification(namespace.getPageSpecification(_simpleName));
 130  43 return;
 131    }
 132   
 133    // Not defined in the specification, so it's time to hunt it down.
 134   
 135  101 searchForPage(cycle);
 136   
 137  101 if (getSpecification() == null)
 138  2 throw new PageNotFoundException(ResolverMessages.noSuchPage(_simpleName, namespace));
 139    }
 140   
 141  142 public String getSimplePageName()
 142    {
 143  142 return _simpleName;
 144    }
 145   
 146  101 private void searchForPage(IRequestCycle cycle)
 147    {
 148  101 INamespace namespace = getNamespace();
 149   
 150  101 if (_log.isDebugEnabled())
 151  8 _log.debug(ResolverMessages.resolvingPage(_simpleName, namespace));
 152   
 153  101 String expectedName = _simpleName + ".page";
 154   
 155  101 Resource namespaceLocation = namespace.getSpecificationLocation();
 156   
 157    // See if there's a specification file in the same folder
 158    // as the library or application specification that's
 159    // supposed to contain the page.
 160   
 161  101 if (found(namespaceLocation.getRelativeResource(expectedName)))
 162  47 return;
 163   
 164  54 if (namespace.isApplicationNamespace())
 165    {
 166   
 167    // The application namespace gets some extra searching.
 168   
 169  52 if (found(getWebInfAppLocation().getRelativeResource(expectedName)))
 170  1 return;
 171   
 172  51 if (found(getWebInfLocation().getRelativeResource(expectedName)))
 173  1 return;
 174   
 175  50 if (found(getContextRoot().getRelativeResource(expectedName)))
 176  1 return;
 177   
 178    // The wierd one ... where we see if there's a template in the application root
 179    // location.
 180   
 181  49 String templateName = _simpleName + "." + getTemplateExtension();
 182   
 183  49 Resource templateResource = getContextRoot().getRelativeResource(templateName);
 184   
 185  49 if (_log.isDebugEnabled())
 186  2 _log.debug(ResolverMessages.checkingResource(templateResource));
 187   
 188  49 if (templateResource.getResourceURL() != null)
 189    {
 190  19 setupImplicitPage(templateResource, namespaceLocation);
 191  19 return;
 192    }
 193   
 194    // Not found in application namespace, so maybe its a framework page.
 195   
 196  30 if (_frameworkNamespace.containsPage(_simpleName))
 197    {
 198  29 if (_log.isDebugEnabled())
 199  1 _log.debug(ResolverMessages.foundFrameworkPage(_simpleName));
 200   
 201  29 setNamespace(_frameworkNamespace);
 202   
 203    // Note: This implies that normal lookup rules don't work
 204    // for the framework! Framework pages must be
 205    // defined in the framework library specification.
 206   
 207  29 setSpecification(_frameworkNamespace.getPageSpecification(_simpleName));
 208  29 return;
 209    }
 210    }
 211   
 212    // Not found by any normal rule, so its time to
 213    // consult the delegate.
 214   
 215  3 IComponentSpecification specification = getDelegate().findPageSpecification(
 216    cycle,
 217    namespace,
 218    _simpleName);
 219   
 220  3 if (specification != null)
 221    {
 222  1 setSpecification(specification);
 223  1 install();
 224    }
 225    }
 226   
 227  19 private void setupImplicitPage(Resource resource, Resource namespaceLocation)
 228    {
 229  19 if (_log.isDebugEnabled())
 230  1 _log.debug(ResolverMessages.foundHTMLTemplate(resource));
 231   
 232    // TODO The SpecFactory in Specification parser should be used in some way to
 233    // create an IComponentSpecification!
 234   
 235    // The virtual location of the page specification is relative to the
 236    // namespace (typically, the application specification). This will be used when
 237    // searching for the page's message catalog or other related assets.
 238   
 239  19 Resource pageResource = namespaceLocation.getRelativeResource(_simpleName + ".page");
 240   
 241  19 IComponentSpecification specification = new ComponentSpecification();
 242  19 specification.setPageSpecification(true);
 243  19 specification.setSpecificationLocation(pageResource);
 244  19 specification.setLocation(new LocationImpl(resource));
 245   
 246  19 setSpecification(specification);
 247   
 248  19 install();
 249    }
 250   
 251  254 private boolean found(Resource resource)
 252    {
 253  254 if (_log.isDebugEnabled())
 254  20 _log.debug(ResolverMessages.checkingResource(resource));
 255   
 256  254 if (resource.getResourceURL() == null)
 257  204 return false;
 258   
 259  50 setSpecification(getSpecificationSource().getPageSpecification(resource));
 260   
 261  50 install();
 262   
 263  50 return true;
 264    }
 265   
 266  70 private void install()
 267    {
 268  70 INamespace namespace = getNamespace();
 269  70 IComponentSpecification specification = getSpecification();
 270   
 271  70 if (_log.isDebugEnabled())
 272  4 _log.debug(ResolverMessages.installingPage(_simpleName, namespace, specification));
 273   
 274  70 namespace.installPageSpecification(_simpleName, specification);
 275    }
 276   
 277    /**
 278    * If the namespace defines the template extension (as property
 279    * {@link Tapestry#TEMPLATE_EXTENSION_PROPERTY}, then that is used, otherwise the default is
 280    * used.
 281    */
 282   
 283  49 private String getTemplateExtension()
 284    {
 285  49 return _componentPropertySource.getNamespaceProperty(
 286    getNamespace(),
 287    Tapestry.TEMPLATE_EXTENSION_PROPERTY);
 288    }
 289   
 290    /** @since 4.0 */
 291   
 292  110 public void setLog(Log log)
 293    {
 294  110 _log = log;
 295    }
 296   
 297    /** @since 4.0 */
 298  104 public void setComponentPropertySource(ComponentPropertySource componentPropertySource)
 299    {
 300  104 _componentPropertySource = componentPropertySource;
 301    }
 302    }