1 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.internal.ServicePoint; 23 import org.apache.hivemind.service.BodyBuilder; 24 import org.apache.hivemind.service.ClassFab; 25 import org.apache.hivemind.service.ClassFabUtils; 26 import org.apache.hivemind.service.ClassFactory; 27 import org.apache.hivemind.service.MethodIterator; 28 import org.apache.hivemind.service.MethodSignature; 29 import org.apache.hivemind.util.ConstructorUtils; 30 import org.apache.hivemind.util.PropertyAdaptor; 31 import org.apache.hivemind.util.PropertyUtils; 32 33 40 public class ServicePropertyFactory implements ServiceImplementationFactory 41 { 42 private ClassFactory _classFactory; 43 44 public Object createCoreServiceImplementation( 45 ServiceImplementationFactoryParameters factoryParameters) 46 { 47 ServicePropertyFactoryParameter p = (ServicePropertyFactoryParameter) factoryParameters 48 .getFirstParameter(); 49 50 ServicePoint targetServicePoint = p.getServicePoint(); 51 final Class targetServiceInterface = targetServicePoint.getServiceInterface(); 52 final Object targetService = targetServicePoint.getService( targetServiceInterface ); 53 String propertyName = p.getPropertyName(); 54 55 PropertyAdaptor pa = PropertyUtils.getPropertyAdaptor(targetService, propertyName); 56 57 String readMethodName = pa.getReadMethodName(); 58 59 if (readMethodName == null) 60 throw new ApplicationRuntimeException(ImplMessages.servicePropertyNotReadable( 61 propertyName, 62 targetService), null, p.getLocation(), null); 63 Class serviceInterface = factoryParameters.getServiceInterface(); 64 65 if (!(serviceInterface.isAssignableFrom(pa.getPropertyType()))) 66 throw new ApplicationRuntimeException(ImplMessages.servicePropertyWrongType( 67 propertyName, 68 targetService, 69 pa.getPropertyType(), 70 serviceInterface), p.getLocation(), null); 71 72 74 String name = ClassFabUtils.generateClassName(serviceInterface); 75 76 ClassFab cf = _classFactory.newClass(name, Object .class); 77 78 addInfrastructure(cf, targetService, serviceInterface, targetServiceInterface, propertyName, readMethodName); 79 80 addMethods( 81 cf, 82 factoryParameters.getServiceId(), 83 serviceInterface, 84 propertyName, 85 targetService); 86 87 Class proxyClass = cf.createClass(); 88 89 try 90 { 91 return ConstructorUtils.invokeConstructor(proxyClass, new Object [] 92 { targetService }); 93 } 94 catch (Throwable ex) 95 { 96 throw new ApplicationRuntimeException(ex.getMessage(), p.getLocation(), ex); 97 } 98 } 99 100 private void addInfrastructure(ClassFab cf, Object targetService, Class serviceInterface, Class targetServiceInterface, 101 String propertyName, String readPropertyMethodName) 102 { 103 cf.addInterface(serviceInterface); 104 105 Class targetServiceClass = ClassFabUtils.getInstanceClass(cf, targetService, targetServiceInterface); 106 107 cf.addField("_targetService", targetServiceClass); 108 109 cf.addConstructor(new Class [] 110 { targetServiceClass }, null, "{ super(); _targetService = $1; }"); 111 112 BodyBuilder b = new BodyBuilder(); 113 114 b.begin(); 115 b.addln( 116 "{0} property = _targetService.{1}();", 117 serviceInterface.getName(), 118 readPropertyMethodName); 119 120 b.addln("if (property == null)"); 121 b.add(" throw new java.lang.NullPointerException("); 122 b.addQuoted(ImplMessages.servicePropertyWasNull(propertyName, targetService)); 123 b.addln(");"); 124 125 b.addln("return property;"); 126 127 b.end(); 128 129 MethodSignature sig = new MethodSignature(serviceInterface, "_targetServiceProperty", null, 130 null); 131 cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString()); 132 } 133 134 private void addMethods(ClassFab cf, String serviceId, Class serviceInterface, 135 String propertyName, Object targetService) 136 { 137 MethodIterator mi = new MethodIterator(serviceInterface); 138 139 while (mi.hasNext()) 140 { 141 MethodSignature sig = mi.next(); 142 143 String body = "return ($r) _targetServiceProperty()." + sig.getName() + "($$);"; 144 145 cf.addMethod(Modifier.PUBLIC, sig, body); 146 } 147 148 if (!mi.getToString()) 149 ClassFabUtils.addToStringMethod(cf, ImplMessages.servicePropertyToString( 150 serviceId, 151 serviceInterface, 152 propertyName, 153 targetService)); 154 } 155 156 public void setClassFactory(ClassFactory factory) 157 { 158 _classFactory = factory; 159 } 160 } | Popular Tags |