1 package org.apache.maven.shared.dependency.analyzer.asm;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.nio.Buffer;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class ConstantPoolParser
44 {
45 public static final int HEAD = 0xcafebabe;
46
47
48 public static final byte CONSTANT_UTF8 = 1;
49
50 public static final byte CONSTANT_INTEGER = 3;
51
52 public static final byte CONSTANT_FLOAT = 4;
53
54 public static final byte CONSTANT_LONG = 5;
55
56 public static final byte CONSTANT_DOUBLE = 6;
57
58 public static final byte CONSTANT_CLASS = 7;
59
60 public static final byte CONSTANT_STRING = 8;
61
62 public static final byte CONSTANT_FIELDREF = 9;
63
64 public static final byte CONSTANT_METHODREF = 10;
65
66 public static final byte CONSTANT_INTERFACEMETHODREF = 11;
67
68 public static final byte CONSTANT_NAME_AND_TYPE = 12;
69
70 public static final byte CONSTANT_METHODHANDLE = 15;
71
72 public static final byte CONSTANT_METHOD_TYPE = 16;
73
74 public static final byte CONSTANT_INVOKE_DYNAMIC = 18;
75
76 public static final byte CONSTANT_MODULE = 19;
77
78 public static final byte CONSTANT_PACKAGE = 20;
79
80 private static final int OXF0 = 0xf0;
81
82 private static final int OXE0 = 0xe0;
83
84 private static final int OX3F = 0x3F;
85
86 static Set<String> getConstantPoolClassReferences( byte[] b )
87 {
88 return parseConstantPoolClassReferences( ByteBuffer.wrap( b ) );
89 }
90
91 static Set<String> parseConstantPoolClassReferences( ByteBuffer buf )
92 {
93 if ( buf.order( ByteOrder.BIG_ENDIAN )
94 .getInt() != HEAD )
95 {
96 return Collections.emptySet();
97 }
98 buf.getChar() ; buf.getChar();
99 Set<Integer> classes = new HashSet<Integer>();
100 Map<Integer, String> stringConstants = new HashMap<Integer, String>();
101 for ( int ix = 1, num = buf.getChar(); ix < num; ix++ )
102 {
103 byte tag = buf.get();
104 switch ( tag )
105 {
106 default:
107 throw new RuntimeException( "Unknown constant pool type '" + tag + "'" );
108 case CONSTANT_UTF8:
109 stringConstants.put( ix, decodeString( buf ) );
110 continue;
111 case CONSTANT_CLASS:
112 case CONSTANT_STRING:
113 case CONSTANT_METHOD_TYPE:
114 classes.add( (int) buf.getChar() );
115 break;
116 case CONSTANT_FIELDREF:
117 case CONSTANT_METHODREF:
118 case CONSTANT_INTERFACEMETHODREF:
119 case CONSTANT_NAME_AND_TYPE:
120 buf.getChar();
121 buf.getChar();
122 break;
123 case CONSTANT_INTEGER:
124 buf.getInt();
125 break;
126 case CONSTANT_FLOAT:
127 buf.getFloat();
128 break;
129 case CONSTANT_DOUBLE:
130 buf.getDouble();
131 ix++;
132 break;
133 case CONSTANT_LONG:
134 buf.getLong();
135 ix++;
136 break;
137 case CONSTANT_METHODHANDLE:
138 buf.get();
139 buf.getChar();
140 break;
141 case CONSTANT_INVOKE_DYNAMIC:
142 buf.getChar();
143 buf.getChar();
144 break;
145 case CONSTANT_MODULE:
146 buf.getChar();
147 break;
148 case CONSTANT_PACKAGE:
149 buf.getChar();
150 break;
151 }
152 }
153 Set<String> result = new HashSet<String>();
154 for ( Integer aClass : classes )
155 {
156 result.add( stringConstants.get( aClass ) );
157 }
158 return result;
159 }
160
161 private static String decodeString( ByteBuffer buf )
162 {
163 int size = buf.getChar();
164
165 int oldLimit = ( (Buffer) buf ).limit();
166 ( (Buffer) buf ).limit( buf.position() + size );
167 StringBuilder sb = new StringBuilder( size + ( size >> 1 ) + 16 );
168 while ( buf.hasRemaining() )
169 {
170 byte b = buf.get();
171 if ( b > 0 )
172 {
173 sb.append( (char) b );
174 }
175 else
176 {
177 int b2 = buf.get();
178 if ( ( b & OXF0 ) != OXE0 )
179 {
180 sb.append( (char) ( ( b & 0x1F ) << 6 | b2 & OX3F ) );
181 }
182 else
183 {
184 int b3 = buf.get();
185 sb.append( (char) ( ( b & 0x0F ) << 12 | ( b2 & OX3F ) << 6 | b3 & OX3F ) );
186 }
187 }
188 }
189 ( (Buffer) buf ).limit( oldLimit );
190 return sb.toString();
191 }
192 }