Coverage Report - net.sf.tacos.resolvers.ClasspathComponentSpecResolver
 
Classes in this File Line Coverage Branch Coverage Complexity
ClasspathComponentSpecResolver
0% 
0% 
3,091
 
 1  
 /*
 2  
  *  Copyright 2007 Tacos.
 3  
  * 
 4  
  *  Licensed under the Apache License, Version 2.0 (the "License");
 5  
  *  you may not use this file except in compliance with the License.
 6  
  *  You may obtain a copy of the License at
 7  
  * 
 8  
  *       http://www.apache.org/licenses/LICENSE-2.0
 9  
  * 
 10  
  *  Unless required by applicable law or agreed to in writing, software
 11  
  *  distributed under the License is distributed on an "AS IS" BASIS,
 12  
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  *  See the License for the specific language governing permissions and
 14  
  *  limitations under the License.
 15  
  *  under the License.
 16  
  */
 17  
 package net.sf.tacos.resolvers;
 18  
 
 19  
 import org.apache.commons.logging.Log;
 20  
 import org.apache.hivemind.ApplicationRuntimeException;
 21  
 import org.apache.hivemind.Location;
 22  
 import org.apache.hivemind.Resource;
 23  
 import org.apache.hivemind.impl.DefaultClassResolver;
 24  
 import org.apache.hivemind.impl.LocationImpl;
 25  
 import org.apache.hivemind.util.ClasspathResource;
 26  
 import org.apache.hivemind.util.Defense;
 27  
 import org.apache.tapestry.INamespace;
 28  
 import org.apache.tapestry.IRequestCycle;
 29  
 import org.apache.tapestry.resolver.AbstractSpecificationResolver;
 30  
 import org.apache.tapestry.resolver.ComponentSpecificationResolver;
 31  
 import org.apache.tapestry.services.ClassFinder;
 32  
 import org.apache.tapestry.spec.ComponentSpecification;
 33  
 import org.apache.tapestry.spec.IComponentSpecification;
 34  
 
 35  
 /**
 36  
  * An AbstractSpecificationResolver similar to tapestry's. Contains additional 
 37  
  * logic that can loads tapestry templates from the classpath.
 38  
  * 
 39  
  * @author Howard Lewis Ship
 40  
  * @author Andreas Andreou, amplafi.com
 41  
  */
 42  
 
 43  0
 public class ClasspathComponentSpecResolver extends
 44  
         AbstractSpecificationResolver implements ComponentSpecificationResolver {
 45  
 
 46  
     /** Set by container. */
 47  
     private Log log;
 48  
 
 49  
     /** Set by resolve(). */
 50  
     private String type;
 51  
 
 52  
     private ClassFinder classFinder;
 53  
 
 54  
     protected void reset() {
 55  0
         type = null;
 56  0
         super.reset();
 57  0
     }
 58  
 
 59  
     /**
 60  
      * Passed the namespace of a container (to resolve the type in) and the type
 61  
      * to resolve, performs the processing. A "bare type" (without a library
 62  
      * prefix) may be in the containerNamespace, or the framework namespace (a
 63  
      * search occurs in that order).
 64  
      * 
 65  
      * @param cycle
 66  
      *            current request cycle
 67  
      * @param containerNamespace
 68  
      *            namespace that may contain a library referenced in the type
 69  
      * @param componentType
 70  
      *            the component specification to find, either a simple name, or
 71  
      *            prefixed with a library id (defined for the container
 72  
      *            namespace)
 73  
      * @see #getNamespace()
 74  
      * @see #getSpecification()
 75  
      */
 76  
 
 77  
     public void resolve(IRequestCycle cycle, INamespace containerNamespace,
 78  
             String componentType, Location location) {
 79  0
         Defense.notNull(componentType, "type");
 80  
 
 81  0
         int colonx = componentType.indexOf(':');
 82  
 
 83  0
         if (colonx > 0) {
 84  0
             String libraryId = componentType.substring(0, colonx);
 85  0
             String simpleType = componentType.substring(colonx + 1);
 86  
 
 87  0
             resolve(cycle, containerNamespace, libraryId, simpleType, location);
 88  0
         } else {
 89  0
             resolve(cycle, containerNamespace, null, componentType, location);
 90  
         }
 91  0
     }
 92  
 
 93  
     /**
 94  
      * Like #resolve(org.apache.tapestry.IRequestCycle,
 95  
      * org.apache.tapestry.INamespace, java.lang.String,
 96  
      * org.apache.tapestry.ILocation), but used when the type has already been
 97  
      * parsed into a library id and a simple type.
 98  
      * 
 99  
      * @param cycle
 100  
      *            current request cycle
 101  
      * @param containerNamespace
 102  
      *            namespace that may contain a library referenced in the type
 103  
      * @param libraryId
 104  
      *            the library id within the container namespace, or null
 105  
      * @param componentType
 106  
      *            the component specification to find as a simple name (without
 107  
      *            a library prefix)
 108  
      * @param location
 109  
      *            of reference to be resolved
 110  
      * @throws ApplicationRuntimeException
 111  
      *             if the type cannot be resolved
 112  
      */
 113  
 
 114  
     public void resolve(IRequestCycle cycle, INamespace containerNamespace,
 115  
             String libraryId, String componentType, Location location) {
 116  0
         reset();
 117  0
         this.type = componentType;
 118  
 
 119  0
         INamespace namespace = findNamespaceForId(containerNamespace, libraryId);
 120  
 
 121  0
         setNamespace(namespace);
 122  
 
 123  0
         if (namespace.containsComponentType(type)) {
 124  0
             setSpecification(namespace.getComponentSpecification(type));
 125  0
             return;
 126  
         }
 127  
 
 128  0
         IComponentSpecification spec = searchForComponent(cycle);
 129  
 
 130  
         // If not found after search, check to see if it's in
 131  
         // the framework instead.
 132  0
         if (spec == null) {
 133  0
             spec = doCustomSearch(cycle);
 134  
         }
 135  
 
 136  0
         if (spec == null) {
 137  0
             throw new ApplicationRuntimeException("no Such Component Type:" + this.type,
 138  
                     location, null);
 139  
         }
 140  
 
 141  0
         setSpecification(spec);
 142  
 
 143  
         // Install it into the namespace, to short-circuit any future search.
 144  0
         install();
 145  0
     }
 146  
 
 147  
     /**
 148  
      * Override to add custom behavior to component resolution - will be the last
 149  
      * resolve logic to be executed.
 150  
      * @param cycle
 151  
      * @return
 152  
      */
 153  
     protected IComponentSpecification doCustomSearch(IRequestCycle cycle) {
 154  0
         return null;
 155  
     }
 156  
 
 157  
     private IComponentSpecification searchForComponent(IRequestCycle cycle) {
 158  0
         INamespace namespace = getNamespace();
 159  
 
 160  
         // if (_log.isDebugEnabled())
 161  
         // _log.debug(ImplMessages.resolvingComponent(_type, namespace));
 162  
 
 163  0
         String expectedName = type + ".jwc";
 164  0
         Resource namespaceLocation = namespace.getSpecificationLocation();
 165  
 
 166  
         // Look for appropriate file in same folder as the library (or
 167  
         // application) specification.
 168  
 
 169  0
         IComponentSpecification result = check(namespaceLocation.getRelativeResource(expectedName));
 170  
 
 171  0
         if (result != null) {
 172  0
             return result;
 173  
         }
 174  0
         if (namespace.isApplicationNamespace()) {
 175  
 
 176  
             // The application namespace gets some extra searching.
 177  
 
 178  0
             result = check(getWebInfAppLocation().getRelativeResource(
 179  
                     expectedName));
 180  
 
 181  0
             if (result == null) {
 182  0
                 result = check(getWebInfLocation().getRelativeResource(
 183  
                         expectedName));
 184  
             }
 185  0
             if (result == null) {
 186  0
                 result = check(getContextRoot()
 187  
                         .getRelativeResource(expectedName));
 188  
             }
 189  0
             if (result != null) {
 190  0
                 return result;
 191  
             }
 192  
         }
 193  
 
 194  0
         result = searchForComponentClass(namespace, type);
 195  
 
 196  0
         if (result != null) {
 197  0
             return result;
 198  
         }
 199  
 
 200  
         // Not in the library or app spec; does it match a component
 201  
         // provided by the Framework?
 202  
 
 203  0
         INamespace framework = getSpecificationSource().getFrameworkNamespace();
 204  
 
 205  0
         if (framework.containsComponentType(type)) {
 206  0
             return framework.getComponentSpecification(type);
 207  
         }
 208  0
         return getDelegate()
 209  
                 .findComponentSpecification(cycle, namespace, type);
 210  
     }
 211  
 
 212  
     IComponentSpecification searchForComponentClass(INamespace namespace,
 213  
             String componentType) {
 214  0
         String packages = namespace
 215  
                 .getPropertyValue("org.apache.tapestry.component-class-packages");
 216  
 
 217  0
         String className = componentType.replace('/', '.');
 218  
 
 219  0
         Class componentClass = classFinder.findClass(packages, className);
 220  
 
 221  0
         if (componentClass == null) {
 222  0
             return null;
 223  
         }
 224  0
         Resource componentResource = null;
 225  0
         Resource namespaceResource = namespace.getSpecificationLocation();
 226  
 
 227  0
         String fullPath = componentClass.getName().replace('.', '/');
 228  0
         ClasspathResource html = new ClasspathResource(
 229  
                 new DefaultClassResolver(), fullPath + ".html");
 230  
 
 231  
         // first check near the class, if the html is there then that's where
 232  
         // the (fictional) jwc should be - need exploded wars for this
 233  
 
 234  0
         if (html.getResourceURL() != null && namespace.isApplicationNamespace()) {
 235  0
             componentResource = new ClasspathResource(
 236  
                     new DefaultClassResolver(), fullPath + ".jwc");
 237  
         } else {
 238  0
             componentResource = namespaceResource.getRelativeResource(componentType
 239  
                     + ".jwc");
 240  
         }
 241  
 
 242  0
         Location location = new LocationImpl(componentResource);
 243  
 
 244  0
         IComponentSpecification spec = new ComponentSpecification();
 245  0
         spec.setLocation(location);
 246  0
         spec.setSpecificationLocation(componentResource);
 247  0
         spec.setComponentClassName(componentClass.getName());
 248  
 
 249  0
         return spec;
 250  
     }
 251  
 
 252  
     private IComponentSpecification check(Resource resource) {
 253  0
         if (log.isDebugEnabled()) {
 254  0
             log.debug("Checking: " + resource);
 255  
         }
 256  0
         if (resource.getResourceURL() == null) {
 257  0
             return null;
 258  
         }
 259  0
         return getSpecificationSource().getComponentSpecification(resource);
 260  
     }
 261  
 
 262  
     private void install() {
 263  0
         INamespace namespace = getNamespace();
 264  0
         IComponentSpecification specification = getSpecification();
 265  
 
 266  
         // if (_log.isDebugEnabled())
 267  
         // _log.debug(ImplMessages.installingComponent(_type, namespace,
 268  
         // specification));
 269  
 
 270  0
         namespace.installComponentSpecification(type, specification);
 271  0
     }
 272  
 
 273  
     public String getType() {
 274  0
         return type;
 275  
     }
 276  
 
 277  
     public void setLog(Log log) {
 278  0
         this.log = log;
 279  0
     }
 280  
 
 281  
     public void setClassFinder(ClassFinder classFinder) {
 282  0
         this.classFinder = classFinder;
 283  0
     }
 284  
 
 285  
 }