AnnotationSetItem.java revision 83b80f81d311b233188c281059aad4a9f5e8b4e6
1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2009 Ben Gruver 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 29package org.jf.dexlib; 30 31import org.jf.dexlib.Util.Input; 32import org.jf.dexlib.Util.AnnotatedOutput; 33 34public class AnnotationSetItem extends Item<AnnotationSetItem> { 35 private int hashCode = 0; 36 37 private AnnotationItem[] annotations; 38 39 /** 40 * Creates a new uninitialized <code>AnnotationSetItem</code> 41 * @param dexFile The <code>DexFile</code> that this item belongs to 42 */ 43 protected AnnotationSetItem(DexFile dexFile) { 44 super(dexFile); 45 } 46 47 /** 48 * Creates a new <code>AnnotationSetItem</code> for the given annotations 49 * @param dexFile The <code>DexFile</code> that this item belongs to 50 * @param annotations The annotations for this <code>AnnotationSetItem</code> 51 */ 52 private AnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) { 53 super(dexFile); 54 this.annotations = annotations; 55 } 56 57 /** 58 * Returns an <code>AnnotationSetItem</code> for the given annotations, and that has been interned into the given 59 * <code>DexFile</code> 60 * @param dexFile The <code>DexFile</code> that this item belongs to 61 * @param annotations The annotations for this <code>AnnotationSetItem</code> 62 * @return an <code>AnnotationSetItem</code> for the given annotations 63 */ 64 public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) { 65 AnnotationSetItem annotationSetItem = new AnnotationSetItem(dexFile, annotations); 66 return dexFile.AnnotationSetsSection.intern(annotationSetItem); 67 } 68 69 /** {@inheritDoc} */ 70 protected void readItem(Input in, ReadContext readContext) { 71 annotations = new AnnotationItem[in.readInt()]; 72 73 for (int i=0; i<annotations.length; i++) { 74 annotations[i] = (AnnotationItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_ITEM, 75 in.readInt()); 76 } 77 } 78 79 /** {@inheritDoc} */ 80 protected int placeItem(int offset) { 81 return offset + 4 + annotations.length * 4; 82 } 83 84 /** {@inheritDoc} */ 85 protected void writeItem(AnnotatedOutput out) { 86 if (out.annotates()) { 87 out.annotate(4, "size"); 88 for (int i=0; i<annotations.length; i++) { 89 out.annotate(4, "annotation_off"); 90 } 91 } 92 out.writeInt(annotations.length); 93 for (AnnotationItem annotationItem: annotations) { 94 out.writeInt(annotationItem.getOffset()); 95 } 96 } 97 98 /** {@inheritDoc} */ 99 public ItemType getItemType() { 100 return ItemType.TYPE_ANNOTATION_SET_ITEM; 101 } 102 103 /** {@inheritDoc} */ 104 public String getConciseIdentity() { 105 return "annotation_set_item @0x" + Integer.toHexString(getOffset()); 106 } 107 108/** {@inheritDoc} */ 109 public int compareTo(AnnotationSetItem o) { 110 if (o == null) { 111 return 1; 112 } 113 114 int comp = annotations.length - o.annotations.length; 115 if (comp == 0) { 116 for (int i=0; i<annotations.length; i++) { 117 comp = annotations[i].compareTo(o.annotations[i]); 118 if (comp != 0) { 119 return comp; 120 } 121 } 122 } 123 return comp; 124 } 125 126 /** 127 * @return An array of the <code>AnnotationItem</code> objects in this <code>AnnotationSetItem</code> 128 */ 129 public AnnotationItem[] getAnnotations() { 130 return annotations; 131 } 132 133 /** 134 * calculate and cache the hashcode 135 */ 136 private void calcHashCode() { 137 hashCode = 0; 138 for (AnnotationItem annotationItem: annotations) { 139 hashCode = hashCode * 31 + annotationItem.hashCode(); 140 } 141 } 142 143 @Override 144 public int hashCode() { 145 //there's a small possibility that the actual hash code will be 0. If so, we'll 146 //just end up recalculating it each time 147 if (hashCode == 0) 148 calcHashCode(); 149 return hashCode; 150 } 151 152 @Override 153 public boolean equals(Object o) { 154 if (this==o) { 155 return true; 156 } 157 if (o==null || !this.getClass().equals(o.getClass())) { 158 return false; 159 } 160 161 AnnotationSetItem other = (AnnotationSetItem)o; 162 return (this.compareTo(other) == 0); 163 } 164} 165