Clover coverage report - Code Coverage for hivemind-lib release 1.0-rc-2
Coverage timestamp: Sat Sep 11 2004 09:10:14 EDT
file stats: LOC: 182   Methods: 4
NCLOC: 124   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ServicePropertyFactory.java 87.5% 97.6% 100% 96.3%
coverage coverage
 1   
 //  Copyright 2004 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.hivemind.lib.impl;
 16   
 
 17   
 import java.lang.reflect.Method;
 18   
 import java.lang.reflect.Modifier;
 19   
 import java.util.List;
 20   
 
 21   
 import org.apache.commons.logging.Log;
 22   
 import org.apache.hivemind.ApplicationRuntimeException;
 23   
 import org.apache.hivemind.ServiceImplementationFactory;
 24   
 import org.apache.hivemind.internal.Module;
 25   
 import org.apache.hivemind.service.BodyBuilder;
 26   
 import org.apache.hivemind.service.ClassFab;
 27   
 import org.apache.hivemind.service.ClassFabUtils;
 28   
 import org.apache.hivemind.service.ClassFactory;
 29   
 import org.apache.hivemind.service.MethodSignature;
 30   
 import org.apache.hivemind.util.ConstructorUtils;
 31   
 import org.apache.hivemind.util.PropertyAdaptor;
 32   
 import org.apache.hivemind.util.PropertyUtils;
 33   
 
 34   
 /**
 35   
  * Factory that dynamically exposes a property of another service. A proxy
 36   
  * is constructed that accesses the target service and obtains a property from that.
 37   
  * The service interface of the constructed service must match the
 38   
  * type of the exposed property.
 39   
  *
 40   
  * @author Howard Lewis Ship
 41   
  */
 42   
 public class ServicePropertyFactory implements ServiceImplementationFactory
 43   
 {
 44   
     private ClassFactory _classFactory;
 45   
 
 46  6
     public Object createCoreServiceImplementation(
 47   
         String serviceId,
 48   
         Class serviceInterface,
 49   
         Log serviceLog,
 50   
         Module invokingModule,
 51   
         List parameters)
 52   
     {
 53  6
         ServicePropertyFactoryParameter p = (ServicePropertyFactoryParameter) parameters.get(0);
 54   
 
 55  6
         Object targetService = p.getService();
 56  6
         String propertyName = p.getPropertyName();
 57   
 
 58  6
         PropertyAdaptor pa = PropertyUtils.getPropertyAdaptor(targetService, propertyName);
 59   
 
 60  6
         String readMethodName = pa.getReadMethodName();
 61   
 
 62  6
         if (readMethodName == null)
 63  1
             throw new ApplicationRuntimeException(
 64   
                 ImplMessages.servicePropertyNotReadable(propertyName, targetService),
 65   
                 null,
 66   
                 p.getLocation(),
 67   
                 null);
 68   
 
 69  5
         if (!(serviceInterface.isAssignableFrom(pa.getPropertyType())))
 70  1
             throw new ApplicationRuntimeException(
 71   
                 ImplMessages.servicePropertyWrongType(
 72   
                     propertyName,
 73   
                     targetService,
 74   
                     pa.getPropertyType(),
 75   
                     serviceInterface),
 76   
                 p.getLocation(),
 77   
                 null);
 78   
 
 79   
         // Now we're good to go.
 80   
 
 81  4
         String name = ClassFabUtils.generateClassName("ServicePropertyProxy");
 82   
 
 83  4
         ClassFab cf =
 84   
             _classFactory.newClass(
 85   
                 name,
 86   
                 Object.class,
 87   
                 invokingModule.getClassResolver().getClassLoader());
 88   
 
 89  4
         addInfrastructure(cf, targetService, serviceInterface, propertyName, readMethodName);
 90   
 
 91  4
         addMethods(cf, serviceId, serviceInterface, propertyName, targetService);
 92   
 
 93  4
         Class proxyClass = cf.createClass();
 94   
 
 95  4
         try
 96   
         {
 97  4
             return ConstructorUtils.invokeConstructor(proxyClass, new Object[] { targetService });
 98   
         }
 99   
         catch (Throwable ex)
 100   
         {
 101  0
             throw new ApplicationRuntimeException(ex.getMessage(), p.getLocation(), ex);
 102   
         }
 103   
     }
 104   
 
 105  4
     private void addInfrastructure(
 106   
         ClassFab cf,
 107   
         Object targetService,
 108   
         Class serviceInterface,
 109   
         String propertyName,
 110   
         String readPropertyMethodName)
 111   
     {
 112  4
         cf.addInterface(serviceInterface);
 113   
 
 114  4
         Class targetServiceClass = targetService.getClass();
 115   
 
 116  4
         cf.addField("_targetService", targetServiceClass);
 117   
 
 118  4
         cf.addConstructor(
 119   
             new Class[] { targetServiceClass },
 120   
             null,
 121   
             "{ super(); _targetService = $1; }");
 122   
 
 123  4
         BodyBuilder b = new BodyBuilder();
 124   
 
 125  4
         b.begin();
 126  4
         b.addln(
 127   
             "{0} property = _targetService.{1}();",
 128   
             serviceInterface.getName(),
 129   
             readPropertyMethodName);
 130   
 
 131  4
         b.addln("if (property == null)");
 132  4
         b.add("  throw new java.lang.NullPointerException(");
 133  4
         b.addQuoted(ImplMessages.servicePropertyWasNull(propertyName, targetService));
 134  4
         b.addln(");");
 135   
 
 136  4
         b.addln("return property;");
 137   
 
 138  4
         b.end();
 139   
 
 140  4
         MethodSignature sig =
 141   
             new MethodSignature(serviceInterface, "_targetServiceProperty", null, null);
 142  4
         cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString());
 143   
     }
 144   
 
 145  4
     private void addMethods(
 146   
         ClassFab cf,
 147   
         String serviceId,
 148   
         Class serviceInterface,
 149   
         String propertyName,
 150   
         Object targetService)
 151   
     {
 152  4
         boolean toString = false;
 153   
 
 154  4
         Method[] methods = serviceInterface.getMethods();
 155   
 
 156  4
         for (int i = 0; i < methods.length; i++)
 157   
         {
 158  8
             Method method = methods[i];
 159   
 
 160  8
             toString |= ClassFabUtils.isToString(method);
 161   
 
 162  8
             String body = "return ($r) _targetServiceProperty()." + method.getName() + "($$);";
 163   
 
 164  8
             cf.addMethod(Modifier.PUBLIC, new MethodSignature(method), body);
 165   
         }
 166   
 
 167  4
         if (!toString)
 168  4
             ClassFabUtils.addToStringMethod(
 169   
                 cf,
 170   
                 ImplMessages.servicePropertyToString(
 171   
                     serviceId,
 172   
                     serviceInterface,
 173   
                     propertyName,
 174   
                     targetService));
 175   
     }
 176   
 
 177  6
     public void setClassFactory(ClassFactory factory)
 178   
     {
 179  6
         _classFactory = factory;
 180   
     }
 181   
 }
 182