Clover coverage report - Code Coverage for hivemind-lib release 1.0-rc-1
Coverage timestamp: Wed Aug 25 2004 13:06:39 EDT
file stats: LOC: 178   Methods: 4
NCLOC: 120   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  5
     public Object createCoreServiceImplementation(
 47   
         String serviceId,
 48   
         Class serviceInterface,
 49   
         Log serviceLog,
 50   
         Module invokingModule,
 51   
         List parameters)
 52   
     {
 53  5
         ServicePropertyFactoryParameter p = (ServicePropertyFactoryParameter) parameters.get(0);
 54   
 
 55  5
         Object targetService = p.getService();
 56  5
         String propertyName = p.getPropertyName();
 57   
 
 58  5
         PropertyAdaptor pa = PropertyUtils.getPropertyAdaptor(targetService, propertyName);
 59   
 
 60  5
         String readMethodName = pa.getReadMethodName();
 61   
 
 62  5
         if (readMethodName == null)
 63  1
             throw new ApplicationRuntimeException(
 64   
                 ImplMessages.servicePropertyNotReadable(propertyName, targetService),
 65   
                 null,
 66   
                 p.getLocation(),
 67   
                 null);
 68   
 
 69  4
         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  3
         String name = ClassFabUtils.generateClassName("ServicePropertyProxy");
 82   
 
 83  3
         ClassFab cf = _classFactory.newClass(name, Object.class, invokingModule);
 84   
 
 85  3
         addInfrastructure(cf, targetService, serviceInterface, propertyName, readMethodName);
 86   
 
 87  3
         addMethods(cf, serviceId, serviceInterface, propertyName, targetService);
 88   
 
 89  3
         Class proxyClass = cf.createClass();
 90   
 
 91  3
         try
 92   
         {
 93  3
             return ConstructorUtils.invokeConstructor(proxyClass, new Object[] { targetService });
 94   
         }
 95   
         catch (ApplicationRuntimeException ex)
 96   
         {
 97  0
             throw new ApplicationRuntimeException(ex.getMessage(), p.getLocation(), ex);
 98   
         }
 99   
     }
 100   
 
 101  3
     private void addInfrastructure(
 102   
         ClassFab cf,
 103   
         Object targetService,
 104   
         Class serviceInterface,
 105   
         String propertyName,
 106   
         String readPropertyMethodName)
 107   
     {
 108  3
         cf.addInterface(serviceInterface);
 109   
 
 110  3
         Class targetServiceClass = targetService.getClass();
 111   
 
 112  3
         cf.addField("_targetService", targetServiceClass);
 113   
 
 114  3
         cf.addConstructor(
 115   
             new Class[] { targetServiceClass },
 116   
             null,
 117   
             "{ super(); _targetService = $1; }");
 118   
 
 119  3
         BodyBuilder b = new BodyBuilder();
 120   
 
 121  3
         b.begin();
 122  3
         b.addln(
 123   
             "{0} property = _targetService.{1}();",
 124   
             serviceInterface.getName(),
 125   
             readPropertyMethodName);
 126   
 
 127  3
         b.addln("if (property == null)");
 128  3
         b.add("  throw new java.lang.NullPointerException(");
 129  3
         b.addQuoted(ImplMessages.servicePropertyWasNull(propertyName, targetService));
 130  3
         b.addln(");");
 131   
 
 132  3
         b.addln("return property;");
 133   
 
 134  3
         b.end();
 135   
 
 136  3
         MethodSignature sig =
 137   
             new MethodSignature(serviceInterface, "_targetServiceProperty", null, null);
 138  3
         cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString());
 139   
     }
 140   
 
 141  3
     private void addMethods(
 142   
         ClassFab cf,
 143   
         String serviceId,
 144   
         Class serviceInterface,
 145   
         String propertyName,
 146   
         Object targetService)
 147   
     {
 148  3
         boolean toString = false;
 149   
 
 150  3
         Method[] methods = serviceInterface.getMethods();
 151   
 
 152  3
         for (int i = 0; i < methods.length; i++)
 153   
         {
 154  6
             Method method = methods[i];
 155   
 
 156  6
             toString |= ClassFabUtils.isToString(method);
 157   
 
 158  6
             String body = "return ($r) _targetServiceProperty()." + method.getName() + "($$);";
 159   
 
 160  6
             cf.addMethod(Modifier.PUBLIC, new MethodSignature(method), body);
 161   
         }
 162   
 
 163  3
         if (!toString)
 164  3
             ClassFabUtils.addToStringMethod(
 165   
                 cf,
 166   
                 ImplMessages.servicePropertyToString(
 167   
                     serviceId,
 168   
                     serviceInterface,
 169   
                     propertyName,
 170   
                     targetService));
 171   
     }
 172   
 
 173  5
     public void setClassFactory(ClassFactory factory)
 174   
     {
 175  5
         _classFactory = factory;
 176   
     }
 177   
 }
 178