KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > hivemind > service > impl > ClassFabImpl


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 JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
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 extends AbstractFab implements ClassFab
43 {
44     /**
45      * Stores information about a constructor; used by toString().
46      *
47      * @since 1.1
48      */

49
50     private class AddedConstructor
51     {
52         private Class JavaDoc[] _parameterTypes;
53
54         private Class JavaDoc[] _exceptionTypes;
55
56         private String JavaDoc _body;
57
58         AddedConstructor(Class JavaDoc[] parameterTypes, Class JavaDoc[] exceptionTypes, String JavaDoc body)
59         {
60             _parameterTypes = parameterTypes;
61             _exceptionTypes = exceptionTypes;
62             _body = body;
63         }
64
65         public String JavaDoc toString()
66         {
67             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
68
69             buffer.append("public ");
70             buffer.append(getCtClass().getName());
71
72             buffer.append("(");
73
74             int count = size(_parameterTypes);
75             for (int i = 0; i < count; i++)
76             {
77                 if (i > 0)
78                     buffer.append(", ");
79
80                 buffer.append(_parameterTypes[i].getName());
81
82                 buffer.append(" $");
83                 buffer.append(i + 1);
84             }
85
86             buffer.append(")");
87
88             count = size(_exceptionTypes);
89             for (int i = 0; i < count; i++)
90             {
91                 if (i == 0)
92                     buffer.append("\n throws ");
93                 else
94                     buffer.append(", ");
95
96                 buffer.append(_exceptionTypes[i].getName());
97             }
98
99             buffer.append("\n");
100             buffer.append(_body);
101
102             buffer.append("\n");
103
104             return buffer.toString();
105         }
106
107         private int size(Object JavaDoc[] array)
108         {
109             return array == null ? 0 : array.length;
110         }
111     }
112
113     /**
114      * Map of {@link MethodFab}keyed on {@link MethodSignature}.
115      */

116     private Map JavaDoc _methods = new HashMap JavaDoc();
117
118     /**
119      * List of {@link AddedConstructor}.
120      *
121      * @since 1.1
122      */

123
124     private List JavaDoc _constructors = new ArrayList JavaDoc();
125
126     public ClassFabImpl(CtClassSource source, CtClass ctClass)
127     {
128         super(source, ctClass);
129     }
130
131     /**
132      * Returns a representation of the fabricated class, including inheritance, fields,
133      * constructors, methods and method bodies.
134      *
135      * @since 1.1
136      */

137     public String JavaDoc toString()
138     {
139         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("ClassFab[\n");
140
141         try
142         {
143             buildClassAndInheritance(buffer);
144
145             buildFields(buffer);
146
147             buildConstructors(buffer);
148
149             buildMethods(buffer);
150
151         }
152         catch (Exception JavaDoc ex)
153         {
154             buffer.append(" *** ");
155             buffer.append(ex);
156         }
157
158         buffer.append("\n]");
159
160         return buffer.toString();
161     }
162
163     /** @since 1.1 */
164     private void buildMethods(StringBuffer JavaDoc buffer)
165     {
166         Iterator JavaDoc i = _methods.values().iterator();
167         while (i.hasNext())
168         {
169
170             MethodFab mf = (MethodFab) i.next();
171
172             buffer.append("\n");
173             buffer.append(mf);
174             buffer.append("\n");
175         }
176     }
177
178     /** @since 1.1 */
179     private void buildConstructors(StringBuffer JavaDoc buffer)
180     {
181         Iterator JavaDoc i = _constructors.iterator();
182
183         while (i.hasNext())
184         {
185             buffer.append("\n");
186             buffer.append(i.next());
187         }
188     }
189
190     /** @since 1.1 */
191     private void buildFields(StringBuffer JavaDoc buffer) throws NotFoundException
192     {
193         CtField fields[] = getCtClass().getDeclaredFields();
194
195         for (int i = 0; i < fields.length; i++)
196         {
197             buffer.append("\n");
198             buffer.append(modifiers(fields[i].getModifiers()));
199             buffer.append(" ");
200             buffer.append(fields[i].getType().getName());
201             buffer.append(" ");
202             buffer.append(fields[i].getName());
203             buffer.append(";\n");
204         }
205     }
206
207     /** @since 1.1 */
208     private void buildClassAndInheritance(StringBuffer JavaDoc buffer) throws NotFoundException
209     {
210         buffer.append(modifiers(getCtClass().getModifiers()));
211         buffer.append(" class ");
212         buffer.append(getCtClass().getName());
213         buffer.append(" extends ");
214         buffer.append(getCtClass().getSuperclass().getName());
215         buffer.append("\n");
216
217         CtClass[] interfaces = getCtClass().getInterfaces();
218
219         if (interfaces.length > 0)
220         {
221             buffer.append(" implements ");
222
223             for (int i = 0; i < interfaces.length; i++)
224             {
225                 if (i > 0)
226                     buffer.append(", ");
227
228                 buffer.append(interfaces[i].getName());
229             }
230
231             buffer.append("\n");
232         }
233     }
234
235     private String JavaDoc modifiers(int modifiers)
236     {
237         return Modifier.toString(modifiers);
238     }
239
240     /**
241      * Returns the name of the class fabricated by this instance.
242      */

243     String JavaDoc getName()
244     {
245         return getCtClass().getName();
246     }
247     
248     public void addField(String JavaDoc name, Class JavaDoc type)
249     {
250         CtClass ctType = convertClass(type);
251
252         try
253         {
254             CtField field = new CtField(ctType, name, getCtClass());
255             field.setModifiers(Modifier.PRIVATE);
256
257             getCtClass().addField(field);
258         }
259         catch (CannotCompileException ex)
260         {
261             throw new ApplicationRuntimeException(ServiceMessages.unableToAddField(
262                     name,
263                     getCtClass(),
264                     ex), ex);
265         }
266     }
267
268     public boolean containsMethod( MethodSignature ms )
269     {
270         return _methods.get( ms ) != null;
271     }
272     
273     public MethodFab addMethod(int modifiers, MethodSignature ms, String JavaDoc body)
274     {
275         if (_methods.get(ms) != null)
276             throw new ApplicationRuntimeException(ServiceMessages.duplicateMethodInClass(ms, this));
277
278         CtClass ctReturnType = convertClass(ms.getReturnType());
279
280         CtClass[] ctParameters = convertClasses(ms.getParameterTypes());
281         CtClass[] ctExceptions = convertClasses(ms.getExceptionTypes());
282
283         CtMethod method = new CtMethod(ctReturnType, ms.getName(), ctParameters, getCtClass());
284
285         try
286         {
287             method.setModifiers(modifiers);
288             method.setBody(body);
289             method.setExceptionTypes(ctExceptions);
290
291             getCtClass().addMethod(method);
292         }
293         catch (Exception JavaDoc ex)
294         {
295             throw new ApplicationRuntimeException(ServiceMessages.unableToAddMethod(
296                     ms,
297                     getCtClass(),
298                     ex), ex);
299         }
300
301         // Return a MethodFab so the caller can add catches.
302

303         MethodFab result = new MethodFabImpl(getSource(), ms, method, body);
304
305         _methods.put(ms, result);
306
307         return result;
308     }
309
310     public MethodFab getMethodFab(MethodSignature ms)
311     {
312         return (MethodFab) _methods.get(ms);
313     }
314
315     public void addConstructor(Class JavaDoc[] parameterTypes, Class JavaDoc[] exceptions, String JavaDoc body)
316     {
317         CtClass[] ctParameters = convertClasses(parameterTypes);
318         CtClass[] ctExceptions = convertClasses(exceptions);
319
320         try
321         {
322             CtConstructor constructor = new CtConstructor(ctParameters, getCtClass());
323             constructor.setExceptionTypes(ctExceptions);
324             constructor.setBody(body);
325
326             getCtClass().addConstructor(constructor);
327
328             _constructors.add(new AddedConstructor(parameterTypes, exceptions, body));
329         }
330         catch (Exception JavaDoc ex)
331         {
332             throw new ApplicationRuntimeException(ServiceMessages.unableToAddConstructor(
333                     getCtClass(),
334                     ex), ex);
335         }
336     }
337
338 }
Popular Tags