Coverage Report - org.apache.commons.clazz.reflect.ReflectedClazzLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
ReflectedClazzLoader
0%
0/93
0%
0/62
6.6
 
 1  
 /*
 2  
  * Copyright 2002-2004 The Apache Software Foundation
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.commons.clazz.reflect;
 17  
 
 18  
 import java.lang.reflect.Constructor;
 19  
 
 20  
 import org.apache.commons.clazz.Clazz;
 21  
 import org.apache.commons.clazz.ClazzAccessException;
 22  
 import org.apache.commons.clazz.ClazzLoader;
 23  
 import org.apache.commons.clazz.ModelClazzLoader;
 24  
 
 25  
 /**
 26  
  * 
 27  
  * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
 28  
  * @version $Id: ReflectedClazzLoader.java 155436 2005-02-26 13:17:48Z dirkv $
 29  
  */
 30  
 public abstract class ReflectedClazzLoader extends ClazzLoader {
 31  
 
 32  
     private ClassLoader classLoader;
 33  
     
 34  
     public ReflectedClazzLoader(
 35  
             ModelClazzLoader modelClazzLoader,
 36  
             ClassLoader classLoader) 
 37  
     {
 38  0
         super(modelClazzLoader);
 39  0
         this.classLoader = classLoader;
 40  0
     }
 41  
     
 42  
     public String getClazzName(Object instance) {
 43  0
         if (instance == null) {
 44  0
             return null;
 45  
         }
 46  0
         return Clazz.getCanonicalClassName(instance.getClass()); 
 47  
     }
 48  
     
 49  
     public Clazz getClazzForName(String name) {
 50  0
         Class javaClass = null;
 51  
         try {
 52  0
             if (classLoader != null) {
 53  0
                 javaClass = classLoader.loadClass(name);
 54  
             }
 55  
             else {
 56  0
                 javaClass = Class.forName(name);
 57  
             }
 58  
         }
 59  0
         catch (ClassNotFoundException ex) {
 60  
             // Won't happen
 61  0
         }
 62  
 
 63  0
         if (javaClass == null) {
 64  
             try {
 65  0
                 javaClass = getClazzForCanonicalName(classLoader, name);
 66  
             }
 67  0
             catch (ClassNotFoundException ex) {
 68  
                 // Won't happen
 69  0
             }
 70  
         }
 71  0
         if (javaClass == null) {
 72  0
             return null;
 73  
         }
 74  
         
 75  0
         if (javaClass.isArray()) {
 76  
             // TBD: automatically produce clazzes for arrays
 77  
         }
 78  
         else {
 79  0
             Clazz clazz = lookupCustomClazz(javaClass);
 80  0
             if (clazz != null) {
 81  0
                 return clazz;
 82  
             }
 83  
         }
 84  0
         if (!isSupportedClass(javaClass)) {
 85  0
             return null;
 86  
         }
 87  0
         return createClazz(javaClass);
 88  
     }
 89  
     
 90  
     /**
 91  
      * Try to find and allocate a custom Clazz for the specified Java class.
 92  
      * Build the name of the custom Clazz class out of the name of the 
 93  
      * Java class, followed by the model name, followed by the word "Clazz".
 94  
      * For example, if the java class is called "my.Foo", and the model is
 95  
      * "Standard", the corresponding Clazz class name is "my.FooStandardClazz".
 96  
      * 
 97  
      * @param javaClass
 98  
      * @return Clazz
 99  
      */
 100  
     protected Clazz lookupCustomClazz(Class javaClass) {
 101  0
         if (javaClass.isPrimitive()) {
 102  0
             return null;
 103  
         }
 104  
         
 105  0
         String customClazzName = javaClass.getName() + getModel() + "Clazz";
 106  
 
 107  
         Class customClazzClass;
 108  
         try {
 109  0
             if (classLoader == null) {
 110  0
                 classLoader = getClass().getClassLoader();
 111  
             }
 112  0
             if (classLoader != null) {
 113  0
                 customClazzClass = classLoader.loadClass(customClazzName);
 114  
             }
 115  
             else {
 116  0
                 customClazzClass = Class.forName(customClazzName);
 117  
             }
 118  
         }
 119  0
         catch (ClassNotFoundException e) {
 120  0
             return null;
 121  0
         }
 122  
             
 123  0
         if (!Clazz.class.isAssignableFrom(customClazzClass)) {
 124  0
             return null;
 125  
         }
 126  
         
 127  
         Constructor constructor;
 128  
         try {
 129  0
             constructor =
 130  
                 customClazzClass.getConstructor(
 131  
                     new Class[] { ClazzLoader.class, Class.class });
 132  0
             if (constructor == null) {
 133  0
                 return null;
 134  
             }
 135  
         }
 136  0
         catch (NoSuchMethodException e) {
 137  0
             return null;
 138  0
         }
 139  
                 
 140  
         try {
 141  0
             return (Clazz) constructor.newInstance(
 142  
                 new Object[] { getModelClazzLoader(), javaClass });
 143  
         }
 144  0
         catch (Exception e) {
 145  0
             throw new ClazzAccessException(
 146  
                 "Cannot instantiate custom ReflectedClazz " + customClazzName,
 147  
                 e);
 148  
         }
 149  
     }
 150  
         
 151  
 
 152  
     /**
 153  
      * Converts a canonical class name into the corresponding internal JVM type
 154  
      * name format and looks up the type.
 155  
      */
 156  
     private static Class getClazzForCanonicalName(
 157  
             ClassLoader classLoader,
 158  
             String name)
 159  
         throws ClassNotFoundException 
 160  
     {
 161  0
         int arrayDepth = 0;
 162  0
         while (name.endsWith("[]")) {
 163  0
             arrayDepth++;
 164  0
             name = name.substring(0, name.length() - 2);
 165  
         }
 166  
 
 167  0
         if (name.equals("boolean")) {
 168  0
             return getPrimitiveType(classLoader, arrayDepth, Boolean.TYPE, 'Z');
 169  
         }
 170  0
         else if (name.equals("byte")) {
 171  0
             return getPrimitiveType(classLoader, arrayDepth, Byte.TYPE, 'B');
 172  
         }
 173  0
         else if (name.equals("char")) {
 174  0
             return 
 175  
                 getPrimitiveType(classLoader, arrayDepth, Character.TYPE, 'C');
 176  
         }
 177  0
         else if (name.equals("short")) {
 178  0
             return getPrimitiveType(classLoader, arrayDepth, Short.TYPE, 'S');
 179  
         }
 180  0
         else if (name.equals("int")) {
 181  0
             return getPrimitiveType(classLoader, arrayDepth, Integer.TYPE, 'I');
 182  
         }
 183  0
         else if (name.equals("long")) {
 184  0
             return getPrimitiveType(classLoader, arrayDepth, Long.TYPE, 'J');
 185  
         }
 186  0
         else if (name.equals("float")) {
 187  0
             return getPrimitiveType(classLoader, arrayDepth, Float.TYPE, 'F');
 188  
         }
 189  0
         else if (name.equals("double")) {
 190  0
             return getPrimitiveType(classLoader, arrayDepth, Double.TYPE, 'D');
 191  
         }
 192  0
         if (arrayDepth != 0) {
 193  0
             StringBuffer buffer = new StringBuffer();
 194  0
             for (int i = 0; i < arrayDepth; i++) {
 195  0
                 buffer.append('[');
 196  
             }
 197  0
             buffer.append('L');
 198  0
             buffer.append(name);
 199  0
             buffer.append(';');
 200  0
             name = buffer.toString();
 201  
         }
 202  
 
 203  0
         if (classLoader != null) {
 204  0
             return classLoader.loadClass(name);
 205  
         }
 206  
         else {
 207  0
             return Class.forName(name);
 208  
         }
 209  
     }
 210  
 
 211  
     /**
 212  
      * Hacking around some JVM quirks, looks up Classes for primitive types and
 213  
      * arrays thereof.
 214  
      */
 215  
     private static Class getPrimitiveType(
 216  
             ClassLoader classLoader,
 217  
             int arrayDepth,
 218  
             Class primitiveType,
 219  
             char typeLetter)
 220  
         throws ClassNotFoundException 
 221  
     {
 222  0
         if (arrayDepth == 0) {
 223  0
             return primitiveType;
 224  
         }
 225  
 
 226  0
         StringBuffer buffer = new StringBuffer();
 227  0
         for (int i = 0; i < arrayDepth; i++) {
 228  0
             buffer.append('[');
 229  
         }
 230  0
         buffer.append(typeLetter);
 231  0
         String name = buffer.toString();
 232  
 
 233  0
         if (classLoader != null) {
 234  0
             return classLoader.loadClass(name);
 235  
         }
 236  
         else {
 237  0
             return Class.forName(name);
 238  
         }
 239  
     }      
 240  
     
 241  
     /**
 242  
      * Returns <code>true</code> for all objects.
 243  
      * 
 244  
      * @see ClazzLoader#isMember(Object)
 245  
      */
 246  
     public boolean isMember(Object instance) {
 247  0
         if (instance == null) {
 248  0
             return false;
 249  
         }
 250  0
         return isSupportedClass(instance.getClass());
 251  
     }
 252  
 
 253  
     /**
 254  
      * Returns true for all classes supported by this specific clazz loader.
 255  
      */
 256  
     protected boolean isSupportedClass(Class javaClass) {
 257  0
         return true;
 258  
     }
 259  
 
 260  
     /**
 261  
      * Override this method to construct an Clazz for the given Class
 262  
      * (javaClass). Make sure that the new Clazz is initialized with the
 263  
      * supplied clazzLoader representing the clazz loader group, not with
 264  
      * <code>this</code>.
 265  
      */
 266  
     protected abstract Clazz createClazz(Class javaClass);
 267  
 
 268  
     /**
 269  
      * @see ClazzLoader#defineClazz(String, Class, Class)
 270  
      */
 271  
     public Clazz defineClazz(
 272  
                 String name,
 273  
                 Class clazzClass,
 274  
                 Class instanceClass) 
 275  
     {
 276  0
         return null;
 277  
     }
 278  
 }