Coverage Report - org.apache.tapestry.resolver.ComponentSpecificationResolverImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ComponentSpecificationResolverImpl
0%
0/91
0%
0/36
3.636
 
 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.ClassResolver;
 20  
 import org.apache.hivemind.Location;
 21  
 import org.apache.hivemind.Resource;
 22  
 import org.apache.hivemind.impl.LocationImpl;
 23  
 import org.apache.hivemind.util.ClasspathResource;
 24  
 import org.apache.tapestry.INamespace;
 25  
 import org.apache.tapestry.IRequestCycle;
 26  
 import org.apache.tapestry.services.ClassFinder;
 27  
 import org.apache.tapestry.spec.ComponentSpecification;
 28  
 import org.apache.tapestry.spec.IComponentSpecification;
 29  
 
 30  
 /**
 31  
  * Utility class that understands the rules of component types (which may optionally have a library
 32  
  * prefix) and can resolve the type to a {@link org.apache.tapestry.INamespace}and a
 33  
  * {@link org.apache.tapestry.spec.IComponentSpecification}.
 34  
  * <p>
 35  
  * Like {@link org.apache.tapestry.resolver.PageSpecificationResolver}, if the component is not
 36  
  * defined explicitly in the namespace, a search may occur: Performs the tricky work of resolving a
 37  
  * page name to a page specification. The search for pages in the application namespace is the most
 38  
  * complicated, since Tapestry searches for pages that aren't explicitly defined in the application
 39  
  * specification. The search, based on the <i>simple-name </i> of the page, goes as follows:
 40  
  * <ul>
 41  
  * <li>As declared in the application specification
 42  
  * <li><i>type</i>.jwc in the same folder as the application specification
 43  
  * <li><i>type</i> jwc in the WEB-INF/ <i>servlet-name </i> directory of the context root
 44  
  * <li><i>type</i>.jwc in WEB-INF
 45  
  * <li><i>type</i>.jwc in the application root (within the context root)
 46  
  * <li>By searching the framework namespace
 47  
  * <li>By searching for a named class file within the org.apache.tapestry.component-class-packages
 48  
  * property (defined within the namespace)
 49  
  * </ul>
 50  
  *
 51  
  * The search for components in library namespaces is more abbreviated:
 52  
  * <ul>
 53  
  * <li>As declared in the library specification
 54  
  * <li><i>type </i>.jwc in the same folder as the library specification
 55  
  * <li>By searching the framework namespace
 56  
  * </ul>
 57  
  *
 58  
  * @since 3.0
 59  
  */
 60  
 
 61  0
 public class ComponentSpecificationResolverImpl extends AbstractSpecificationResolver implements ComponentSpecificationResolver
 62  
 {
 63  
     /** Set by container. */
 64  
     private Log _log;
 65  
 
 66  
     /** Set by resolve(). */
 67  
     private String _type;
 68  
 
 69  
     private ClassFinder _classFinder;
 70  
 
 71  
     private ClassResolver _classResolver;
 72  
 
 73  
     protected void reset()
 74  
     {
 75  0
         _type = null;
 76  
 
 77  0
         super.reset();
 78  0
     }
 79  
 
 80  
     /**
 81  
      * Passed the namespace of a container (to resolve the type in) and the type to resolve,
 82  
      * performs the processing. A "bare type" (without a library prefix) may be in the
 83  
      * containerNamespace, or the framework namespace (a search occurs in that order).
 84  
      *
 85  
      * @param cycle
 86  
      *            current request cycle
 87  
      * @param containerNamespace
 88  
      *            namespace that may contain a library referenced in the type
 89  
      * @param type
 90  
      *            the component specification to find, either a simple name, or prefixed with a
 91  
      *            library id (defined for the container namespace)
 92  
      * @see #getNamespace()
 93  
      * @see #getSpecification()
 94  
      */
 95  
 
 96  
     public void resolve(IRequestCycle cycle, INamespace containerNamespace, String type, Location location)
 97  
     {
 98  0
         int colonx = type.indexOf(':');
 99  
 
 100  0
         if (colonx > 0)
 101  
         {
 102  0
             String libraryId = type.substring(0, colonx);
 103  0
             String simpleType = type.substring(colonx + 1);
 104  
 
 105  0
             resolve(cycle, containerNamespace, libraryId, simpleType, location);
 106  0
         }
 107  
         else
 108  0
             resolve(cycle, containerNamespace, null, type, location);
 109  
 
 110  0
         IComponentSpecification spec = getSpecification();
 111  
 
 112  0
         if (spec.isDeprecated())
 113  0
             _log.warn(ResolverMessages.componentIsDeprecated(type, location));
 114  0
     }
 115  
 
 116  
     /**
 117  
      * Like
 118  
      * {@link #resolve(org.apache.tapestry.IRequestCycle, org.apache.tapestry.INamespace, java.lang.String, Location)},
 119  
      * but used when the type has already been parsed into a library id and a simple type.
 120  
      *
 121  
      * @param cycle
 122  
      *            current request cycle
 123  
      * @param containerNamespace
 124  
      *            namespace that may contain a library referenced in the type
 125  
      * @param libraryId
 126  
      *            the library id within the container namespace, or null
 127  
      * @param type
 128  
      *            the component specification to find as a simple name (without a library prefix)
 129  
      * @param location
 130  
      *            of reference to be resolved
 131  
      * @throws ApplicationRuntimeException
 132  
      *             if the type cannot be resolved
 133  
      */
 134  
 
 135  
     public void resolve(IRequestCycle cycle, INamespace containerNamespace, String libraryId,
 136  
                         String type, Location location)
 137  
     {
 138  0
         reset();
 139  0
         _type = type;
 140  
 
 141  
         INamespace namespace;
 142  
         try
 143  
         {
 144  0
             namespace = findNamespaceForId(containerNamespace, libraryId);
 145  
         }
 146  0
         catch (ApplicationRuntimeException e)
 147  
         {
 148  0
             throw new ApplicationRuntimeException(e.getMessage(), location, e);
 149  0
         }
 150  
 
 151  0
         setNamespace(namespace);
 152  
 
 153  0
         if (namespace.containsComponentType(type))
 154  
         {
 155  0
             setSpecification(namespace.getComponentSpecification(type));
 156  0
             return;
 157  
         }
 158  
 
 159  0
         IComponentSpecification spec = searchForComponent(cycle);
 160  
 
 161  
         // If not found after search, check to see if it's in
 162  
         // the framework instead.
 163  
 
 164  0
         if (spec == null)
 165  
         {
 166  0
             throw new ApplicationRuntimeException(ResolverMessages.noSuchComponentType(
 167  
               type,
 168  
               namespace), location, null);
 169  
 
 170  
         }
 171  
 
 172  0
         setSpecification(spec);
 173  
 
 174  
         // Install it into the namespace, to short-circuit any future search.
 175  
 
 176  0
         install();
 177  0
     }
 178  
 
 179  
     // Hm. This could maybe go elsewhere, say onto ISpecificationSource
 180  
 
 181  
     private IComponentSpecification searchForComponent(IRequestCycle cycle)
 182  
     {
 183  0
         IComponentSpecification result = null;
 184  0
         INamespace namespace = getNamespace();
 185  
 
 186  0
         if (_log.isDebugEnabled())
 187  0
             _log.debug(ResolverMessages.resolvingComponent(_type, namespace));
 188  
 
 189  0
         String expectedName = _type + ".jwc";
 190  0
         Resource namespaceLocation = namespace.getSpecificationLocation();
 191  
 
 192  
         // Look for appropriate file in same folder as the library (or application)
 193  
         // specificaiton.
 194  
 
 195  0
         result = check(namespaceLocation.getRelativeResource(expectedName));
 196  
 
 197  0
         if (result != null)
 198  0
             return result;
 199  
 
 200  0
         if (namespace.isApplicationNamespace()) {
 201  
 
 202  
             // The application namespace gets some extra searching.
 203  
 
 204  0
             result = check(getWebInfAppLocation().getRelativeResource(expectedName));
 205  
 
 206  0
             if (result == null)
 207  0
                 result = check(getWebInfLocation().getRelativeResource(expectedName));
 208  
 
 209  0
             if (result == null)
 210  0
                 result = check((getContextRoot().getRelativeResource(expectedName)));
 211  
 
 212  0
             if (result != null)
 213  0
                 return result;
 214  
         }
 215  
 
 216  0
         result = getDelegate().findComponentSpecification(cycle, namespace, _type);
 217  0
         if (result != null)
 218  0
             return result;
 219  
 
 220  0
         result = searchForComponentClass(namespace, _type);
 221  
 
 222  0
         if (result != null)
 223  0
             return result;
 224  
 
 225  
         // Not in the library or app spec; does it match a component
 226  
         // provided by the Framework?
 227  
 
 228  0
         INamespace framework = getSpecificationSource().getFrameworkNamespace();
 229  
 
 230  0
         if (framework.containsComponentType(_type))
 231  0
             return framework.getComponentSpecification(_type);
 232  
 
 233  0
         return null;
 234  
     }
 235  
 
 236  
     IComponentSpecification searchForComponentClass(INamespace namespace, String type)
 237  
     {
 238  0
         String packages = namespace.getPropertyValue("org.apache.tapestry.component-class-packages");
 239  
 
 240  0
         String className = type.replace('/', '.');
 241  
 
 242  0
         Class componentClass = _classFinder.findClass(packages, className);
 243  0
         if (componentClass == null)
 244  0
             return null;
 245  
 
 246  0
         IComponentSpecification spec = new ComponentSpecification();
 247  
 
 248  0
         Resource namespaceResource = namespace.getSpecificationLocation();
 249  0
         Resource componentResource = namespaceResource.getRelativeResource(type + ".jwc");
 250  
 
 251  
         // try classpath relative if namespace relative doesn't resolve
 252  
 
 253  0
         if (componentResource.getResourceURL() == null) {
 254  
 
 255  0
             componentResource = new ClasspathResource(_classResolver, componentClass.getName().replace('.', '/'));
 256  
         }
 257  
 
 258  0
         Location location = new LocationImpl(componentResource);
 259  
 
 260  0
         spec.setLocation(location);
 261  0
         spec.setSpecificationLocation(componentResource);
 262  0
         spec.setComponentClassName(componentClass.getName());
 263  
 
 264  0
         return spec;
 265  
     }
 266  
 
 267  
     private IComponentSpecification check(Resource resource)
 268  
     {
 269  0
         if (_log.isDebugEnabled())
 270  0
             _log.debug("Checking: " + resource);
 271  
 
 272  0
         if (resource.getResourceURL() == null)
 273  0
             return null;
 274  
 
 275  0
         return getSpecificationSource().getComponentSpecification(resource);
 276  
     }
 277  
 
 278  
     private void install()
 279  
     {
 280  0
         INamespace namespace = getNamespace();
 281  0
         IComponentSpecification specification = getSpecification();
 282  
 
 283  0
         if (_log.isDebugEnabled())
 284  0
             _log.debug(ResolverMessages.installingComponent(_type, namespace, specification));
 285  
 
 286  0
         namespace.installComponentSpecification(_type, specification);
 287  0
     }
 288  
 
 289  
     public String getType()
 290  
     {
 291  0
         return _type;
 292  
     }
 293  
 
 294  
     public void setLog(Log log)
 295  
     {
 296  0
         _log = log;
 297  0
     }
 298  
 
 299  
     public void setClassFinder(ClassFinder classFinder)
 300  
     {
 301  0
         _classFinder = classFinder;
 302  0
     }
 303  
 
 304  
     public void setClassResolver(ClassResolver classResolver)
 305  
     {
 306  0
         _classResolver = classResolver;
 307  0
     }
 308  
 }