View Javadoc

    1   /*
    2    * Copyright (c) 2001-2003 The XDoclet team
    3    * All rights reserved.
    4    */
    5   package xjavadoc;
    6
    7   import java.lang.reflect.Constructor;
    8   import java.lang.reflect.AccessibleObject;
    9   import java.lang.reflect.Method;
    10  import java.util.List;
    11  import java.util.Arrays;
    12
    13  /***
    14   * Describe what this class does
    15   *
    16   * @author    Ara Abrahamian
    17   * @author    Aslak Hellesøy
    18   * @created   20. mars 2003
    19   */
    20  final class BinaryClass extends AbstractClass
    21  {
    22  	public static int  instanceCount = 0;
    23
    24  	private final static List _primitiveTypes = Arrays.asList( new String[]{
    25  		"java.lang.Boolean",
    26  		"java.lang.Byte",
    27  		"java.lang.Character",
    28  		"java.lang.Double",
    29  		"java.lang.Float",
    30  		"java.lang.Integer",
    31  		"java.lang.Long",
    32  		"java.lang.Short",
    33  		"java.lang.String"
    34  		} );
    35  	private final Class _clazz;
    36
    37  	private boolean    _isSuperclassSet = false;
    38
    39  	private boolean    _isInterfacesSet = false;
    40  	public BinaryClass( XJavaDoc xJavaDoc, Class clazz  )
    41  	{
    42  		super( xJavaDoc, null );
    43  		_clazz = clazz;
    44  		setQualifiedName( clazz.getName() );
    45  		setContainingPackage( Util.getPackageNameFor( clazz.getName() ) );
    46
    47  		addModifier( clazz.getModifiers() );
    48
    49  //		setSuperclassMaybe();
    50  //		setInterfacesMaybe();
    51
    52  		// We gain speed by not instantiating the methods and constructors, and we probably don't need them (Aslak)
    53  		// Well, looks like we need it anyway:
    54  		// http://opensource.atlassian.com/projects/xdoclet/secure/ViewIssue.jspa?id=10100
    55  		// To avoid sacrificing speed, this will be controlled with a system property.
    56  		if( "true".equals( System.getProperty( "xjavadoc.compiledmethods" ) ) )
    57  		{
    58  			setMethods( _clazz );
    59  			setConstructors( _clazz );
    60  		}
    61  		instanceCount++;
    62  	}
    63
    64  	private static int getDimension( Class c )
    65  	{
    66  		return c.getName().lastIndexOf( '[' ) + 1;
    67  	}
    68
    69  	private static String getTypeName( Class c )
    70  	{
    71  		return c.getComponentType() != null ? c.getComponentType().getName() : c.getName();
    72  	}
    73
    74  	public XClass getSuperclass()
    75  	{
    76  		setSuperclassMaybe();
    77  		return super.getSuperclass();
    78  	}
    79
    80  	public List getInterfaces()
    81  	{
    82  		setInterfacesMaybe();
    83  		return super.getInterfaces();
    84  	}
    85
    86  	/***
    87  	 * whether this class is writeable an can be save ( it can not )
    88  	 *
    89  	 * @return   false since this class can not be mutated or saved
    90  	 */
    91  	public boolean isWriteable()
    92  	{
    93  		return false;
    94  	}
    95  	public boolean isImplementingInterface( String full_qualified_type_name, boolean superclasses )
    96  	{
    97  		return isClassImplementingInterface( _clazz, full_qualified_type_name, superclasses );
    98  	}
    99
    100 	public boolean isSubclassOf( String full_qualified_type_name, boolean superclasses )
    101 	{
    102 		Class superclass = _clazz.getSuperclass();
    103
    104 		if( superclass == null )
    105 			return false;
    106 		do
    107 		{
    108 			if( superclass.getName().equals( full_qualified_type_name ) )
    109 				return true;
    110
    111 			superclass = superclass.getSuperclass();
    112 		}while ( superclasses == true && superclass != null );
    113
    114 		return false;
    115 	}
    116
    117 	public boolean isPrimitive()
    118 	{
    119 		return _primitiveTypes.contains( getQualifiedName() );
    120 	}
    121
    122 	/***
    123 	 * no op since we do not save binary classes
    124 	 */
    125 	public void setDirty()
    126 	{
    127
    128 	}
    129
    130 	/***
    131 	 * this class is not intended to be saved
    132 	 *
    133 	 * @return   always false
    134 	 */
    135 	public boolean saveNeeded()
    136 	{
    137 		return false;
    138 	}
    139
    140 	private boolean isClassImplementingInterface( Class cur_class, String full_qualified_type_name, boolean superclasses )
    141 	{
    142 		do
    143 		{
    144 			Class[] interfaces = cur_class.getInterfaces();
    145
    146 			for( int i = 0; i < interfaces.length; i++ )
    147 			{
    148 				Class intf = interfaces[i];
    149
    150 				if( intf.getName().equals( full_qualified_type_name ) || isClassImplementingInterface( intf, full_qualified_type_name, superclasses ) )
    151 					return true;
    152 			}
    153
    154 			cur_class = cur_class.getSuperclass();
    155 		}while ( superclasses == true && cur_class != null );
    156
    157 		return false;
    158 	}
    159
    160 	private void setSuperclassMaybe()
    161 	{
    162 		if( !_isSuperclassSet )
    163 		{
    164 			Class superclass = _clazz.getSuperclass();
    165
    166 			if( superclass != null )
    167 			{
    168 				setSuperclass( superclass.getName() );
    169 			}
    170 			_isSuperclassSet = true;
    171 		}
    172 	}
    173
    174 	private void setInterfacesMaybe()
    175 	{
    176 		if( !_isInterfacesSet )
    177 		{
    178 			Class[] interfaces = _clazz.getInterfaces();
    179
    180 			for( int i = 0; i < interfaces.length; i++ )
    181 			{
    182 				addInterface( interfaces[i].getName() );
    183 			}
    184 			_isInterfacesSet = true;
    185 		}
    186 	}
    187
    188 	/***
    189 	 * Discovers constructors. This method is currently never called
    190 	 *
    191 	 * @param clazz
    192 	 */
    193 	private void setConstructors( Class clazz )
    194 	{
    195 		Constructor[] constructors = clazz.getDeclaredConstructors();
    196
    197 		for( int i = 0; i < constructors.length; i++ )
    198 		{
    199 			ConstructorImpl constructor = new ConstructorImpl( this, null );
    200
    201 			constructor.addModifier( constructors[i].getModifiers() );
    202 			populateExecutableMember( constructor, constructors[i] );
    203 			addConstructor( constructor );
    204 		}
    205 	}
    206
    207 	/***
    208 	 * Discovers constructors. This method is currently never called
    209 	 *
    210 	 * @param clazz
    211 	 */
    212 	private void setMethods( Class clazz )
    213 	{
    214 		Method[] methods = clazz.getDeclaredMethods();
    215
    216 		for( int i = 0; i < methods.length; i++ )
    217 		{
    218 			// Don't include static initialiser "methods"
    219 			if( !"<clinit>".equals( methods[i].getName() ) )
    220 			{
    221 				MethodImpl method = new MethodImpl( this, null );
    222
    223 				method.setName( methods[i].getName() );
    224
    225 				method.addModifier( methods[i].getModifiers() );
    226 				populateExecutableMember( method, methods[i] );
    227
    228 				Class returnType = methods[i].getReturnType();
    229
    230 				String typeName = getTypeName( returnType );
    231 				int dimension = getDimension( returnType );
    232
    233 				method.setReturnType( typeName );
    234 				method.setReturnDimension( dimension );
    235 				addMethod( method );
    236 			}
    237 		}
    238 	}
    239
    240 	private void populateExecutableMember( AbstractExecutableMember executableMember, AccessibleObject accessibleObject )
    241 	{
    242 		Class[] parameters;
    243 		Class[] exceptions;
    244
    245 		// sadly, getParameterTypes is not in the AccesibleObject or Member interface
    246 		if( accessibleObject instanceof Constructor )
    247 		{
    248 			parameters = ( ( Constructor ) accessibleObject ).getParameterTypes();
    249 			exceptions = ( ( Constructor ) accessibleObject ).getExceptionTypes();
    250 		}
    251 		else
    252 		{
    253 			// It's method then
    254 			parameters = ( ( Method ) accessibleObject ).getParameterTypes();
    255 			exceptions = ( ( Method ) accessibleObject ).getExceptionTypes();
    256 		}
    257 		for( int i = parameters.length - 1; i >= 0; i-- )
    258 		{
    259 			String typeName = getTypeName( parameters[i] );
    260 			int dimension = getDimension( parameters[i] );
    261
    262 			executableMember.addParameterData( typeName, "p" + i, dimension );
    263 		}
    264 		for( int i = exceptions.length - 1; i >= 0; i-- )
    265 		{
    266 			executableMember.addThrownException( exceptions[i].getName() );
    267 		}
    268 	}
    269 }