1/* 2 * Copyright 2012, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib2.immutable; 33 34import com.google.common.collect.*; 35import org.jf.dexlib2.base.reference.BaseTypeReference; 36import org.jf.dexlib2.iface.Annotation; 37import org.jf.dexlib2.iface.ClassDef; 38import org.jf.dexlib2.iface.Field; 39import org.jf.dexlib2.iface.Method; 40import org.jf.dexlib2.util.FieldUtil; 41import org.jf.dexlib2.util.MethodUtil; 42import org.jf.util.ImmutableConverter; 43import org.jf.util.ImmutableUtils; 44 45import javax.annotation.Nonnull; 46import javax.annotation.Nullable; 47import java.util.AbstractCollection; 48import java.util.Collection; 49import java.util.Iterator; 50import java.util.List; 51 52public class ImmutableClassDef extends BaseTypeReference implements ClassDef { 53 @Nonnull protected final String type; 54 protected final int accessFlags; 55 @Nullable protected final String superclass; 56 @Nonnull protected final ImmutableList<String> interfaces; 57 @Nullable protected final String sourceFile; 58 @Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations; 59 @Nonnull protected final ImmutableSortedSet<? extends ImmutableField> staticFields; 60 @Nonnull protected final ImmutableSortedSet<? extends ImmutableField> instanceFields; 61 @Nonnull protected final ImmutableSortedSet<? extends ImmutableMethod> directMethods; 62 @Nonnull protected final ImmutableSortedSet<? extends ImmutableMethod> virtualMethods; 63 64 public ImmutableClassDef(@Nonnull String type, 65 int accessFlags, 66 @Nullable String superclass, 67 @Nullable Collection<String> interfaces, 68 @Nullable String sourceFile, 69 @Nullable Collection<? extends Annotation> annotations, 70 @Nullable Iterable<? extends Field> fields, 71 @Nullable Iterable<? extends Method> methods) { 72 if (fields == null) { 73 fields = ImmutableList.of(); 74 } 75 if (methods == null) { 76 methods = ImmutableList.of(); 77 } 78 79 this.type = type; 80 this.accessFlags = accessFlags; 81 this.superclass = superclass; 82 this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces); 83 this.sourceFile = sourceFile; 84 this.annotations = ImmutableAnnotation.immutableSetOf(annotations); 85 this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC)); 86 this.instanceFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE)); 87 this.directMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT)); 88 this.virtualMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL)); 89 } 90 91 public ImmutableClassDef(@Nonnull String type, 92 int accessFlags, 93 @Nullable String superclass, 94 @Nullable Collection<String> interfaces, 95 @Nullable String sourceFile, 96 @Nullable Collection<? extends Annotation> annotations, 97 @Nullable Iterable<? extends Field> staticFields, 98 @Nullable Iterable<? extends Field> instanceFields, 99 @Nullable Iterable<? extends Method> directMethods, 100 @Nullable Iterable<? extends Method> virtualMethods) { 101 this.type = type; 102 this.accessFlags = accessFlags; 103 this.superclass = superclass; 104 this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces); 105 this.sourceFile = sourceFile; 106 this.annotations = ImmutableAnnotation.immutableSetOf(annotations); 107 this.staticFields = ImmutableField.immutableSetOf(staticFields); 108 this.instanceFields = ImmutableField.immutableSetOf(instanceFields); 109 this.directMethods = ImmutableMethod.immutableSetOf(directMethods); 110 this.virtualMethods = ImmutableMethod.immutableSetOf(virtualMethods); 111 } 112 113 public ImmutableClassDef(@Nonnull String type, 114 int accessFlags, 115 @Nullable String superclass, 116 @Nullable ImmutableList<String> interfaces, 117 @Nullable String sourceFile, 118 @Nullable ImmutableSet<? extends ImmutableAnnotation> annotations, 119 @Nullable ImmutableSortedSet<? extends ImmutableField> staticFields, 120 @Nullable ImmutableSortedSet<? extends ImmutableField> instanceFields, 121 @Nullable ImmutableSortedSet<? extends ImmutableMethod> directMethods, 122 @Nullable ImmutableSortedSet<? extends ImmutableMethod> virtualMethods) { 123 this.type = type; 124 this.accessFlags = accessFlags; 125 this.superclass = superclass; 126 this.interfaces = ImmutableUtils.nullToEmptyList(interfaces); 127 this.sourceFile = sourceFile; 128 this.annotations = ImmutableUtils.nullToEmptySet(annotations); 129 this.staticFields = ImmutableUtils.nullToEmptySortedSet(staticFields); 130 this.instanceFields = ImmutableUtils.nullToEmptySortedSet(instanceFields); 131 this.directMethods = ImmutableUtils.nullToEmptySortedSet(directMethods); 132 this.virtualMethods = ImmutableUtils.nullToEmptySortedSet(virtualMethods); 133 } 134 135 public static ImmutableClassDef of(ClassDef classDef) { 136 if (classDef instanceof ImmutableClassDef) { 137 return (ImmutableClassDef)classDef; 138 } 139 return new ImmutableClassDef( 140 classDef.getType(), 141 classDef.getAccessFlags(), 142 classDef.getSuperclass(), 143 classDef.getInterfaces(), 144 classDef.getSourceFile(), 145 classDef.getAnnotations(), 146 classDef.getStaticFields(), 147 classDef.getInstanceFields(), 148 classDef.getDirectMethods(), 149 classDef.getVirtualMethods()); 150 } 151 152 @Nonnull @Override public String getType() { return type; } 153 @Override public int getAccessFlags() { return accessFlags; } 154 @Nullable @Override public String getSuperclass() { return superclass; } 155 @Nonnull @Override public ImmutableList<String> getInterfaces() { return interfaces; } 156 @Nullable @Override public String getSourceFile() { return sourceFile; } 157 @Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; } 158 @Nonnull @Override public ImmutableSet<? extends ImmutableField> getStaticFields() { return staticFields; } 159 @Nonnull @Override public ImmutableSet<? extends ImmutableField> getInstanceFields() { return instanceFields; } 160 @Nonnull @Override public ImmutableSet<? extends ImmutableMethod> getDirectMethods() { return directMethods; } 161 @Nonnull @Override public ImmutableSet<? extends ImmutableMethod> getVirtualMethods() { return virtualMethods; } 162 163 @Nonnull 164 @Override 165 public Collection<? extends ImmutableField> getFields() { 166 return new AbstractCollection<ImmutableField>() { 167 @Nonnull 168 @Override 169 public Iterator<ImmutableField> iterator() { 170 return Iterators.concat(staticFields.iterator(), instanceFields.iterator()); 171 } 172 173 @Override public int size() { 174 return staticFields.size() + instanceFields.size(); 175 } 176 }; 177 } 178 179 @Nonnull 180 @Override 181 public Collection<? extends ImmutableMethod> getMethods() { 182 return new AbstractCollection<ImmutableMethod>() { 183 @Nonnull 184 @Override 185 public Iterator<ImmutableMethod> iterator() { 186 return Iterators.concat(directMethods.iterator(), virtualMethods.iterator()); 187 } 188 189 @Override public int size() { 190 return directMethods.size() + virtualMethods.size(); 191 } 192 }; 193 } 194 195 @Nonnull 196 public static ImmutableSet<ImmutableClassDef> immutableSetOf(@Nullable Iterable<? extends ClassDef> iterable) { 197 return CONVERTER.toSet(iterable); 198 } 199 200 private static final ImmutableConverter<ImmutableClassDef, ClassDef> CONVERTER = 201 new ImmutableConverter<ImmutableClassDef, ClassDef>() { 202 @Override 203 protected boolean isImmutable(@Nonnull ClassDef item) { 204 return item instanceof ImmutableClassDef; 205 } 206 207 @Nonnull 208 @Override 209 protected ImmutableClassDef makeImmutable(@Nonnull ClassDef item) { 210 return ImmutableClassDef.of(item); 211 } 212 }; 213} 214