1 /* ClassWrapper.java - wrap ASM class objects
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.classpath.tools.javah;
41 import java.io.ByteArrayOutputStream;
42 import java.io.IOException;
43 import java.io.PrintStream;
44 import java.lang.reflect.Modifier;
45 import java.util.ArrayList;
46 import java.util.HashSet;
47 import java.util.Iterator;
49 import org.objectweb.asm.tree.ClassNode;
50 import org.objectweb.asm.tree.FieldNode;
51 import org.objectweb.asm.tree.MethodNode;
53 public class ClassWrapper
58 ClassWrapper superClass;
60 ArrayList interfaceClasses;
62 // The virtual table for this class.
65 // A set of all the bridge method targets we've found.
66 HashSet bridgeTargets;
68 // A set of all the method names in this class.
69 HashSet methodNames = new HashSet();
71 public ClassWrapper(Main classpath)
73 this.classpath = classpath;
76 public boolean hasNativeMethod()
78 Iterator i = methods.iterator();
81 MethodNode method = (MethodNode) i.next();
82 if (Modifier.isNative(method.access))
88 public boolean isThrowable() throws IOException
91 ClassWrapper self = this;
94 if (self.name.equals("java/lang/Throwable"))
96 self = self.superClass;
101 private void linkSupers() throws IOException
103 if (superName == null)
105 // Object, do nothing.
108 if (superClass == null)
110 superClass = classpath.getClass(superName);
111 assert interfaceClasses == null;
112 interfaceClasses = new ArrayList();
113 for (int i = 0; i < interfaces.size(); ++i)
115 String ifname = (String) interfaces.get(i);
116 ClassWrapper iface = classpath.getClass(ifname);
118 interfaceClasses.add(iface);
121 superClass.linkSupers();
124 private int findSlot(MethodNode method)
126 for (int i = vtable.size() - 1; i >= 0; --i)
128 MethodNode base = (MethodNode) vtable.get(i);
129 if (MethodHelper.overrides(method, base))
135 private void addInterfaceMethods(ClassWrapper iface)
137 Iterator i = iface.methods.iterator();
140 MethodNode im = (MethodNode) i.next();
141 int slot = findSlot(im);
145 // Also add it to our local methods.
149 addInterfaces(iface);
152 private void addInterfaces(ClassWrapper base)
154 if (base.interfaceClasses == null)
156 Iterator i = base.interfaceClasses.iterator();
159 ClassWrapper iface = (ClassWrapper) i.next();
160 addInterfaceMethods(iface);
164 private void addLocalMethods()
166 Iterator i = methods.iterator();
169 MethodNode meth = (MethodNode) i.next();
170 methodNames.add(meth.name);
171 if (Modifier.isStatic(meth.access))
173 int slot = findSlot(meth);
177 vtable.set(slot, meth);
181 private void makeVtable() throws IOException
185 if (superClass != null)
187 superClass.makeVtable();
188 vtable = new ArrayList(superClass.vtable);
189 bridgeTargets = new HashSet(superClass.bridgeTargets);
194 vtable = new ArrayList();
195 bridgeTargets = new HashSet();
200 // Make a set of all the targets of bridge methods.
201 // We rename bridge methods to avoid problems with C++.
202 Iterator i = methods.iterator();
205 MethodNode m = (MethodNode) i.next();
206 String desc = MethodHelper.getBridgeTarget(m);
208 bridgeTargets.add(m.name + desc);
212 private void printFields(CniPrintStream out)
214 Iterator i = fields.iterator();
215 ClassWrapper self = superClass;
218 FieldNode f = (FieldNode) i.next();
219 boolean hasMethodName = methodNames.contains(f.name);
220 if (FieldHelper.print(out, f, self, hasMethodName))
225 private void printMethods(CniPrintStream out) throws IOException
229 // A given method is either static, overrides a super method, or
230 // is already in vtable order.
231 Iterator i = methods.iterator();
234 MethodNode m = (MethodNode) i.next();
235 boolean isTarget = bridgeTargets.contains(m.name + m.desc);
236 MethodHelper.print(out, m, this, isTarget);
240 private void printTextList(PrintStream out, int what, ArrayList textList)
242 if (textList == null)
244 Iterator i = textList.iterator();
245 boolean first = true;
248 Text item = (Text) i.next();
249 if (item.type == what)
256 if (what == Text.FRIEND)
257 out.print(" friend ");
258 out.println(item.text);
263 public void print(CniPrintStream out)
265 out.print("::" + name.replaceAll("/", "::"));
268 // This prints the body of a class to a CxxPrintStream.
269 private void printContents(CniPrintStream out, ArrayList textList)
272 printTextList(out, Text.PREPEND, textList);
276 // Don't use our print() -- we don't want the leading "::".
277 out.print(name.replaceAll("/", "::"));
278 if (superClass != null)
280 out.print(" : public ");
281 superClass.print(out);
286 printTextList(out, Text.ADD, textList);
289 // Note: methods must come first, as we build the list
290 // of method names while printing them.
294 out.setModifiers(Modifier.PUBLIC);
295 out.println(" static ::java::lang::Class class$;");
297 printTextList(out, Text.FRIEND, textList);
300 if (Modifier.isInterface(access))
301 out.print(" __attribute__ ((java_interface))");
304 printTextList(out, Text.APPEND, textList);
307 public void printFully(PrintStream out) throws IOException
311 ArrayList textList = classpath.getClassTextList(name);
313 out.println("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-");
315 String xname = "__" + name.replaceAll("/", "_") + "__";
316 out.println("#ifndef " + xname);
317 out.println("#define " + xname);
319 out.println("#pragma interface");
322 if (superClass != null)
324 out.print("#include <");
325 out.print(superName);
329 // Write the body of the stream here. This lets
330 // us emit the namespaces without a second pass.
331 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
332 CniPrintStream cxxOut = new CniPrintStream(bytes);
333 cxxOut.addClass(this);
334 printContents(cxxOut, textList);
335 cxxOut.printNamespaces(out);
339 out.println("#endif // " + xname);
342 public String toString()