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: 258   Methods: 11
NCLOC: 178   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
EJBProxyFactory.java 87.5% 98.8% 100% 98%
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.Constructor;
 18    import java.lang.reflect.Modifier;
 19    import java.rmi.RemoteException;
 20   
 21    import org.apache.hivemind.ApplicationRuntimeException;
 22    import org.apache.hivemind.ServiceImplementationFactory;
 23    import org.apache.hivemind.ServiceImplementationFactoryParameters;
 24    import org.apache.hivemind.impl.BaseLocatable;
 25    import org.apache.hivemind.internal.Module;
 26    import org.apache.hivemind.lib.NameLookup;
 27    import org.apache.hivemind.lib.RemoteExceptionCoordinator;
 28    import org.apache.hivemind.service.BodyBuilder;
 29    import org.apache.hivemind.service.ClassFab;
 30    import org.apache.hivemind.service.ClassFabUtils;
 31    import org.apache.hivemind.service.ClassFactory;
 32    import org.apache.hivemind.service.MethodIterator;
 33    import org.apache.hivemind.service.MethodSignature;
 34   
 35    /**
 36    * An implementation of {@link org.apache.hivemind.ServiceImplementationFactory}
 37    * that can create a proxy to a stateless session EJB. Using this factory, it is
 38    * easy to create a HiveMind service wrapper around the actual EJB.
 39    *
 40    * <p>
 41    * The parameters for the factory are used to identify the JNDI name of the
 42    * session EJB's home interface.
 43    *
 44    * @author Howard Lewis Ship
 45    */
 46    public class EJBProxyFactory extends BaseLocatable implements ServiceImplementationFactory
 47    {
 48    private NameLookup _nameLookup;
 49    private RemoteExceptionCoordinator _coordinator;
 50    private ClassFactory _classFactory;
 51   
 52  3 public Object createCoreServiceImplementation(ServiceImplementationFactoryParameters factoryParameters)
 53    {
 54  3 EJBProxyParameters proxyParameters = (EJBProxyParameters) factoryParameters.getParameters().get(0);
 55  3 String jndiName = proxyParameters.getJndiName();
 56  3 String homeInterfaceClassName = proxyParameters.getHomeInterfaceClassName();
 57   
 58    // The service interface is the remote interface.
 59   
 60  3 Module module = factoryParameters.getInvokingModule();
 61  3 Class serviceInterface = factoryParameters.getServiceInterface();
 62   
 63  3 Class homeInterface = module.resolveType(homeInterfaceClassName);
 64   
 65  3 String proxyClassName = ClassFabUtils.generateClassName(serviceInterface);
 66   
 67  3 ClassFab classFab =
 68    _classFactory.newClass(
 69    proxyClassName,
 70    AbstractEJBProxy.class);
 71   
 72  3 classFab.addInterface(serviceInterface);
 73   
 74  3 classFab.addField("_remote", serviceInterface);
 75   
 76  3 addClearCachedMethod(classFab);
 77   
 78  3 addLookupMethod(classFab, homeInterface, serviceInterface, jndiName);
 79   
 80  3 addServiceMethods(classFab, serviceInterface, factoryParameters.getServiceId(), jndiName);
 81   
 82  3 addConstructor(classFab);
 83   
 84  3 Class proxyClass = classFab.createClass();
 85   
 86  3 return invokeConstructor(proxyClass, proxyParameters.getNameLookup(_nameLookup));
 87    }
 88   
 89  3 private void addClearCachedMethod(ClassFab classFab)
 90    {
 91  3 classFab.addMethod(
 92    Modifier.PROTECTED,
 93    new MethodSignature(void.class, "_clearCachedReferences", null, null),
 94    "_remote = null;");
 95    }
 96   
 97  3 private void addLookupMethod(
 98    ClassFab classFab,
 99    Class homeInterface,
 100    Class remoteInterface,
 101    String jndiName)
 102    {
 103  3 String homeInterfaceName = homeInterface.getName();
 104   
 105  3 BodyBuilder builder = new BodyBuilder();
 106   
 107  3 builder.begin();
 108   
 109  3 builder.addln("if (_remote != null)");
 110  3 builder.addln(" return _remote;");
 111   
 112  3 builder.add(homeInterfaceName);
 113  3 builder.add(" home = (");
 114  3 builder.add(homeInterfaceName);
 115  3 builder.add(") _lookup(");
 116  3 builder.addQuoted(jndiName);
 117  3 builder.addln(");");
 118   
 119  3 builder.add("try");
 120  3 builder.begin();
 121  3 builder.add("_remote = home.create();");
 122  3 builder.end();
 123  3 builder.add("catch (javax.ejb.CreateException ex)");
 124  3 builder.begin();
 125  3 builder.add("throw new java.rmi.RemoteException(ex.getMessage(), ex);");
 126  3 builder.end();
 127   
 128  3 builder.add("return _remote;");
 129   
 130  3 builder.end();
 131   
 132  3 classFab.addMethod(
 133    Modifier.SYNCHRONIZED + Modifier.PRIVATE,
 134    new MethodSignature(
 135    remoteInterface,
 136    "_lookupRemote",
 137    null,
 138    new Class[] { RemoteException.class }),
 139    builder.toString());
 140   
 141    }
 142   
 143  3 private void addServiceMethods(
 144    ClassFab classFab,
 145    Class serviceInterface,
 146    String serviceId,
 147    String jndiName)
 148    {
 149  3 MethodIterator mi = new MethodIterator(serviceInterface);
 150   
 151  3 while (mi.hasNext())
 152    {
 153  18 addServiceMethod(classFab, mi.next());
 154    }
 155   
 156  3 if (!mi.getToString())
 157  3 addToStringMethod(classFab, serviceInterface, serviceId, jndiName);
 158    }
 159   
 160  18 private void addServiceMethod(ClassFab classFab, MethodSignature sig)
 161    {
 162  18 String methodName = sig.getName();
 163   
 164  18 boolean isVoid = sig.getReturnType().equals(Void.TYPE);
 165   
 166  18 BodyBuilder builder = new BodyBuilder();
 167   
 168  18 builder.begin();
 169   
 170  18 builder.addln("boolean first = true;");
 171  18 builder.add("while (true)");
 172  18 builder.begin();
 173   
 174  18 builder.add("try");
 175  18 builder.begin();
 176   
 177  18 if (!isVoid)
 178  15 builder.add("return ");
 179   
 180  18 builder.add("_lookupRemote().");
 181  18 builder.add(methodName);
 182  18 builder.addln("($$);");
 183   
 184  18 if (isVoid)
 185  3 builder.addln("return;");
 186   
 187  18 builder.end(); // try
 188   
 189  18 builder.add("catch (java.rmi.RemoteException ex)");
 190  18 builder.begin();
 191   
 192  18 builder.addln("if (first)");
 193  18 builder.begin();
 194   
 195  18 builder.addln("_handleRemoteException(ex);");
 196  18 builder.addln("first = false;");
 197   
 198  18 builder.end(); // if
 199  18 builder.addln("else");
 200  18 builder.add(" throw ex;");
 201  18 builder.end(); // catch
 202  18 builder.end(); // while
 203  18 builder.end();
 204   
 205  18 classFab.addMethod(Modifier.PUBLIC, sig, builder.toString());
 206    }
 207   
 208  3 private void addToStringMethod(
 209    ClassFab classFab,
 210    Class serviceInterface,
 211    String serviceId,
 212    String jndiName)
 213    {
 214  3 ClassFabUtils.addToStringMethod(
 215    classFab,
 216    ImplMessages.ejbProxyDescription(serviceId, serviceInterface, jndiName));
 217    }
 218   
 219  3 private void addConstructor(ClassFab classFab)
 220    {
 221  3 classFab.addConstructor(
 222    new Class[] { NameLookup.class, RemoteExceptionCoordinator.class },
 223    null,
 224    "super($1, $2);");
 225    }
 226   
 227  3 private Object invokeConstructor(Class proxyClass, NameLookup nameLookup)
 228    {
 229  3 try
 230    {
 231  3 Constructor c =
 232    proxyClass.getConstructor(
 233    new Class[] { NameLookup.class, RemoteExceptionCoordinator.class });
 234   
 235  3 return c.newInstance(new Object[] { nameLookup, _coordinator });
 236    }
 237    catch (Exception ex)
 238    {
 239  0 throw new ApplicationRuntimeException(ex);
 240    }
 241    }
 242   
 243  3 public void setClassFactory(ClassFactory factory)
 244    {
 245  3 _classFactory = factory;
 246    }
 247   
 248  3 public void setCoordinator(RemoteExceptionCoordinator coordinator)
 249    {
 250  3 _coordinator = coordinator;
 251    }
 252   
 253  3 public void setNameLookup(NameLookup lookup)
 254    {
 255  3 _nameLookup = lookup;
 256    }
 257   
 258    }