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 }