Clover coverage report - Code Coverage for hivemind release 1.1-alpha-1
Coverage timestamp: Tue Jan 18 2005 07:55:08 EST
file stats: LOC: 392   Methods: 19
NCLOC: 254   Classes: 2
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
ClassFabImpl.java 93.3% 97.5% 100% 97%
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.service.impl;
 16   
 
 17   
 import java.lang.reflect.Modifier;
 18   
 import java.util.ArrayList;
 19   
 import java.util.HashMap;
 20   
 import java.util.Iterator;
 21   
 import java.util.List;
 22   
 import java.util.Map;
 23   
 
 24   
 import javassist.CannotCompileException;
 25   
 import javassist.CtClass;
 26   
 import javassist.CtConstructor;
 27   
 import javassist.CtField;
 28   
 import javassist.CtMethod;
 29   
 import javassist.NotFoundException;
 30   
 
 31   
 import org.apache.hivemind.ApplicationRuntimeException;
 32   
 import org.apache.hivemind.service.ClassFab;
 33   
 import org.apache.hivemind.service.MethodFab;
 34   
 import org.apache.hivemind.service.MethodSignature;
 35   
 
 36   
 /**
 37   
  * Implementation of {@link org.apache.hivemind.service.ClassFab}. Hides, as much as possible, the
 38   
  * underlying library (Javassist).
 39   
  * 
 40   
  * @author Howard Lewis Ship
 41   
  */
 42   
 public class ClassFabImpl implements ClassFab
 43   
 {
 44   
     private final CtClass _ctClass;
 45   
 
 46   
     private final CtClassSource _source;
 47   
 
 48   
     /**
 49   
      * Map from Class to CtClass.
 50   
      * 
 51   
      * @since 1.1
 52   
      */
 53   
 
 54   
     private Map _ctClassCache = new HashMap();
 55   
 
 56   
     /**
 57   
      * Stores information about a constructor; used by toString().
 58   
      * 
 59   
      * @since 1.1
 60   
      */
 61   
 
 62   
     private class AddedConstructor
 63   
     {
 64   
         private Class[] _parameterTypes;
 65   
 
 66   
         private Class[] _exceptionTypes;
 67   
 
 68   
         private String _body;
 69   
 
 70  733
         AddedConstructor(Class[] parameterTypes, Class[] exceptionTypes, String body)
 71   
         {
 72  733
             _parameterTypes = parameterTypes;
 73  733
             _exceptionTypes = exceptionTypes;
 74  733
             _body = body;
 75   
         }
 76   
 
 77  1
         public String toString()
 78   
         {
 79  1
             StringBuffer buffer = new StringBuffer();
 80   
 
 81  1
             buffer.append("public ");
 82  1
             buffer.append(_ctClass.getName());
 83   
 
 84  1
             buffer.append("(");
 85   
 
 86  1
             int count = size(_parameterTypes);
 87  1
             for (int i = 0; i < count; i++)
 88   
             {
 89  2
                 if (i > 0)
 90  1
                     buffer.append(", ");
 91   
 
 92  2
                 buffer.append(_parameterTypes[i].getName());
 93   
 
 94  2
                 buffer.append(" $");
 95  2
                 buffer.append(i + 1);
 96   
             }
 97   
 
 98  1
             buffer.append(")");
 99   
 
 100  1
             count = size(_exceptionTypes);
 101  1
             for (int i = 0; i < count; i++)
 102   
             {
 103  2
                 if (i == 0)
 104  1
                     buffer.append("\n  throws ");
 105   
                 else
 106  1
                     buffer.append(", ");
 107   
 
 108  2
                 buffer.append(_exceptionTypes[i].getName());
 109   
             }
 110   
 
 111  1
             buffer.append("\n");
 112  1
             buffer.append(_body);
 113   
 
 114  1
             buffer.append("\n");
 115   
 
 116  1
             return buffer.toString();
 117   
         }
 118   
 
 119  2
         private int size(Object[] array)
 120   
         {
 121  2
             return array == null ? 0 : array.length;
 122   
         }
 123   
     }
 124   
 
 125   
     /**
 126   
      * Map of {@link MethodFab}keyed on {@link MethodSignature}.
 127   
      */
 128   
     private Map _methods = new HashMap();
 129   
 
 130   
     /**
 131   
      * List of {@link AddedConstructor}.
 132   
      * 
 133   
      * @since 1.1
 134   
      */
 135   
 
 136   
     private List _constructors = new ArrayList();
 137   
 
 138  1455
     public ClassFabImpl(CtClassSource source, CtClass ctClass)
 139   
     {
 140  1455
         _source = source;
 141  1455
         _ctClass = ctClass;
 142   
     }
 143   
 
 144   
     /**
 145   
      * Returns a representation of the fabricated class, including inheritance, fields,
 146   
      * constructors, methods and method bodies.
 147   
      * 
 148   
      * @since 1.1
 149   
      */
 150  1
     public String toString()
 151   
     {
 152  1
         StringBuffer buffer = new StringBuffer("ClassFab[\n");
 153   
 
 154  1
         try
 155   
         {
 156  1
             buildClassAndInheritance(buffer);
 157   
 
 158  1
             buildFields(buffer);
 159   
 
 160  1
             buildConstructors(buffer);
 161   
 
 162  1
             buildMethods(buffer);
 163   
 
 164   
         }
 165   
         catch (Exception ex)
 166   
         {
 167  0
             buffer.append(" *** ");
 168  0
             buffer.append(ex);
 169   
         }
 170   
 
 171  1
         buffer.append("\n]");
 172   
 
 173  1
         return buffer.toString();
 174   
     }
 175   
 
 176   
     /** @since 1.1 */
 177  1
     private void buildMethods(StringBuffer buffer)
 178   
     {
 179  1
         Iterator i = _methods.values().iterator();
 180  1
         while (i.hasNext())
 181   
         {
 182   
 
 183  1
             MethodFab mf = (MethodFab) i.next();
 184   
 
 185  1
             buffer.append("\n");
 186  1
             buffer.append(mf);
 187  1
             buffer.append("\n");
 188   
         }
 189   
     }
 190   
 
 191   
     /** @since 1.1 */
 192  1
     private void buildConstructors(StringBuffer buffer)
 193   
     {
 194  1
         Iterator i = _constructors.iterator();
 195   
 
 196  1
         while (i.hasNext())
 197   
         {
 198  1
             buffer.append("\n");
 199  1
             buffer.append(i.next());
 200   
         }
 201   
     }
 202   
 
 203   
     /** @since 1.1 */
 204  1
     private void buildFields(StringBuffer buffer) throws NotFoundException
 205   
     {
 206  1
         CtField fields[] = _ctClass.getDeclaredFields();
 207   
 
 208  1
         for (int i = 0; i < fields.length; i++)
 209   
         {
 210  1
             buffer.append("\n");
 211  1
             buffer.append(modifiers(fields[i].getModifiers()));
 212  1
             buffer.append(" ");
 213  1
             buffer.append(fields[i].getType().getName());
 214  1
             buffer.append(" ");
 215  1
             buffer.append(fields[i].getName());
 216  1
             buffer.append(";\n");
 217   
         }
 218   
     }
 219   
 
 220   
     /** @since 1.1 */
 221  1
     private void buildClassAndInheritance(StringBuffer buffer) throws NotFoundException
 222   
     {
 223  1
         buffer.append(modifiers(_ctClass.getModifiers()));
 224  1
         buffer.append(" class ");
 225  1
         buffer.append(_ctClass.getName());
 226  1
         buffer.append(" extends ");
 227  1
         buffer.append(_ctClass.getSuperclass().getName());
 228  1
         buffer.append("\n");
 229   
 
 230  1
         CtClass[] interfaces = _ctClass.getInterfaces();
 231   
 
 232  1
         if (interfaces.length > 0)
 233   
         {
 234  1
             buffer.append("  implements ");
 235   
 
 236  1
             for (int i = 0; i < interfaces.length; i++)
 237   
             {
 238  2
                 if (i > 0)
 239  1
                     buffer.append(", ");
 240   
 
 241  2
                 buffer.append(interfaces[i].getName());
 242   
             }
 243   
 
 244  1
             buffer.append("\n");
 245   
         }
 246   
     }
 247   
 
 248  2
     private String modifiers(int modifiers)
 249   
     {
 250  2
         return Modifier.toString(modifiers);
 251   
     }
 252   
 
 253   
     /**
 254   
      * Returns the name of the class fabricated by this instance.
 255   
      */
 256  1
     String getName()
 257   
     {
 258  1
         return _ctClass.getName();
 259   
     }
 260   
 
 261  4293
     public void addInterface(Class interfaceClass)
 262   
     {
 263  4293
         CtClass ctInterfaceClass = _source.getCtClass(interfaceClass);
 264   
 
 265  4293
         _ctClass.addInterface(ctInterfaceClass);
 266   
     }
 267   
 
 268  3599
     public void addField(String name, Class type)
 269   
     {
 270  3599
         CtClass ctType = _source.getCtClass(type);
 271   
 
 272  3599
         try
 273   
         {
 274  3599
             CtField field = new CtField(ctType, name, _ctClass);
 275  3599
             field.setModifiers(Modifier.PRIVATE);
 276   
 
 277  3599
             _ctClass.addField(field);
 278   
         }
 279   
         catch (CannotCompileException ex)
 280   
         {
 281  0
             throw new ApplicationRuntimeException(ServiceMessages.unableToAddField(
 282   
                     name,
 283   
                     _ctClass,
 284   
                     ex), ex);
 285   
         }
 286   
     }
 287   
 
 288  8098
     public MethodFab addMethod(int modifiers, MethodSignature ms, String body)
 289   
     {
 290  8098
         if (_methods.get(ms) != null)
 291  1
             throw new ApplicationRuntimeException(ServiceMessages.duplicateMethodInClass(ms, this));
 292   
 
 293  8097
         CtClass ctReturnType = _source.getCtClass(ms.getReturnType());
 294   
 
 295  8097
         CtClass[] ctParameters = convertClasses(ms.getParameterTypes());
 296  8097
         CtClass[] ctExceptions = convertClasses(ms.getExceptionTypes());
 297   
 
 298  8097
         CtMethod method = new CtMethod(ctReturnType, ms.getName(), ctParameters, _ctClass);
 299   
 
 300  8097
         try
 301   
         {
 302  8097
             method.setBody(body);
 303  8096
             method.setModifiers(modifiers);
 304  8096
             method.setExceptionTypes(ctExceptions);
 305   
 
 306  8096
             _ctClass.addMethod(method);
 307   
         }
 308   
         catch (Exception ex)
 309   
         {
 310  1
             throw new ApplicationRuntimeException(ServiceMessages.unableToAddMethod(
 311   
                     ms,
 312   
                     _ctClass,
 313   
                     ex), ex);
 314   
         }
 315   
 
 316   
         // Return a MethodFab so the caller can add catches.
 317   
 
 318  8096
         MethodFab result = new MethodFabImpl(_source, ms, method, body);
 319   
 
 320  8096
         _methods.put(ms, result);
 321   
 
 322  8096
         return result;
 323   
     }
 324   
 
 325  2
     public MethodFab getMethodFab(MethodSignature ms)
 326   
     {
 327  2
         return (MethodFab) _methods.get(ms);
 328   
     }
 329   
 
 330  734
     public void addConstructor(Class[] parameterTypes, Class[] exceptions, String body)
 331   
     {
 332  734
         CtClass[] ctParameters = convertClasses(parameterTypes);
 333  734
         CtClass[] ctExceptions = convertClasses(exceptions);
 334   
 
 335  734
         try
 336   
         {
 337  734
             CtConstructor constructor = new CtConstructor(ctParameters, _ctClass);
 338  734
             constructor.setExceptionTypes(ctExceptions);
 339  734
             constructor.setBody(body);
 340   
 
 341  733
             _ctClass.addConstructor(constructor);
 342   
 
 343  733
             _constructors.add(new AddedConstructor(parameterTypes, exceptions, body));
 344   
         }
 345   
         catch (Exception ex)
 346   
         {
 347  1
             throw new ApplicationRuntimeException(ServiceMessages.unableToAddConstructor(
 348   
                     _ctClass,
 349   
                     ex), ex);
 350   
         }
 351   
     }
 352   
 
 353  17662
     private CtClass[] convertClasses(Class[] inputClasses)
 354   
     {
 355  17662
         if (inputClasses == null || inputClasses.length == 0)
 356  14913
             return null;
 357   
 
 358  2749
         int count = inputClasses.length;
 359  2749
         CtClass[] result = new CtClass[count];
 360   
 
 361  2749
         for (int i = 0; i < count; i++)
 362   
         {
 363  6583
             CtClass ctClass = convertClass(inputClasses[i]);
 364   
 
 365  6583
             result[i] = ctClass;
 366   
         }
 367   
 
 368  2749
         return result;
 369   
     }
 370   
 
 371   
     /**
 372   
      * @since 1.1
 373   
      */
 374  6583
     private CtClass convertClass(Class inputClass)
 375   
     {
 376  6583
         CtClass result = (CtClass) _ctClassCache.get(inputClass);
 377   
 
 378  6583
         if (result == null)
 379   
         {
 380  6466
             result = _source.getCtClass(inputClass);
 381  6466
             _ctClassCache.put(inputClass, result);
 382   
         }
 383   
 
 384  6583
         return result;
 385   
     }
 386   
 
 387  1448
     public Class createClass()
 388   
     {
 389  1448
         return _source.createClass(_ctClass);
 390   
     }
 391   
 
 392   
 }