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