KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejen > ext > JavaClassToXML


1 //
2
// Ejen (code generation system)
3
// Copyright (C) 2001, 2002 François Wolff (ejen@noos.fr).
4
//
5
// This file is part of Ejen.
6
//
7
// Ejen is free software; you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation; either version 2 of the License, or
10
// (at your option) any later version.
11
//
12
// Ejen is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
16
//
17
// You should have received a copy of the GNU General Public License
18
// along with Ejen; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
//
21
package org.ejen.ext;
22
23 import org.ejen.util.DOMUtil;
24 import java.lang.reflect.*;
25 import org.w3c.dom.Node JavaDoc;
26 import org.w3c.dom.Element JavaDoc;
27 import org.w3c.dom.Document JavaDoc;
28 import org.apache.xalan.extensions.ExpressionContext;
29 import org.apache.xml.utils.WrappedRuntimeException;
30
31 /**
32  * Class reflection utility (static methods).
33  * <p>
34  * <table class="usage">
35  * <tr><th class="usage">Usage (XSL stylesheet)</th></tr>
36  * <tr><td class="usage"><pre>
37  *
38  * &lt;?xml version="1.0" encoding="iso-8859-1"?&gt;
39  *
40  * &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
41  * ...
42  * <b>xmlns:jcx="org.ejen.ext.JavaClassToXML"</b>
43  * version="1.0"&gt;
44  *
45  * &lt;xsl:output method="xml" encoding="iso-8859-1"/&gt;
46  *
47  * &lt;xsl:template match="ejen"&gt;
48  *
49  * &lt;xsl:copy-of select="jcx:{@link #process(ExpressionContext,String) process}('java.lang.String')"/&gt;
50  * &lt;xsl:value-of select="jcx:{@link #stripType(ExpressionContext,String) stripType}('[LLjava.lang.Object;')"/&gt;
51  * &lt;xsl:value-of select="jcx:{@link #stripTypeDims(ExpressionContext,String) stripTypeDims}('[LLjava.lang.Object;')"/&gt;
52  * &lt;xsl:value-of select="jcx:{@link #dimsOfType(ExpressionContext,String) dimsOfType}('[LLjava.lang.Object;')"/&gt;
53  * &lt;xsl:value-of select="jcx:{@link #packageOfType(ExpressionContext,String) packageOfType}('[LLjava.lang.Object;')"/&gt;
54  *
55  * &lt;/xsl:template&gt;
56  *
57  * &lt;/xsl:stylesheet&gt;
58  * </pre></td></tr></table>
59  * @author F. Wolff
60  * @version 1.0
61  */

