001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200;
018:
019: public class AttributeLayout implements IMatcher {
020:
021: public static final String ACC_ABSTRACT = "ACC_ABSTRACT"; //$NON-NLS-1$
022: public static final String ACC_ANNOTATION = "ACC_ANNOTATION"; //$NON-NLS-1$
023: public static final String ACC_ENUM = "ACC_ENUM"; //$NON-NLS-1$
024: public static final String ACC_FINAL = "ACC_FINAL"; //$NON-NLS-1$
025: public static final String ACC_INTERFACE = "ACC_INTERFACE"; //$NON-NLS-1$
026: public static final String ACC_NATIVE = "ACC_NATIVE"; //$NON-NLS-1$
027: public static final String ACC_PRIVATE = "ACC_PRIVATE"; //$NON-NLS-1$
028: public static final String ACC_PROTECTED = "ACC_PROTECTED"; //$NON-NLS-1$
029: public static final String ACC_PUBLIC = "ACC_PUBLIC"; //$NON-NLS-1$
030: public static final String ACC_STATIC = "ACC_STATIC"; //$NON-NLS-1$
031: public static final String ACC_STRICT = "ACC_STRICT"; //$NON-NLS-1$
032: public static final String ACC_SYNCHRONIZED = "ACC_SYNCHRONIZED"; //$NON-NLS-1$
033: public static final String ACC_SYNTHETIC = "ACC_SYNTHETIC"; //$NON-NLS-1$
034: public static final String ACC_TRANSIENT = "ACC_TRANSIENT"; //$NON-NLS-1$
035: public static final String ACC_VOLATILE = "ACC_VOLATILE"; //$NON-NLS-1$
036: public static final String ATTRIBUTE_ANNOTATION_DEFAULT = "AnnotationDefault"; //$NON-NLS-1$
037: public static final String ATTRIBUTE_CLASS_FILE_VERSION = "class-file version"; //$NON-NLS-1$
038: public static final String ATTRIBUTE_CODE = "Code"; //$NON-NLS-1$
039: public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue"; //$NON-NLS-1$
040: public static final String ATTRIBUTE_DEPRECATED = "Deprecated"; //$NON-NLS-1$
041: public static final String ATTRIBUTE_ENCLOSING_METHOD = "EnclosingMethod"; //$NON-NLS-1$
042: public static final String ATTRIBUTE_EXCEPTIONS = "Exceptions"; //$NON-NLS-1$
043: public static final String ATTRIBUTE_INNER_CLASSES = "InnerClasses"; //$NON-NLS-1$
044: public static final String ATTRIBUTE_LINE_NUMBER_TABLE = "LineNumberTable"; //$NON-NLS-1$
045: public static final String ATTRIBUTE_LOCAL_VARIABLE_TABLE = "LocalVariableTable"; //$NON-NLS-1$
046: public static final String ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable"; //$NON-NLS-1$
047: public static final String ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; //$NON-NLS-1$
048: public static final String ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations"; //$NON-NLS-1$
049: public static final String ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; //$NON-NLS-1$
050: public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; //$NON-NLS-1$
051: public static final String ATTRIBUTE_SIGNATURE = "Signature"; //$NON-NLS-1$
052: public static final String ATTRIBUTE_SOURCE_FILE = "SourceFile"; //$NON-NLS-1$
053: public static final int CONTEXT_CLASS = 0;
054: public static final int CONTEXT_CODE = 3;
055: public static final int CONTEXT_FIELD = 1;
056: public static final int CONTEXT_METHOD = 2;
057: public static final String[] contextNames = {
058: "Class", "Field", "Method", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
059: "Code", }; //$NON-NLS-1$
060:
061: private static Object getValue(String layout, long value,
062: SegmentConstantPool pool) throws Pack200Exception {
063: if (layout.startsWith("R")) { //$NON-NLS-1$
064: // references
065: if (layout.indexOf('N') != -1)
066: value--;
067: if (layout.startsWith("RU")) { //$NON-NLS-1$
068: return pool.getValue(SegmentConstantPool.UTF_8, value);
069: } else if (layout.startsWith("RS")) { //$NON-NLS-1$
070: return pool.getValue(SegmentConstantPool.SIGNATURE,
071: value);
072: }
073: } else if (layout.startsWith("K")) { //$NON-NLS-1$
074: char type = layout.charAt(1);
075: switch (type) {
076: case 'S': // String
077: return pool.getValue(SegmentConstantPool.CP_STRING,
078: value);
079: case 'I': // Int (or byte or short)
080: case 'C': // Char
081: return pool.getValue(SegmentConstantPool.CP_INT, value);
082: case 'F': // Float
083: return pool.getValue(SegmentConstantPool.CP_FLOAT,
084: value);
085: case 'J': // Long
086: return pool
087: .getValue(SegmentConstantPool.CP_LONG, value);
088: case 'D': // Double
089: return pool.getValue(SegmentConstantPool.CP_DOUBLE,
090: value);
091: }
092: }
093: throw new Pack200Exception("Unknown layout encoding: " + layout);
094: }
095:
096: private int context;
097:
098: private int index;
099:
100: private final String layout;
101:
102: private long mask;
103:
104: private String name;
105: private boolean isDefault;
106: private int backwardsCallCount;
107:
108: /**
109: * Construct a default AttributeLayout
110: * (equivalent to <code>new AttributeLayout(name, context, layout, index, true);</code>)
111: * @param name
112: * @param context
113: * @param layout
114: * @param index
115: * @throws Pack200Exception
116: */
117: public AttributeLayout(String name, int context, String layout,
118: int index) throws Pack200Exception {
119: this (name, context, layout, index, true);
120: }
121:
122: public AttributeLayout(String name, int context, String layout,
123: int index, boolean isDefault) throws Pack200Exception {
124: super ();
125: this .index = index;
126: this .context = context;
127: if (index >= 0) {
128: this .mask = 1L << index;
129: } else {
130: this .mask = 0;
131: }
132: if (context != CONTEXT_CLASS && context != CONTEXT_CODE
133: && context != CONTEXT_FIELD
134: && context != CONTEXT_METHOD)
135: throw new Pack200Exception(
136: "Attribute context out of range: " + context);
137: if (layout == null) // || layout.length() == 0)
138: throw new Pack200Exception("Cannot have a null layout");
139: if (name == null || name.length() == 0)
140: throw new Pack200Exception("Cannot have an unnamed layout");
141: this .name = name;
142: this .layout = layout;
143: this .isDefault = isDefault;
144: }
145:
146: public boolean equals(Object obj) {
147: if (this == obj)
148: return true;
149: if (obj == null)
150: return false;
151: if (getClass() != obj.getClass())
152: return false;
153: final AttributeLayout other = (AttributeLayout) obj;
154: if (layout == null) {
155: if (other.layout != null)
156: return false;
157: } else if (!layout.equals(other.layout))
158: return false;
159: if (index != other.index)
160: return false;
161: if (context != other.context)
162: return false;
163: if (name == null) {
164: if (other.name != null)
165: return false;
166: } else if (!name.equals(other.name))
167: return false;
168: return true;
169: }
170:
171: public Codec getCodec() {
172: if (layout.indexOf("O") >= 0) { //$NON-NLS-1$
173: return Codec.BRANCH5;
174: } else if (layout.indexOf("P") >= 0) { //$NON-NLS-1$
175: return Codec.BCI5;
176: } else if (layout.indexOf("S") >= 0 && layout.indexOf("KS") < 0 //$NON-NLS-1$ //$NON-NLS-2$
177: && layout.indexOf("RS") < 0) { //$NON-NLS-1$
178: return Codec.SIGNED5;
179: } else if (layout.indexOf("B") >= 0) { //$NON-NLS-1$
180: return Codec.BYTE1;
181: } else {
182: return Codec.UNSIGNED5;
183: }
184: }
185:
186: public String getLayout() {
187: return layout;
188: }
189:
190: public Object getValue(long value, SegmentConstantPool pool)
191: throws Pack200Exception {
192: return getValue(layout, value, pool);
193: }
194:
195: public Object getValue(long value, String type,
196: SegmentConstantPool pool) throws Pack200Exception {
197: // TODO This really needs to be better tested, esp. the different types
198: // TODO This should have the ability to deal with RUN stuff too, and
199: // unions
200: if (layout.startsWith("KQ")) { //$NON-NLS-1$
201: if (type.equals("Ljava/lang/String;")) { //$NON-NLS-1$
202: Object value2 = getValue("KS", value, pool); //$NON-NLS-1$
203: return value2;
204: } else {
205: return getValue(
206: "K" + type + layout.substring(2), value, //$NON-NLS-1$
207: pool);
208: }
209: } else {
210: return getValue(layout, value, pool);
211: }
212: }
213:
214: public int hashCode() {
215: int PRIME = 31;
216: int r = 1;
217: if (name != null) {
218: r = r * PRIME + name.hashCode();
219: }
220: if (layout != null) {
221: r = r * PRIME + layout.hashCode();
222: }
223: r = r * PRIME + index;
224: r = r * PRIME + context;
225: return r;
226: }
227:
228: public boolean isClass() {
229: return context == CONTEXT_CLASS;
230: }
231:
232: public boolean isCode() {
233: return context == CONTEXT_CODE;
234: }
235:
236: public boolean isField() {
237: return context == CONTEXT_FIELD;
238: }
239:
240: public boolean isMethod() {
241: return context == CONTEXT_METHOD;
242: }
243:
244: /* (non-Javadoc)
245: * @see org.apache.harmony.pack200.IMatches#matches(long)
246: */
247: public boolean matches(long value) {
248: return (value & mask) != 0;
249: }
250:
251: public String toString() {
252: return contextNames[context] + ": " + name;
253: }
254:
255: public int getContext() {
256: return context;
257: }
258:
259: public int getIndex() {
260: return index;
261: }
262:
263: public String getName() {
264: return name;
265: }
266:
267: public int numBackwardsCallables() {
268: if (layout == "*") {
269: return 1;
270: } else {
271: return backwardsCallCount;
272: }
273: }
274:
275: public boolean isDefaultLayout() {
276: return isDefault;
277: }
278:
279: public void setBackwardsCallCount(int backwardsCallCount) {
280: this.backwardsCallCount = backwardsCallCount;
281: }
282:
283: }
|