KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > nbbuild > NbEnhanceClass


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.nbbuild;
21
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import org.apache.tools.ant.*;
32 import org.apache.tools.ant.types.*;
33
34 /**
35  * @author Jaroslav Tulach
36  */

37 public class NbEnhanceClass extends Task {
38
39     /* Path to library containing the patch method */
40     private Path patchPath;
41     public Path createClasspath() {
42         if (patchPath == null) {
43             patchPath = new Path(getProject());
44         }
45         return patchPath.createPath();
46     }
47     
48     /* Name of class with patch method */
49     private String JavaDoc patchClass = "org.netbeans.PatchByteCode";
50     public void setPatchClass (String JavaDoc f) {
51         patchClass = f;
52     }
53     
54     /** Name of the method to call. Must have signature byte[] x(byte[], Map)
55      */

56     private String JavaDoc enhanceMethod = "enhanceClass";
57     public void setEnhanceMethod (String JavaDoc f) {
58         enhanceMethod = f;
59     }
60     
61     /* Base dir to find classes relative to */
62     private File JavaDoc basedir;
63     public void setBasedir (File JavaDoc f) {
64         basedir = f;
65     }
66     
67     /* The class to change its super class and the value of the super class.
68      */

69     public static class Patch {
70         String JavaDoc clazz;
71         String JavaDoc nbSuperClass;
72         String JavaDoc nbImplements;
73         List JavaDoc<Member> members;
74         
75         
76         /** Class in form of java/lang/Object */
77         public void setClass (String JavaDoc s) {
78             clazz = s;
79         }
80         /** Class in form of java/lang/Object */
81         public void setSuper (String JavaDoc s) {
82             nbSuperClass = s;
83         }
84         public void setImplements (String JavaDoc s) {
85             nbImplements = s;
86         }
87         
88         public Object JavaDoc createMember () {
89             Member m = new Member();
90             if (members == null) {
91                 members = new ArrayList JavaDoc<Member>();
92             }
93             members.add (m);
94             return m;
95         }
96         
97         public static final class Member extends Object JavaDoc {
98             String JavaDoc name;
99             String JavaDoc rename;
100             
101             public void setName (String JavaDoc s) {
102                 name = s;
103             }
104             
105             public void setRename (String JavaDoc s) {
106                 rename = s;
107             }
108         }
109     }
110     private List JavaDoc<Patch> patches = new ArrayList JavaDoc<Patch>();
111     public Patch createPatch () {
112         Patch n = new Patch ();
113         patches.add(n);
114         return n;
115     }
116     
117     
118     public void execute() throws BuildException {
119         if (basedir == null) {
120             throw new BuildException ("Attribute basedir must be specified");
121         }
122         
123         if (patches.isEmpty()) {
124             // no work
125
return;
126         }
127         
128         //
129
// Initialize the method
130
//
131

132         ClassLoader JavaDoc cl = new AntClassLoader(getProject(), patchPath, false);
133         
134         Method JavaDoc m;
135         try {
136             Class JavaDoc<?> c = cl.loadClass(patchClass);
137             m = c.getMethod(enhanceMethod, byte[].class, Map JavaDoc.class);
138             if (m.getReturnType() != byte[].class) {
139                 throw new BuildException ("Method does not return byte[]: " + m);
140             }
141         } catch (Exception JavaDoc ex) {
142             throw new BuildException ("Cannot initialize class " + patchClass + " and method " + enhanceMethod, ex);
143         }
144             
145         /*
146         try {
147             log ("Testing method " + m);
148             byte[] res = (byte[])m.invoke (null, new Object[] { new byte[0], "someString" });
149         } catch (Exception ex) {
150             throw new BuildException ("Exception during test invocation of the method", ex);
151         }
152          */

153             
154         //
155
// Ok we have the method and we can do the patching
156
//
157

158         for (Patch p : patches) {
159             if (p.clazz == null) {
160                 throw new BuildException ("Attribute class must be specified");
161             }
162             
163             File JavaDoc f = new File JavaDoc (basedir, p.clazz + ".class");
164             if (!f.exists ()) {
165                 throw new BuildException ("File " + f + " for class " + p.clazz + " does not exists");
166             }
167             
168             byte[] arr = new byte[(int)f.length()];
169             try {
170                 FileInputStream JavaDoc is = new FileInputStream JavaDoc (f);
171                 if (arr.length != is.read (arr)) {
172                     throw new BuildException ("Not all bytes read");
173                 }
174                 is.close ();
175             } catch (IOException JavaDoc ex) {
176                 throw new BuildException ("Cannot read file " + f, ex);
177             }
178             
179             List JavaDoc<String JavaDoc> members = null;
180             List JavaDoc<String JavaDoc> rename = null;
181             if (p.members != null) {
182                 members = new ArrayList JavaDoc<String JavaDoc>();
183                 for (Patch.Member mem : p.members) {
184                     members.add (mem.name);
185                     
186                     if (mem.rename != null) {
187                         if (rename == null) {
188                             rename = new ArrayList JavaDoc<String JavaDoc>();
189                         }
190                         rename.add (mem.name);
191                         rename.add (mem.rename);
192                     }
193                 }
194             }
195                 
196              
197             byte[] out;
198             try {
199                 Map JavaDoc<String JavaDoc,Object JavaDoc> args = new HashMap JavaDoc<String JavaDoc,Object JavaDoc>();
200                 if (p.nbSuperClass != null) {
201                     args.put ("netbeans.superclass", p.nbSuperClass);
202                 }
203                 if (p.nbImplements != null) {
204                     args.put ("netbeans.interfaces", p.nbImplements);
205                 }
206                 if (members != null) {
207                     args.put ("netbeans.public", members);
208                 }
209                 if (rename != null) {
210                     args.put ("netbeans.rename", rename);
211                 }
212                 
213                 log("Patching " + p.clazz + " with arguments " + args, Project.MSG_VERBOSE);
214                 
215                 out = (byte[]) m.invoke(null, arr, args);
216                 if (out == null) {
217                     // no patching needed
218
continue;
219                 }
220             } catch (Exception JavaDoc ex) {
221                 throw new BuildException (ex);
222             }
223
224             if (p.nbSuperClass != null) {
225                 log ("Enhanced " + f + " to have alternate superclass " + p.nbSuperClass + " and be public");
226             } else {
227                 log ("Enhanced " + f + " to be public");
228             }
229             
230             try {
231                 FileOutputStream JavaDoc os = new FileOutputStream JavaDoc (f);
232                 os.write (out);
233                 os.close ();
234             } catch (IOException JavaDoc ex) {
235                 throw new BuildException ("Cannot overwrite file " + f, ex);
236             }
237         }
238     }
239     
240 }
241
Popular Tags