2009/04/15 - Apache HiveMind has been retired.

For more information, please explore the Attic.

Clover coverage report - Code Coverage for hivemind-lib release 1.2.1
Coverage timestamp: Fri Feb 10 2006 16:34:07 PST
file stats: LOC: 157   Methods: 4
NCLOC: 102   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ServicePropertyFactory.java 87.5% 97.6% 100% 96.2%
coverage 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.hivemind.lib.impl;
 16   
 17    import java.lang.reflect.Modifier;
 18   
 19    import org.apache.hivemind.ApplicationRuntimeException;
 20    import org.apache.hivemind.ServiceImplementationFactory;
 21    import org.apache.hivemind.ServiceImplementationFactoryParameters;
 22    import org.apache.hivemind.service.BodyBuilder;
 23    import org.apache.hivemind.service.ClassFab;
 24    import org.apache.hivemind.service.ClassFabUtils;
 25    import org.apache.hivemind.service.ClassFactory;
 26    import org.apache.hivemind.service.MethodIterator;
 27    import org.apache.hivemind.service.MethodSignature;
 28    import org.apache.hivemind.util.ConstructorUtils;
 29    import org.apache.hivemind.util.PropertyAdaptor;
 30    import org.apache.hivemind.util.PropertyUtils;
 31   
 32    /**
 33    * Factory that dynamically exposes a property of another service. A proxy is constructed that
 34    * accesses the target service and obtains a property from that. The service interface of the
 35    * constructed service must match the type of the exposed property.
 36    *
 37    * @author Howard Lewis Ship
 38    */
 39    public class ServicePropertyFactory implements ServiceImplementationFactory
 40    {
 41    private ClassFactory _classFactory;
 42   
 43  8 public Object createCoreServiceImplementation(
 44    ServiceImplementationFactoryParameters factoryParameters)
 45    {
 46  8 ServicePropertyFactoryParameter p = (ServicePropertyFactoryParameter) factoryParameters
 47    .getParameters().get(0);
 48   
 49  8 Object targetService = p.getService();
 50  8 String propertyName = p.getPropertyName();
 51   
 52  8 PropertyAdaptor pa = PropertyUtils.getPropertyAdaptor(targetService, propertyName);
 53   
 54  8 String readMethodName = pa.getReadMethodName();
 55   
 56  8 if (readMethodName == null)
 57  1 throw new ApplicationRuntimeException(ImplMessages.servicePropertyNotReadable(
 58    propertyName,
 59    targetService), null, p.getLocation(), null);
 60  7 Class serviceInterface = factoryParameters.getServiceInterface();
 61   
 62  7 if (!(serviceInterface.isAssignableFrom(pa.getPropertyType())))
 63  1 throw new ApplicationRuntimeException(ImplMessages.servicePropertyWrongType(
 64    propertyName,
 65    targetService,
 66    pa.getPropertyType(),
 67    serviceInterface), p.getLocation(), null);
 68   
 69    // Now we're good to go.
 70   
 71  6 String name = ClassFabUtils.generateClassName(serviceInterface);
 72   
 73  6 ClassFab cf = _classFactory.newClass(name, Object.class);
 74   
 75  6 addInfrastructure(cf, targetService, serviceInterface, propertyName, readMethodName);
 76   
 77  6 addMethods(
 78    cf,
 79    factoryParameters.getServiceId(),
 80    serviceInterface,
 81    propertyName,
 82    targetService);
 83   
 84  6 Class proxyClass = cf.createClass();
 85   
 86  6 try
 87    {
 88  6 return ConstructorUtils.invokeConstructor(proxyClass, new Object[]
 89    { targetService });
 90    }
 91    catch (Throwable ex)
 92    {
 93  0 throw new ApplicationRuntimeException(ex.getMessage(), p.getLocation(), ex);
 94    }
 95    }
 96   
 97  6 private void addInfrastructure(ClassFab cf, Object targetService, Class serviceInterface,
 98    String propertyName, String readPropertyMethodName)
 99    {
 100  6 cf.addInterface(serviceInterface);
 101   
 102  6 Class targetServiceClass = ClassFabUtils.getInstanceClass(targetService, serviceInterface);
 103   
 104  6 cf.addField("_targetService", targetServiceClass);
 105   
 106  6 cf.addConstructor(new Class[]
 107    { targetServiceClass }, null, "{ super(); _targetService = $1; }");
 108   
 109  6 BodyBuilder b = new BodyBuilder();
 110   
 111  6 b.begin();
 112  6 b.addln(
 113    "{0} property = _targetService.{1}();",
 114    serviceInterface.getName(),
 115    readPropertyMethodName);
 116   
 117  6 b.addln("if (property == null)");
 118  6 b.add(" throw new java.lang.NullPointerException(");
 119  6 b.addQuoted(ImplMessages.servicePropertyWasNull(propertyName, targetService));
 120  6 b.addln(");");
 121   
 122  6 b.addln("return property;");
 123   
 124  6 b.end();
 125   
 126  6 MethodSignature sig = new MethodSignature(serviceInterface, "_targetServiceProperty", null,
 127    null);
 128  6 cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString());
 129    }
 130   
 131  6 private void addMethods(ClassFab cf, String serviceId, Class serviceInterface,
 132    String propertyName, Object targetService)
 133    {
 134  6 MethodIterator mi = new MethodIterator(serviceInterface);
 135   
 136  6 while (mi.hasNext())
 137    {
 138  18 MethodSignature sig = mi.next();
 139   
 140  18 String body = "return ($r) _targetServiceProperty()." + sig.getName() + "($$);";
 141   
 142  18 cf.addMethod(Modifier.PUBLIC, sig, body);
 143    }
 144   
 145  6 if (!mi.getToString())
 146  6 ClassFabUtils.addToStringMethod(cf, ImplMessages.servicePropertyToString(
 147    serviceId,
 148    serviceInterface,
 149    propertyName,
 150    targetService));
 151    }
 152   
 153  8 public void setClassFactory(ClassFactory factory)
 154    {
 155  8 _classFactory = factory;
 156    }
 157    }