Home | History | Annotate | Download | only in dexlib
      1 /*
      2  * [The "BSD licence"]
      3  * Copyright (c) 2010 Ben Gruver (JesusFreke)
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 package org.jf.dexlib;
     30 
     31 import org.jf.dexlib.Util.AnnotatedOutput;
     32 import org.jf.dexlib.Util.Input;
     33 
     34 import java.util.List;
     35 
     36 public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
     37     private int hashCode = 0;
     38 
     39     private AnnotationSetItem[] annotationSets;
     40 
     41      /**
     42      * Creates a new uninitialized <code>AnnotationSetRefList</code>
     43      * @param dexFile The <code>DexFile</code> that this item belongs to
     44      */
     45     protected AnnotationSetRefList(DexFile dexFile) {
     46         super(dexFile);
     47     }
     48 
     49     /**
     50      * Creates a new <code>AnnotationSetRefList</code> for the given annotation sets
     51      * @param dexFile The <code>DexFile</code> that this item belongs to
     52      * @param annotationSets The annotationSets for this <code>AnnotationSetRefList</code>
     53      */
     54     private AnnotationSetRefList(DexFile dexFile, AnnotationSetItem[] annotationSets) {
     55         super(dexFile);
     56         this.annotationSets = annotationSets;
     57     }
     58 
     59     /**
     60      * Returns an <code>AnnotationSetRefList</code> for the given annotation sets, and that has been interned into the
     61      * given <code>DexFile</code>
     62      * @param dexFile The <code>DexFile</code> that this item belongs to
     63      * @param annotationSets The annotation sets for this <code>AnnotationSetRefList</code>
     64      * @return an <code>AnnotationSetItem</code> for the given annotations
     65      */
     66     public static AnnotationSetRefList internAnnotationSetRefList(DexFile dexFile,
     67                                                                        List<AnnotationSetItem> annotationSets) {
     68         AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()];
     69         annotationSets.toArray(annotationSetsArray);
     70         AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray);
     71         return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList);
     72     }
     73 
     74     /** {@inheritDoc} */
     75     protected void readItem(Input in, ReadContext readContext) {
     76         annotationSets = new AnnotationSetItem[in.readInt()];
     77 
     78         for (int i=0; i<annotationSets.length; i++) {
     79             annotationSets[i] = (AnnotationSetItem)readContext.getOptionalOffsettedItemByOffset(
     80                     ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
     81         }
     82     }
     83 
     84     /** {@inheritDoc} */
     85     protected int placeItem(int offset) {
     86         return offset + 4 + annotationSets.length * 4;
     87     }
     88 
     89     /** {@inheritDoc} */
     90     protected void writeItem(AnnotatedOutput out) {
     91         if (out.annotates()) {
     92             out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length +
     93                     ")");
     94             for (AnnotationSetItem annotationSetItem: annotationSets) {
     95                 out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset()));
     96             }
     97         }
     98         out.writeInt(annotationSets.length);
     99         for (AnnotationSetItem annotationSetItem: annotationSets) {
    100             out.writeInt(annotationSetItem.getOffset());
    101         }
    102     }
    103 
    104     /** {@inheritDoc} */
    105     public ItemType getItemType() {
    106         return ItemType.TYPE_ANNOTATION_SET_REF_LIST;
    107     }
    108 
    109     /** {@inheritDoc} */
    110     public String getConciseIdentity() {
    111         return "annotation_set_item @0x" + Integer.toHexString(getOffset());
    112     }
    113 
    114     /** {@inheritDoc} */
    115     public int compareTo(AnnotationSetRefList o) {
    116         int comp = annotationSets.length - o.annotationSets.length;
    117         if (comp != 0) {
    118             return comp;
    119         }
    120 
    121         for (int i=0; i<annotationSets.length; i++) {
    122             comp = annotationSets[i].compareTo(o.annotationSets[i]);
    123             if (comp != 0) {
    124                 return comp;
    125             }
    126         }
    127 
    128         return comp;
    129     }
    130 
    131     /**
    132      * @return An array of the <code>AnnotationSetItem</code> objects that make up this
    133      * <code>AnnotationSetRefList</code>
    134      */
    135     public AnnotationSetItem[] getAnnotationSets() {
    136         return annotationSets;
    137     }
    138 
    139     /**
    140      * calculate and cache the hashcode
    141      */
    142     private void calcHashCode() {
    143         hashCode = 0;
    144         for (AnnotationSetItem annotationSetItem: annotationSets) {
    145             hashCode = hashCode * 31 + annotationSetItem.hashCode();
    146         }
    147     }
    148 
    149     @Override
    150     public int hashCode() {
    151         //there's a small possibility that the actual hash code will be 0. If so, we'll
    152         //just end up recalculating it each time
    153         if (hashCode == 0)
    154             calcHashCode();
    155         return hashCode;
    156     }
    157 
    158     @Override
    159     public boolean equals(Object o) {
    160         if (this==o) {
    161             return true;
    162         }
    163         if (o==null || !this.getClass().equals(o.getClass())) {
    164             return false;
    165         }
    166 
    167         AnnotationSetRefList other = (AnnotationSetRefList)o;
    168         return (this.compareTo(other) == 0);
    169     }
    170 }
    171