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