62 public class JavaClassToXML {
63
64     /** String that represents one array dimension: <code>[]</code> */
65     public static final String JavaDoc DIM_STR = "[]";
66
67     /**
68      * Protected constructor (prevents instanciation).
69      */

70     protected JavaClassToXML() {}
71
72     /**
73      * Returns a <code>Node</code> that represents a Class definition.
74      * <p>
75      * <table class="usage">
76      * <tr><td class="usage"><pre>
77      *
78      * &lt;xsl:copy-of select="jcx:process('java.lang.String')"/&gt;
79      * </pre></td></tr></table>
80      * <p>
81      * The class definition returned is recursive (for each class/interface definition,
82      * all extended or implemented class/interface definitions are also provided).
83      * <p>
84      * For "java.lang.String", the returned tree as the following structure:
85      * <p>
86      * <table class="usage">
87      * <tr><td class="usage"><pre>
88      *
89      * &lt;class-definition interface="false"&gt;
90      * &lt;package&gt;&lt;![CDATA[java.lang]]&gt;&lt;/package&gt;
91      * &lt;modifiers&gt;&lt;![CDATA[public final]]&gt;&lt;/modifiers&gt;
92      * &lt;name&gt;&lt;![CDATA[String]]&gt;&lt;/name&gt;
93      * &lt;extends&gt;
94      * &lt;class-definition interface="false"&gt;
95      * &lt;package&gt;&lt;![CDATA[java.lang]]&gt;&lt;/package&gt;
96      * &lt;modifiers&gt;&lt;![CDATA[public]]&gt;&lt;/modifiers&gt;
97      * &lt;name&gt;&lt;![CDATA[Object]]&gt;&lt;/name&gt;
98      * ...
99      * &lt;/class-definition&gt;
100      * &lt;/extends&gt;
101      * &lt;implements&gt;
102      * &lt;class-definition interface="true"&gt;
103      * &lt;package&gt;&lt;![CDATA[java.io]]&gt;&lt;/package&gt;
104      * &lt;modifiers&gt;&lt;![CDATA[public abstract interface]]&gt;&lt;/modifiers&gt;
105      * &lt;name&gt;&lt;![CDATA[Serializable]]&gt;&lt;/name&gt;
106      * &lt;/class-definition&gt;
107      * &lt;class-definition interface="true"&gt;
108      * &lt;package&gt;&lt;![CDATA[java.lang]]&gt;&lt;/package&gt;
109      * &lt;modifiers&gt;&lt;![CDATA[public abstract interface]]&gt;&lt;/modifiers&gt;
110      * &lt;name&gt;&lt;![CDATA[Comparable]]&gt;&lt;/name&gt;
111      * &lt;method&gt;
112      * &lt;modifiers&gt;&lt;![CDATA[public abstract]]&gt;&lt;/modifiers&gt;
113      * &lt;return-type&gt;&lt;![CDATA[int]]&gt;&lt;/return-type&gt;
114      * &lt;name&gt;&lt;![CDATA[compareTo]]&gt;&lt;/name&gt;
115      * &lt;parameter&gt;&lt;![CDATA[java.lang.Object]]&gt;&lt;/parameter&gt;
116      * &lt;/method&gt;
117      * &lt;/class-definition&gt;
118      * &lt;/implements&gt;
119      * &lt;field&gt;
120      * &lt;modifiers&gt;&lt;![CDATA[private]]&gt;&lt;/modifiers&gt;
121      * &lt;type&gt;&lt;![CDATA[[C]]&gt;&lt;/type&gt;
122      * &lt;name&gt;&lt;![CDATA[value]]&gt;&lt;/name&gt;
123      * &lt;/field&gt;
124      * ...
125      * &lt;constructor&gt;
126      * &lt;modifiers&gt;&lt;![CDATA[public]]&gt;&lt;/modifiers&gt;
127      * &lt;/constructor&gt;
128      * &lt;constructor&gt;
129      * &lt;modifiers&gt;&lt;![CDATA[public]]&gt;&lt;/modifiers&gt;
130      * &lt;parameter&gt;&lt;![CDATA[java.lang.String]]&gt;&lt;/parameter&gt;
131      * &lt;/constructor&gt;
132      * ...
133      * &lt;method&gt;
134      * &lt;modifiers&gt;&lt;![CDATA[public]]&gt;&lt;/modifiers&gt;
135      * &lt;return-type&gt;&lt;![CDATA[int]]&gt;&lt;/return-type&gt;
136      * &lt;name&gt;&lt;![CDATA[hashCode]]&gt;&lt;/name&gt;
137      * &lt;/method&gt;
138      * &lt;method&gt;
139      * &lt;modifiers&gt;&lt;![CDATA[public]]&gt;&lt;/modifiers&gt;
140      * &lt;return-type&gt;&lt;![CDATA[int]]&gt;&lt;/return-type&gt;
141      * &lt;name&gt;&lt;![CDATA[compareTo]]&gt;&lt;/name&gt;
142      * &lt;parameter&gt;&lt;![CDATA[java.lang.String]]&gt;&lt;/parameter&gt;
143      * &lt;/method&gt;
144      * ...
145      * &lt;class-definition interface="false"&gt;
146      * &lt;package&gt;&lt;![CDATA[java.lang]]&gt;&lt;/package&gt;
147      * &lt;modifiers/&gt;
148      * &lt;name&gt;&lt;![CDATA[String$1]]&gt;&lt;/name&gt;
149      * ...
150      * &lt;/class-definition&gt;
151      * &lt;class-definition interface="false"&gt;
152      * &lt;package&gt;&lt;![CDATA[java.lang]]&gt;&lt;/package&gt;
153      * &lt;modifiers&gt;&lt;![CDATA[private static]]&gt;&lt;/modifiers&gt;
154      * &lt;name&gt;&lt;![CDATA[String$CaseInsensitiveComparator]]&gt;&lt;/name&gt;
155      * ...
156      * &lt;/class-definition&gt;
157      * ...
158      * &lt;/class-definition&gt;
159      * </pre></td></tr></table>
160      * <p>
161      * Note: the two last "class-definitions" are inner class definitions in
162      * <code>java.lang.String</code>.
163      * <p>
164      * <dd><dl><dt><b>XSLT parameters:</b>
165      * <dd><b>[Mandatory/AVT]</b> full Class name.
166      * </dl></dd>
167      * <p>
168      * @param context automatically passed by the xalan extension mechanism.
169      * @param className Class name.
170      * @return a <code>Node</code> that represents a Class definition.
171      * @throws org.apache.xml.utils.WrappedRuntimeException errors (...).
172      */

173     public static Node JavaDoc process(ExpressionContext context, String JavaDoc className) {
174         className = org.ejen.util.XSLUtil.evaluate(context, className);
175         Document JavaDoc doc = org.ejen.util.XSLUtil.getContextDocument(context);
176         Class JavaDoc clazz;
177
178         try {
179             clazz = Class.forName(className);
180         } catch (Exception JavaDoc e) {
181             throw new WrappedRuntimeException("Invalid class name", e);
182         }
183         return process(doc, clazz);
184     }
185     
186     /**
187      * Returns a <code>Node</code> that represents a Class definition.
188      * <p>
189      * @param doc the current Document.
190      * @param c the Class to get definition from..
191      * @return a <code>Node</code> that represents a Class definition.
192      * @throws org.apache.xml.utils.WrappedRuntimeException errors (...).
193      */

194     protected static Node JavaDoc process(Document JavaDoc doc, Class JavaDoc c) {
195         try {
196             Element JavaDoc root = doc.createElement("class-definition");
197
198             root.setAttribute("interface", (c.isInterface()) ? "true" : "false");
199             String JavaDoc className = c.getName();
200             int iLastDot = className.lastIndexOf('.');
201
202             if (iLastDot != -1) {
203                 DOMUtil.createCDATANode(doc, root, "package",
204                         className.substring(0, iLastDot));
205                 className = className.substring(iLastDot + 1);
206             }
207             DOMUtil.createCDATANode(doc, root, "modifiers",
208                     Modifier.toString(c.getModifiers()));
209             DOMUtil.createCDATANode(doc, root, "name", className);
210             Class JavaDoc sc = c.getSuperclass();
211
212             if (sc != null) {
213                 DOMUtil.createNode(doc, root, "extends").appendChild(process(doc,
214                         sc));
215             }
216             Class JavaDoc[] is = c.getInterfaces();
217
218             if (is.length > 0) {
219                 Node JavaDoc nis = DOMUtil.createNode(doc, root, "implements");
220
221                 for (int i = 0; i < is.length; i++) {
222                     nis.appendChild(process(doc, is[i]));
223                 }
224             }
225             Field[] fs = c.getDeclaredFields();
226
227             for (int i = 0; i < fs.length; i++) {
228                 Field f = fs[i];
229                 int mods = f.getModifiers();
230                 Node JavaDoc nf = DOMUtil.createNode(doc, root, "field");
231
232                 DOMUtil.createCDATANode(doc, nf, "modifiers",
233                         Modifier.toString(mods));
234                 DOMUtil.createCDATANode(doc, nf, "type", f.getType().getName());
235                 DOMUtil.createCDATANode(doc, nf, "name", f.getName());
236                 if (Modifier.isStatic(mods) && Modifier.isPublic(mods)) {
237                     DOMUtil.createCDATANode(doc, nf, "init",
238                             f.get(null).toString());
239                 }
240             }
241             Constructor[] cos = c.getConstructors();
242
243             for (int i = 0; i < cos.length; i++) {
244                 Constructor co = cos[i];
245                 Node JavaDoc nco = DOMUtil.createNode(doc, root, "constructor");
246
247                 DOMUtil.createCDATANode(doc, nco, "modifiers",
248                         Modifier.toString(co.getModifiers()));
249                 Class JavaDoc[] ps = co.getParameterTypes();
250
251                 for (int j = 0; j < ps.length; j++) {
252                     DOMUtil.createCDATANode(doc, nco, "parameter",
253                             ps[j].getName());
254                 }
255                 Class JavaDoc[] es = co.getExceptionTypes();
256
257                 for (int j = 0; j < es.length; j++) {
258                     DOMUtil.createCDATANode(doc, nco, "exception",
259                             es[j].getName());
260                 }
261             }
262             Method[] ms = c.getDeclaredMethods();
263
264             for (int i = 0; i < ms.length; i++) {
265                 Method m = ms[i];
266                 Node JavaDoc nm = DOMUtil.createNode(doc, root, "method");
267
268                 DOMUtil.createCDATANode(doc, nm, "modifiers",
269                         Modifier.toString(m.getModifiers()));
270                 DOMUtil.createCDATANode(doc, nm, "return-type",
271                         m.getReturnType().getName());
272                 DOMUtil.createCDATANode(doc, nm, "name", m.getName());
273                 Class JavaDoc[] ps = m.getParameterTypes();
274
275                 for (int j = 0; j < ps.length; j++) {
276                     DOMUtil.createCDATANode(doc, nm, "parameter",
277                             ps[j].getName());
278                 }
279                 Class JavaDoc[] es = m.getExceptionTypes();
280
281                 for (int j = 0; j < es.length; j++) {
282                     DOMUtil.createCDATANode(doc, nm, "exception",
283                             es[j].getName());
284                 }
285             }
286             Class JavaDoc[] cs = c.getDeclaredClasses();
287
288             for (int i = 0; i < cs.length; i++) {
289                 root.appendChild(process(doc, cs[i]));
290             }
291             return root;
292         } catch (WrappedRuntimeException e) {
293             throw e;
294         } catch (Exception JavaDoc e) {
295             throw new WrappedRuntimeException(e);
296         }
297     }
298
299     /**
300      * Strips a type definition (see {@link java.lang.Class#getName()
301      * Java signature format}), removing all array dimensions and package information.
302      * <p>
303      * <table class="usage">
304      * <tr><td class="usage"><pre>
305      *
306      * &lt;xsl:value-of select="jcx:stripType('[[Ljava.lang.String;')"/&gt;
307      * </pre></td></tr></table>
308      * <p>
309      * For example, the function will return "<code>Object</code>" for
310      * "<code>[LLjava.lang.Object;</code>" (ie: <code>java.lang.Object[][]</code>)
311      * or "<code>int</code>" for "<code>[[[I</code>" (ie: <code>int[][][]</code>).
312      * <p>
313      * <dd><dl><dt><b>XSLT parameters:</b>
314      * <dd><b>[Mandatory/AVT]</b> the Java type in the "Java signature format".
315      * </dl></dd>
316      * <p>
317      * @param context automatically passed by the xalan extension mechanism.
318      * @param type the Java type in the "Java signature format".
319      * @return the stripped type.
320      * @throws org.apache.xml.utils.WrappedRuntimeException errors (...).
321      */

322     public static String JavaDoc stripType(ExpressionContext context, String JavaDoc type) {
323         type = stripTypeDims(context, type);
324         int iLastDot = type.lastIndexOf('.');
325
326         return (iLastDot != -1) ? type.substring(iLastDot + 1) : type;
327     }
328
329     /**
330      * Strips a type definition (see {@link java.lang.Class#getName()
331      * Java signature format}), removing only array dimensions information.
332      * <p>
333      * <table class="usage">
334      * <tr><td class="usage"><pre>
335      *
336      * &lt;xsl:value-of select="jcx:stripTypeDims('[[I')"/&gt;
337      * </pre></td></tr></table>
338      * <p>
339      * For example, the function will return "<code>java.lang.Object</code>" for
340      * "<code>[LLjava.lang.Object;</code>" (ie: <code>java.lang.Object[][]</code>)
341      * or "<code>int</code>" for "<code>[[[I</code>" (ie: <code>int[][][]</code>).
342      * <p>
343      * <dd><dl><dt><b>XSLT parameters:</b>
344      * <dd><b>[Mandatory/AVT]</b> the Java type in the "Java signature format".
345      * </dl></dd>
346      * <p>
347      * @param context automatically passed by the xalan extension mechanism.
348      * @param type <b>[AVT]</b> - a type definition in the "Java signature format".
349      * @return the stripped type.
350      * @throws org.apache.xml.utils.WrappedRuntimeException errors (...).
351      */

352     public static String JavaDoc stripTypeDims(ExpressionContext context, String JavaDoc type) {
353         type = org.ejen.util.XSLUtil.evaluate(context, type);
354         if (!type.startsWith("[")) {
355             return type;
356         }
357         char c = type.charAt(1);
358
359         switch (c) {
360         case 'B':
361             return "byte";
362
363         case 'C':
364             return "char";
365
366         case 'D':
367             return "double";
368
369         case 'F':
370             return "float";
371
372         case 'I':
373             return "int";
374
375         case 'J':
376             return "long";
377
378         case 'S':
379             return "short";
380
381         case 'Z':
382             return "boolean";
383
384         case 'L':
385             break;
386
387         default:
388             throw new RuntimeException JavaDoc("Unknown type signature: " + c);
389         }
390         
391         int b = 2;
392         int e = type.length() - 1;
393
394         while (b < e && type.charAt(b) == c) {
395             ++b;
396         }
397         return type.substring(b, e);
398     }
399
400     /**
401      * Returns type array dimensions in the form of "<code>[][][]...</code>".
402      * <p>
403      * <table class="usage">
404      * <tr><td class="usage"><pre>
405      *
406      * &lt;xsl:value-of select="jcx:stripTypeDims('[[I')"/&gt;
407      * </pre></td></tr></table>
408      * <p>
409      * For example, the function will return "<code>[][]</code>" for
410      * "<code>[LLjava.lang.Object;</code>" (ie: <code>java.lang.Object[][]</code>)
411      * or "<code>[][][]</code>" for "<code>[[[I</code>" (ie: <code>int[][][]</code>).
412      * <p>
413      * <dd><dl><dt><b>XSLT parameters:</b>
414      * <dd><b>[Mandatory/AVT]</b> the Java type in the "Java signature format".
415      * </dl></dd>
416      * <p>
417      * @param context automatically passed by the xalan extension mechanism.
418      * @param type <b>[AVT]</b> - a type definition in the "Java signature format".
419      * @return the type array dimensions (may be "").
420      * @throws org.apache.xml.utils.WrappedRuntimeException errors (...).
421      */

422     public static String JavaDoc dimsOfType(ExpressionContext context, String JavaDoc type) {
423         type = org.ejen.util.XSLUtil.evaluate(context, type);
424         if (!type.startsWith("[")) {
425             return "";
426         }
427         StringBuffer JavaDoc dims = new StringBuffer JavaDoc(DIM_STR);
428         char c = type.charAt(1);
429         int l = type.length();
430
431         for (int i = 2; i < l && type.charAt(i) == c; i++) {
432             dims.append(DIM_STR);
433         }
434         return dims.toString();
435     }
436
437     /**
438      * Returns type package information.
439      * <p>
440      * <table class="usage">
441      * <tr><td class="usage"><pre>
442      *
443      * &lt;xsl:value-of select="jcx:stripTypeDims('[[java.lang.Object;')"/&gt;
444      * </pre></td></tr></table>
445      * <p>
446      * For example, the function will return "<code>java.lang</code>" for
447      * "<code>[LLjava.lang.Object;</code>" (ie: <code>java.lang.Object[][]</code>)
448      * or "" for "<code>[[[I</code>" (ie: <code>int[][][]</code>).
449      * <p>
450      * <dd><dl><dt><b>XSLT parameters:</b>
451      * <dd><b>[Mandatory/AVT]</b> the Java type in the "Java signature format".
452      * </dl></dd>
453      * <p>
454      * @param context automatically passed by the xalan extension mechanism.
455      * @param type <b>[AVT]</b> - a type definition in the "Java signature format".
456      * @return the type package (may be "").
457      * @throws org.apache.xml.utils.WrappedRuntimeException errors (...).
458      */

459     public static String JavaDoc packageOfType(ExpressionContext context, String JavaDoc type) {
460         type = stripTypeDims(context, type);
461         int iLastDot = type.lastIndexOf('.');
462
463         return (iLastDot != -1) ? type.substring(0, iLastDot) : "";
464     }
465 }
466
Popular Tags