OSDN Git Service

Add several classes from dx tool to the dexgen project
[android-x86/dalvik.git] / dexgen / src / com / android / dexgen / dex / file / AnnotationItem.java
diff --git a/dexgen/src/com/android/dexgen/dex/file/AnnotationItem.java b/dexgen/src/com/android/dexgen/dex/file/AnnotationItem.java
new file mode 100644 (file)
index 0000000..a078bc0
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dexgen.dex.file;
+
+import com.android.dexgen.rop.annotation.Annotation;
+import com.android.dexgen.rop.annotation.AnnotationVisibility;
+import com.android.dexgen.rop.annotation.NameValuePair;
+import com.android.dexgen.rop.cst.Constant;
+import com.android.dexgen.rop.cst.CstAnnotation;
+import com.android.dexgen.rop.cst.CstArray;
+import com.android.dexgen.rop.cst.CstUtf8;
+import com.android.dexgen.util.AnnotatedOutput;
+import com.android.dexgen.util.ByteArrayAnnotatedOutput;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Single annotation, which consists of a type and a set of name-value
+ * element pairs.
+ */
+public final class AnnotationItem extends OffsettedItem {
+    /** annotation visibility constant: visible at build time only */
+    private static final int VISIBILITY_BUILD = 0;
+
+    /** annotation visibility constant: visible at runtime */
+    private static final int VISIBILITY_RUNTIME = 1;
+
+    /** annotation visibility constant: visible at runtime only to system */
+    private static final int VISIBILITY_SYSTEM = 2;
+
+    /** the required alignment for instances of this class */
+    private static final int ALIGNMENT = 1;
+
+    /** {@code non-null;} unique instance of {@link #TypeIdSorter} */
+    private static final TypeIdSorter TYPE_ID_SORTER = new TypeIdSorter();
+
+    /** {@code non-null;} the annotation to represent */
+    private final Annotation annotation;
+
+    /**
+     * {@code null-ok;} type reference for the annotation type; set during
+     * {@link #addContents}
+     */
+    private TypeIdItem type;
+
+    /**
+     * {@code null-ok;} encoded form, ready for writing to a file; set during
+     * {@link #place0}
+     */
+    private byte[] encodedForm;
+
+    /**
+     * Comparator that sorts (outer) instances by type id index.
+     */
+    private static class TypeIdSorter implements Comparator<AnnotationItem> {
+        /** {@inheritDoc} */
+        public int compare(AnnotationItem item1, AnnotationItem item2) {
+            int index1 = item1.type.getIndex();
+            int index2 = item2.type.getIndex();
+
+            if (index1 < index2) {
+                return -1;
+            } else if (index1 > index2) {
+                return 1;
+            }
+
+            return 0;
+        }
+    }
+
+    /**
+     * Sorts an array of instances, in place, by type id index,
+     * ignoring all other aspects of the elements. This is only valid
+     * to use after type id indices are known.
+     *
+     * @param array {@code non-null;} array to sort
+     */
+    public static void sortByTypeIdIndex(AnnotationItem[] array) {
+        Arrays.sort(array, TYPE_ID_SORTER);
+    }
+
+    /**
+     * Constructs an instance.
+     *
+     * @param annotation {@code non-null;} annotation to represent
+     */
+    public AnnotationItem(Annotation annotation) {
+        /*
+         * The write size isn't known up-front because (the variable-lengthed)
+         * leb128 type is used to represent some things.
+         */
+        super(ALIGNMENT, -1);
+
+        if (annotation == null) {
+            throw new NullPointerException("annotation == null");
+        }
+
+        this.annotation = annotation;
+        this.type = null;
+        this.encodedForm = null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ItemType itemType() {
+        return ItemType.TYPE_ANNOTATION_ITEM;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int hashCode() {
+        return annotation.hashCode();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected int compareTo0(OffsettedItem other) {
+        AnnotationItem otherAnnotation = (AnnotationItem) other;
+
+        return annotation.compareTo(otherAnnotation.annotation);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toHuman() {
+        return annotation.toHuman();
+    }
+
+    /** {@inheritDoc} */
+    public void addContents(DexFile file) {
+        type = file.getTypeIds().intern(annotation.getType());
+        ValueEncoder.addContents(file, annotation);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void place0(Section addedTo, int offset) {
+        // Encode the data and note the size.
+
+        ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
+        ValueEncoder encoder = new ValueEncoder(addedTo.getFile(), out);
+
+        encoder.writeAnnotation(annotation, false);
+        encodedForm = out.toByteArray();
+
+        // Add one for the visibility byte in front of the encoded annotation.
+        setWriteSize(encodedForm.length + 1);
+    }
+
+    /**
+     * Write a (listing file) annotation for this instance to the given
+     * output, that consumes no bytes of output. This is for annotating
+     * a reference to this instance at the point of the reference.
+     *
+     * @param out {@code non-null;} where to output to
+     * @param prefix {@code non-null;} prefix for each line of output
+     */
+    public void annotateTo(AnnotatedOutput out, String prefix) {
+        out.annotate(0, prefix + "visibility: " +
+                annotation.getVisibility().toHuman());
+        out.annotate(0, prefix + "type: " + annotation.getType().toHuman());
+
+        for (NameValuePair pair : annotation.getNameValuePairs()) {
+            CstUtf8 name = pair.getName();
+            Constant value = pair.getValue();
+
+            out.annotate(0, prefix + name.toHuman() + ": " +
+                    ValueEncoder.constantToHuman(value));
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void writeTo0(DexFile file, AnnotatedOutput out) {
+        boolean annotates = out.annotates();
+        AnnotationVisibility visibility = annotation.getVisibility();
+
+        if (annotates) {
+            out.annotate(0, offsetString() + " annotation");
+            out.annotate(1, "  visibility: VISBILITY_" + visibility);
+        }
+
+        switch (visibility) {
+            case BUILD:   out.writeByte(VISIBILITY_BUILD); break;
+            case RUNTIME: out.writeByte(VISIBILITY_RUNTIME); break;
+            case SYSTEM:  out.writeByte(VISIBILITY_SYSTEM); break;
+            default: {
+                // EMBEDDED shouldn't appear at the top level.
+                throw new RuntimeException("shouldn't happen");
+            }
+        }
+
+        if (annotates) {
+            /*
+             * The output is to be annotated, so redo the work previously
+             * done by place0(), except this time annotations will actually
+             * get emitted.
+             */
+            ValueEncoder encoder = new ValueEncoder(file, out);
+            encoder.writeAnnotation(annotation, true);
+        } else {
+            out.write(encodedForm);
+        }
+    }
+}