/** * Returns an <code>AnnotationSetItem</code> for the given annotations, and that has been interned into the given * <code>DexFile</code> * @param dexFile The <code>DexFile</code> that this item belongs to * @param annotations The annotations for this <code>AnnotationSetItem</code> * @return an <code>AnnotationSetItem</code> for the given annotations */ public static AnnotationSetItem internAnnotationSetItem(DexFile dexFile, List<AnnotationItem> annotations) { AnnotationSetItem annotationSetItem; if (annotations == null) { annotationSetItem = new AnnotationSetItem(dexFile, new AnnotationItem[0]); } else { AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()]; annotations.toArray(annotationsArray); annotationSetItem = new AnnotationSetItem(dexFile, annotationsArray); } return dexFile.AnnotationSetsSection.intern(annotationSetItem); }
@Override public int hashCode() { //there's a small possibility that the actual hash code will be 0. If so, we'll //just end up recalculating it each time if (hashCode == 0) calcHashCode(); return hashCode; }
/** {@inheritDoc} */ public int compareTo(AnnotationSetRefList o) { int comp = annotationSets.length - o.annotationSets.length; if (comp != 0) { return comp; } for (int i=0; i<annotationSets.length; i++) { comp = annotationSets[i].compareTo(o.annotationSets[i]); if (comp != 0) { return comp; } } return comp; }
/** {@inheritDoc} */ public String getConciseIdentity() { return "annotation_set_item @0x" + Integer.toHexString(getOffset()); }
/** * calculate and cache the hashcode */ private void calcHashCode() { hashCode = 0; for (AnnotationSetItem annotationSetItem: annotationSets) { hashCode = hashCode * 31 + annotationSetItem.hashCode(); } }
@Nonnull private List<TestCaseEvent> convertClassToTestCaseEvents(ClassDefItem classDefItem) { AnnotationDirectoryItem annotationDirectoryItem = classDefItem.getAnnotations(); if (annotationDirectoryItem == null) { return emptyList(); } List<TestCaseEvent> testCaseEvents = new ArrayList<>(); for (AnnotationDirectoryItem.MethodAnnotation method : annotationDirectoryItem.getMethodAnnotations()) { stream(method.annotationSet.getAnnotations()) .filter(annotation -> TEST_ANNOTATION.equals(stringType(annotation))) .map(annotation -> convertToTestCaseEvent(classDefItem, annotationDirectoryItem, method)) .forEach(testCaseEvents::add); } return testCaseEvents; }
/** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length + ")"); for (AnnotationSetItem annotationSetItem: annotationSets) { out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset())); } } out.writeInt(annotationSets.length); for (AnnotationSetItem annotationSetItem: annotationSets) { out.writeInt(annotationSetItem.getOffset()); } }
@Override public int hashCode() { //an instance is only internable if it has only class annotations, but //no other type of annotation if (!isInternable()) { return super.hashCode(); } return classAnnotations.hashCode(); }
private boolean isClassIgnored(AnnotationDirectoryItem annotationDirectoryItem) { AnnotationSetItem classAnnotations = annotationDirectoryItem.getClassAnnotations(); if (classAnnotations == null) { return false; } return containsAnnotation(IGNORE_ANNOTATION, classAnnotations.getAnnotations()); }
out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset())); } else { out.annotate(4, "class_annotations_off:"); out.annotate(4, "field: " + fieldAnnotationFields[i].getFieldName().getStringValue() + ":" + fieldAnnotationFields[i].getFieldType().getTypeDescriptor()); out.annotate(4, "annotations_off: 0x" + Integer.toHexString(fieldAnnotations[i].getOffset())); out.deindent(); out.indent(); out.annotate(4, "method: " + methodAnnotationMethods[i].getMethodString()); out.annotate(4, "annotations_off: 0x" + Integer.toHexString(methodAnnotations[i].getOffset())); out.deindent(); out.writeInt(classAnnotations==null?0:classAnnotations.getOffset()); out.writeInt(fieldAnnotations==null?0:fieldAnnotations.length); out.writeInt(methodAnnotations==null?0:methodAnnotations.length); for (int i=0; i<fieldAnnotations.length; i++) { out.writeInt(fieldAnnotationFields[i].getIndex()); out.writeInt(fieldAnnotations[i].getOffset()); for (int i=0; i<methodAnnotations.length; i++) { out.writeInt(methodAnnotationMethods[i].getIndex()); out.writeInt(methodAnnotations[i].getOffset());
@Override public boolean equals(Object o) { if (this==o) { return true; } if (o==null || !this.getClass().equals(o.getClass())) { return false; } AnnotationSetItem other = (AnnotationSetItem)o; return (this.compareTo(other) == 0); } }
/** * calculate and cache the hashcode */ private void calcHashCode() { hashCode = 0; for (AnnotationSetItem annotationSetItem: annotationSets) { hashCode = hashCode * 31 + annotationSetItem.hashCode(); } }
return new AnnotationSetRefList(dexFile); case TYPE_ANNOTATION_SET_ITEM: return new AnnotationSetItem(dexFile); case TYPE_CLASS_DATA_ITEM: return new ClassDataItem(dexFile);
@Override public int hashCode() { //there's a small possibility that the actual hash code will be 0. If so, we'll //just end up recalculating it each time if (hashCode == 0) calcHashCode(); return hashCode; }
@Nonnull private TestCaseEvent convertToTestCaseEvent(ClassDefItem classDefItem, AnnotationDirectoryItem annotationDirectoryItem, AnnotationDirectoryItem.MethodAnnotation method) { String testMethod = method.method.getMethodName().getStringValue(); AnnotationItem[] annotations = method.annotationSet.getAnnotations(); String testClass = getClassName(classDefItem); boolean isIgnored = isClassIgnored(annotationDirectoryItem) || isMethodIgnored(annotations); List<String> permissionsToRevoke = getPermissionsToRevoke(annotations); Map<String, String> properties = getTestProperties(annotations); return testCaseEvent() .withTestClass(testClass) .withTestMethod(testMethod) .withIsIgnored(isIgnored) .withPermissionsToRevoke(permissionsToRevoke) .withProperties(properties) .build(); }
/** {@inheritDoc} */ public String getConciseIdentity() { return "annotation_set_item @0x" + Integer.toHexString(getOffset()); }
/** {@inheritDoc} */ public int compareTo(AnnotationDirectoryItem o) { if (!isInternable()) { if (!o.isInternable()) { return parent.compareTo(o.parent); } return -1; } if (!o.isInternable()) { return 1; } return classAnnotations.compareTo(o.classAnnotations); }
@Override public int hashCode() { return field.hashCode() + 31 * annotationSet.hashCode(); }
/** * Returns an <code>AnnotationSetItem</code> for the given annotations, and that has been interned into the given * <code>DexFile</code> * @param dexFile The <code>DexFile</code> that this item belongs to * @param annotations The annotations for this <code>AnnotationSetItem</code> * @return an <code>AnnotationSetItem</code> for the given annotations */ public static AnnotationSetItem internAnnotationSetItem(DexFile dexFile, List<AnnotationItem> annotations) { AnnotationSetItem annotationSetItem; if (annotations == null) { annotationSetItem = new AnnotationSetItem(dexFile, new AnnotationItem[0]); } else { AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()]; annotations.toArray(annotationsArray); annotationSetItem = new AnnotationSetItem(dexFile, annotationsArray); } return dexFile.AnnotationSetsSection.intern(annotationSetItem); }
/** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length + ")"); for (AnnotationSetItem annotationSetItem: annotationSets) { out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset())); } } out.writeInt(annotationSets.length); for (AnnotationSetItem annotationSetItem: annotationSets) { out.writeInt(annotationSetItem.getOffset()); } }