001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.satsa.jcrmic.classfile;
028:
029: import java.io.*;
030:
031: import com.sun.satsa.jcrmic.classfile.attributes.JAttribute;
032: import com.sun.satsa.jcrmic.classfile.constants.JConstantPool;
033:
034: /**
035: * This class represents a Java Class.
036: */
037: public class JClass {
038:
039: /**
040: * Constant for interface flag.
041: */
042: public static final int ACC_INTERFACE = 0x0200;
043:
044: /**
045: * Access flags.
046: */
047: private int access_flags;
048:
049: /**
050: * Class name.
051: */
052: private String class_name;
053:
054: /**
055: * Super class name.
056: */
057: private String super _class_name;
058:
059: /**
060: * Array of declared methods.
061: */
062: private JMethod[] methods;
063:
064: /**
065: * Names of implemented interfaces.
066: */
067: private String[] interface_names;
068:
069: /**
070: * 'Remote' flag.
071: */
072: private boolean remote;
073:
074: /**
075: * 'Verified' flag.
076: */
077: private boolean verified;
078:
079: /**
080: * Super class.
081: */
082: private JClass super Class;
083:
084: /**
085: * Implemented interfaces.
086: */
087: private JClass[] interfaces;
088:
089: /**
090: * Class loader.
091: */
092: private Loader classes;
093:
094: /**
095: * Constructor.
096: * @param classes class loader
097: */
098: public JClass(Loader classes) {
099: this .classes = classes;
100: }
101:
102: /**
103: * Parse and resolve Java class.
104: * @param dis input stream
105: * @throws IOException if I/O error occurs
106: */
107: public void parse(DataInputStream dis) throws IOException {
108:
109: dis.readInt(); // magic
110:
111: dis.readUnsignedShort(); // minor_version
112: dis.readUnsignedShort(); // major_version
113:
114: JConstantPool constant_pool = new JConstantPool(dis
115: .readUnsignedShort());
116: constant_pool.parse(dis);
117:
118: access_flags = dis.readUnsignedShort();
119: int this _class_index = dis.readUnsignedShort();
120: int super _class_index = dis.readUnsignedShort();
121:
122: int[] interface_indexes = new int[dis.readUnsignedShort()];
123:
124: for (int i = 0; i < interface_indexes.length; i++) {
125: interface_indexes[i] = dis.readUnsignedShort();
126: }
127:
128: int field_count = dis.readUnsignedShort();
129: for (int i = 0; i < field_count; i++) {
130: dis.readUnsignedShort(); // access_flags
131: dis.readUnsignedShort(); // name_index
132: dis.readUnsignedShort(); // descriptor_index
133: int attrib_count = dis.readUnsignedShort();
134: for (int k = 0; k < attrib_count; k++) {
135: int index = dis.readUnsignedShort();
136: JAttribute.create(constant_pool, index).parse(dis);
137: }
138: }
139:
140: methods = new JMethod[dis.readUnsignedShort()];
141: for (int i = 0; i < methods.length; i++) {
142: methods[i] = new JMethod(constant_pool);
143: methods[i].parse(dis);
144: }
145:
146: int attribute_count = dis.readUnsignedShort();
147: for (int i = 0; i < attribute_count; i++) {
148: int index = dis.readUnsignedShort();
149: JAttribute.create(constant_pool, index).parse(dis);
150: }
151:
152: // resolve
153:
154: class_name = constant_pool.getConstantClass(this _class_index)
155: .getClassName();
156:
157: if (super _class_index != 0) {
158: super _class_name = constant_pool.getConstantClass(
159: super _class_index).getClassName();
160: } else {
161: super _class_name = null;
162: }
163:
164: interface_names = new String[interface_indexes.length];
165: for (int i = 0; i < interface_names.length; i++) {
166: interface_names[i] = constant_pool.getConstantClass(
167: interface_indexes[i]).getClassName();
168: }
169: }
170:
171: /**
172: * Load all related classes.
173: * @return true if successfull
174: */
175: public boolean update() {
176:
177: if (class_name.equals("java/rmi/Remote")) {
178: setRemote();
179: }
180:
181: String name = super _class_name;
182:
183: if (name != null) {
184:
185: if (!classes.loadClass(name))
186: return false;
187:
188: super Class = classes.getClass(name);
189:
190: if (super Class.isRemote())
191: setRemote();
192: }
193:
194: interfaces = new JClass[interface_names.length];
195:
196: for (int i = 0; i < interface_names.length; i++) {
197:
198: if (!classes.loadClass(interface_names[i]))
199: return false;
200:
201: interfaces[i] = classes.getClass(interface_names[i]);
202:
203: if (interfaces[i].isRemote())
204: setRemote();
205: }
206:
207: JMethod[] methods = getMethods();
208:
209: for (int i = 0; i < methods.length; i++) {
210:
211: String[] exceptions = methods[i].getExceptionsThrown();
212: if (exceptions != null) {
213: for (int j = 0; j < exceptions.length; j++) {
214: if (!classes.loadClass(exceptions[j])) {
215: return false;
216: }
217: }
218: }
219: }
220:
221: return true;
222: }
223:
224: /**
225: * Returns super class.
226: * @return super class
227: */
228: public JClass getSuperClass() {
229:
230: return super Class;
231: }
232:
233: /**
234: * Returns implemented interfaces.
235: * @return implemented interfaces
236: */
237: public JClass[] getInterfaces() {
238:
239: return interfaces;
240: }
241:
242: /**
243: * Returns class name.
244: * @return class name
245: */
246: public String getClassName() {
247: return class_name;
248: }
249:
250: /**
251: * Returns methods declared by class.
252: * @return methods declared by class
253: */
254: public JMethod[] getMethods() {
255: return methods;
256: }
257:
258: /**
259: * Check if the class is interface.
260: * @return true if the class is interface
261: */
262: public boolean isInterface() {
263: return (access_flags & ACC_INTERFACE) != 0;
264: }
265:
266: /**
267: * Set 'remote' flag.
268: */
269: public void setRemote() {
270: remote = true;
271: }
272:
273: /**
274: * Returns 'remote' flag value.
275: * @return 'remote' flag value
276: */
277: public boolean isRemote() {
278: return remote;
279: }
280:
281: /**
282: * Set 'verified' flag.
283: */
284: public void setVerified() {
285: verified = true;
286: }
287:
288: /**
289: * Returns 'verifed' flag value.
290: * @return 'verifed' flag value
291: */
292: public boolean isVerified() {
293: return verified;
294: }
295:
296: /**
297: * Verifies if the class is equal to or a sublass of specified class.
298: * @param c2 class
299: * @return true if the class is equal to or a sublass of specified class
300: */
301: public boolean isSubclass(JClass c2) {
302:
303: String name = c2.getClassName();
304:
305: JClass c1 = this ;
306:
307: while (true) {
308:
309: if (c1.getClassName().equals(name)) {
310: return true;
311: }
312:
313: c1 = c1.getSuperClass();
314:
315: if (c1 == null) {
316: return false;
317: }
318: }
319: }
320: }
|