KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > archive > wizard > EJBClassFile


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.modules.j2ee.archive.wizard;
21
22 import java.nio.ByteBuffer JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.nio.channels.ReadableByteChannel JavaDoc;
25 import java.util.Set JavaDoc;
26 import java.util.HashSet JavaDoc;
27
28 /**
29  *
30  * @author ludo, from jerome's code
31  */

32
33
34 /**
35  * This class is encapsulating binary .class file information as
36  * defined at
37  * http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
38  *
39  * This is used by the annotation frameworks to quickly scan .class files
40  * for the presence of annotations. This avoid the annotation framework having
41  * to load each .class file in the class loader.
42  *
43  */

44 class EJBClassFile {
45     
46     private ByteBuffer JavaDoc header;
47     private EJBConstantPoolInfo constantPoolInfo = new EJBConstantPoolInfo();
48     
49     /** Creates a new instance of ClassFile */
50     EJBClassFile() {
51         header = ByteBuffer.allocate(12000);
52     }
53     
54     
55     
56     /**
57      * Read the input channel and initialize instance data
58      * structure.
59      */

60     boolean containsAnnotation(ReadableByteChannel JavaDoc in, long size) throws IOException JavaDoc {
61         /**
62          * this is the .class file layout
63          *
64          * ClassFile {
65          * u4 magic;
66          * u2 minor_version;
67          * u2 major_version;
68          * u2 constant_pool_count;
69          * cp_info constant_pool[constant_pool_count-1];
70          * u2 access_flags;
71          * u2 this_class;
72          * u2 super_class;
73          * u2 interfaces_count;
74          * u2 interfaces[interfaces_count];
75          * u2 fields_count;
76          * field_info fields[fields_count];
77          * u2 methods_count;
78          * method_info methods[methods_count];
79          * u2 attributes_count;
80          * attribute_info attributes[attributes_count];
81          * }
82          **/

83         boolean retVal = false;
84         if (null != in) {
85             header.clear();
86             if (size!=-1 && size>header.capacity()) {
87                 // time to expand...
88
header = ByteBuffer.allocate((int) size);
89             }
90             long read = (long) in.read(header);
91             if (size!=-1 && read!=size) {
92                 return false;
93             }
94             header.rewind();
95             
96             if (header.getInt()!=magic) {
97                 return false;
98             }
99             
100             majorVersion = header.getShort();
101             minorVersion = header.getShort();
102             int constantPoolSize = header.getShort();
103             
104             retVal = constantPoolInfo.containsAnnotation(constantPoolSize, header);
105         }
106         return retVal;
107         
108     }
109     
110     public short majorVersion;
111     public short minorVersion;
112     public EJBConstantPoolInfo constantPool[];
113     public short accessFlags;
114     public EJBConstantPoolInfo thisClass;
115     public EJBConstantPoolInfo superClass;
116     public EJBConstantPoolInfo interfaces[];
117 // boolean isValidClass = false;
118

119     private static final int magic = 0xCAFEBABE;
120     
121     public static final int ACC_PUBLIC = 0x1;
122     public static final int ACC_PRIVATE = 0x2;
123     public static final int ACC_PROTECTED = 0x4;
124     public static final int ACC_STATIC = 0x8;
125     public static final int ACC_FINAL = 0x10;
126     public static final int ACC_SYNCHRONIZED = 0x20;
127     public static final int ACC_THREADSAFE = 0x40;
128     public static final int ACC_TRANSIENT = 0x80;
129     public static final int ACC_NATIVE = 0x100;
130     public static final int ACC_INTERFACE = 0x200;
131     public static final int ACC_ABSTRACT = 0x400;
132     
133     
134     static class EJBConstantPoolInfo {
135         
136         byte[] bytes = new byte[Short.MAX_VALUE];
137         
138         private Set JavaDoc<String JavaDoc> annotations=null;
139         
140         
141         public EJBConstantPoolInfo() {
142             annotations = new HashSet JavaDoc();
143             annotations.add("Ljavax/ejb/Stateless;");
144             annotations.add("Ljavax/ejb/Stateful;");
145             annotations.add("Ljavax/ejb/MessageDriven;");
146         }
147         
148         /**
149          * Read the input channel and initialize instance data
150          * structure.
151          */

152         public boolean containsAnnotation(int constantPoolSize, final ByteBuffer JavaDoc buffer) throws IOException JavaDoc {
153             
154             for (int i=1;i<constantPoolSize;i++) {
155                 final byte type = buffer.get();
156                 switch(type) {
157                     case ASCIZ:
158                     case UNICODE:
159                         final short length = buffer.getShort();
160                         if (length<0 || length>Short.MAX_VALUE) {
161                             return true;
162                         }
163                         buffer.get(bytes, 0, length);
164                     /* to speed up the process, I am comparing the first few
165                      * bytes to Ljava since all annotations are in the java
166                      * package, the reduces dramatically the number or String
167                      * construction
168                      */

169                         if (bytes[0]=='L' && bytes[1]=='j' && bytes[2]=='a') {
170                             String JavaDoc stringValue;
171                             if (type==ASCIZ) {
172                                 stringValue = new String JavaDoc(bytes, 0, length,"US-ASCII");
173                             } else {
174                                 stringValue = new String JavaDoc(bytes, 0, length);
175                             }
176                             
177                             if (annotations.contains(stringValue)) {
178                                 return true;
179                             }
180                             
181                             
182                         }
183                         break;
184                     case CLASS:
185                     case STRING:
186                         buffer.getShort();
187                         break;
188                     case FIELDREF:
189                     case METHODREF:
190                     case INTERFACEMETHODREF:
191                     case INTEGER:
192                     case FLOAT:
193                         buffer.position(buffer.position()+4);
194                         break;
195                     case LONG:
196                     case DOUBLE:
197                         buffer.position(buffer.position()+8);
198                         // for long, and double, they use 2 constantPool
199
i++;
200                         break;
201                     case NAMEANDTYPE:
202                         buffer.getShort();
203                         buffer.getShort();
204                         break;
205                     default:
206                         ///////ludo DOLUtils.getDefaultLogger().severe("Unknow type constant pool " + type + " at position" + i);
207
break;
208                 }
209             }
210             return false;
211         }
212         
213         
214         public static final byte CLASS = 7;
215         public static final int FIELDREF = 9;
216         public static final int METHODREF = 10;
217         public static final int STRING = 8;
218         public static final int INTEGER = 3;
219         public static final int FLOAT = 4;
220         public static final int LONG = 5;
221         public static final int DOUBLE = 6;
222         public static final int INTERFACEMETHODREF = 11;
223         public static final int NAMEANDTYPE = 12;
224         public static final int ASCIZ = 1;
225         public static final int UNICODE = 2;
226         
227     }
228 }
229
Popular Tags