KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > enhance > Enhancer


1 /*
2  * Copyright 2004 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: Enhancer.java,v 1.9 2004/01/25 22:30:58 jackknifebarber Exp $
9  */

10
11 package com.triactive.jdo.enhance;
12
13 import com.triactive.jdo.model.Types;
14 import com.triactive.jdo.util.XMLHelper;
15 import java.io.File JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStream JavaDoc;
18 import java.io.OutputStream JavaDoc;
19 import java.io.FileOutputStream JavaDoc;
20 import java.io.PrintWriter JavaDoc;
21 import java.util.Arrays JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28 import javax.jdo.spi.PersistenceCapable;
29 import javax.xml.parsers.DocumentBuilder JavaDoc;
30 import javax.xml.parsers.ParserConfigurationException JavaDoc;
31 import org.w3c.dom.Element JavaDoc;
32 import org.w3c.dom.NodeList JavaDoc;
33 import org.xml.sax.SAXException JavaDoc;
34
35
36 /**
37  * Abstract class for JDO bytecode enhancement utility. The expected
38  * command-line syntax is:
39  * <pre><blockquote>
40  * java com.triactive.jdo.enhance.Enhancer JDO-metadata-filename ...
41  * </blockquote></pre>
42  *
43  * Every class listed in the given metadata file(s) should be made persistence
44  * capable via bytecode enhancement.
45  *
46  * This class must be subclassed with an implementation that uses a working
47  * bytecode enhancer. The key method that needs to be overridden and implemented
48  * is callExternalEnhancer(String[]).
49  *
50  *
51  * @version $Revision: 1.9 $
52  */

53
54 public abstract class Enhancer
55 {
56
57     /**
58      * Protected constructor to prevent outside instantiation.
59      */

60     protected Enhancer() {}
61
62     protected int enhance(List JavaDoc classNames) throws Exception JavaDoc
63     {
64         /* Remove from the list any that are already enhanced. */
65         ArrayList JavaDoc l = new ArrayList JavaDoc(classNames);
66         Iterator JavaDoc i = l.iterator();
67
68         while (i.hasNext())
69         {
70             if (isEnhanced((String JavaDoc)i.next()))
71                 i.remove();
72         }
73
74         if (l.isEmpty())
75             return 0;
76         else
77             return callExternalEnhancer((String JavaDoc[])l.toArray(new String JavaDoc[l.size()]));
78     }
79
80
81     /**
82      * Returns true if the named class has already been enhanced. This method
83      * returns false if the enhancement status is unknown because the class
84      * cannot be loaded.
85      *
86      * @param className The name of the class to test.
87      *
88      * @return <tt>true</tt> if the class is enhanced,
89      * <tt>false</tt> otherwise.
90      */

91
92     private boolean isEnhanced(String JavaDoc className)
93     {
94         Class JavaDoc c;
95
96         try
97         {
98             c = Class.forName(className);
99         }
100         catch (Throwable JavaDoc t)
101         {
102             /*
103              * A class that fails to load is deemed to be unenhanced. This
104              * often happens when attempting to load an enhanced subclass whose
105              * superclass is unenhanced.
106              */

107             //t.printStackTrace();
108
return false;
109         }
110
111         return Types.isEnhancedClass(c);
112     }
113
114
115     /**
116      * Called by enhance() to enhance a list of classes.
117      * Subclasses implement this method to invoke the 3rd-party class enhancer.
118      *
119      * @param classNames The list of class names to be enhanced
120      */

121     protected abstract int callExternalEnhancer(String JavaDoc[] classNames) throws Exception JavaDoc;
122
123
124     /**
125      * Returns a list of all classes declared in the given metadata files,
126      * ordered such that all superclasses occur before their subclasses.
127      *
128      * @param metaDataFileNames The list of JDO metadata file names.
129      *
130      * @return An ordered list of class name strings.
131      *
132      * @exception IOException
133      * If any I/O error occurs.
134      * @exception ParserConfigurationXException
135      * If an XML document builder cannot be created.
136      * @exception SAXException
137      * If any parse error occurs.
138      */

139
140     protected static List JavaDoc getOrderedClassNames(String JavaDoc[] metaDataFileNames)
141         throws IOException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc
142     {
143         HashMap JavaDoc superclassesByClass = new HashMap JavaDoc();
144         final DocumentBuilder JavaDoc db = XMLHelper.getDocumentBuilder();
145
146         for (int i = 0; i < metaDataFileNames.length; ++i)
147         {
148             Element JavaDoc docElement = db.parse(new File JavaDoc(metaDataFileNames[i])).getDocumentElement();
149
150             NodeList JavaDoc nodes = docElement.getElementsByTagName("class");
151
152             for (int j = 0; j < nodes.getLength(); ++j)
153             {
154                 Element JavaDoc clsElement = (Element JavaDoc)nodes.item(j);
155                 String JavaDoc packageName = ((Element JavaDoc)clsElement.getParentNode()).getAttribute("name");
156                 String JavaDoc className = packageName + '.' + clsElement.getAttribute("name");
157                 String JavaDoc superclassName = clsElement.getAttribute("persistence-capable-superclass");
158
159                 if (superclassName.length() == 0)
160                     superclassName = null;
161                 else if (superclassName.indexOf('.') < 0)
162                     superclassName = packageName + '.' + superclassName;
163
164                 superclassesByClass.put(className, superclassName);
165             }
166         }
167
168         int numClasses = superclassesByClass.size();
169         ArrayList JavaDoc orderedNames = new ArrayList JavaDoc(numClasses);
170         ArrayList JavaDoc sortedNames = new ArrayList JavaDoc(numClasses);
171
172         sortedNames.addAll(superclassesByClass.keySet());
173         Collections.sort(sortedNames);
174
175         Iterator JavaDoc i = sortedNames.iterator();
176
177         while (i.hasNext())
178             addClass(orderedNames, (String JavaDoc)i.next(), superclassesByClass);
179
180         return orderedNames;
181     }
182
183
184     private static void addClass(List JavaDoc names, String JavaDoc className, Map JavaDoc superclassesByClass)
185     {
186         String JavaDoc superclassName = (String JavaDoc)superclassesByClass.get(className);
187
188         if (superclassName != null)
189             addClass(names, superclassName, superclassesByClass);
190
191         if (!names.contains(className))
192             names.add(className);
193     }
194
195
196     /**
197      * Writes out the given list of classes to a file.
198      */

199     protected static void writeClassListFile(String JavaDoc filename, List JavaDoc classNames) throws IOException JavaDoc
200     {
201         PrintWriter JavaDoc pw = new PrintWriter JavaDoc(new FileOutputStream JavaDoc(new File JavaDoc(filename)), true);
202
203         try
204         {
205             Iterator JavaDoc i = classNames.iterator();
206
207             while (i.hasNext())
208                 pw.println(i.next());
209         }
210         finally
211         {
212             pw.flush();
213             pw.close();
214         }
215     }
216 }
217
Popular Tags