1/* 2 * Copyright 2013, 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.writer.builder; 33 34import com.google.common.collect.Maps; 35import org.jf.dexlib2.base.reference.BaseMethodReference; 36import org.jf.dexlib2.iface.reference.MethodReference; 37import org.jf.dexlib2.writer.MethodSection; 38 39import javax.annotation.Nonnull; 40import java.util.Collection; 41import java.util.List; 42import java.util.Map.Entry; 43import java.util.concurrent.ConcurrentMap; 44 45class BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference, 46 BuilderProtoReference, BuilderMethodReference, BuilderMethod>{ 47 @Nonnull private final BuilderContext context; 48 @Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems = 49 Maps.newConcurrentMap(); 50 51 BuilderMethodPool(@Nonnull BuilderContext context) { 52 this.context = context; 53 } 54 55 @Nonnull public BuilderMethodReference internMethod(@Nonnull MethodReference methodReference) { 56 BuilderMethodReference ret = internedItems.get(methodReference); 57 if (ret != null) { 58 return ret; 59 } 60 61 BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference( 62 context.typePool.internType(methodReference.getDefiningClass()), 63 context.stringPool.internString(methodReference.getName()), 64 context.protoPool.internProto(methodReference)); 65 ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference); 66 return ret==null?dexPoolMethodReference:ret; 67 } 68 69 @Nonnull public BuilderMethodReference internMethod(@Nonnull String definingClass, @Nonnull String name, 70 @Nonnull List<? extends CharSequence> parameters, 71 @Nonnull String returnType) { 72 return internMethod(new MethodKey(definingClass, name, parameters, returnType)); 73 } 74 75 @Nonnull @Override 76 public BuilderTypeReference getDefiningClass(@Nonnull BuilderMethodReference key) { 77 return key.definingClass; 78 } 79 80 @Nonnull @Override 81 public BuilderProtoReference getPrototype(@Nonnull BuilderMethodReference key) { 82 return key.proto; 83 } 84 85 @Nonnull @Override public BuilderProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) { 86 return builderMethod.methodReference.proto; 87 } 88 89 @Nonnull @Override public BuilderStringReference getName(@Nonnull BuilderMethodReference key) { 90 return key.name; 91 } 92 93 @Override public int getMethodIndex(@Nonnull BuilderMethod builderMethod) { 94 return builderMethod.methodReference.index; 95 } 96 97 @Override public int getItemIndex(@Nonnull BuilderMethodReference key) { 98 return key.index; 99 } 100 101 @Nonnull @Override public Collection<? extends Entry<? extends BuilderMethodReference, Integer>> getItems() { 102 return new BuilderMapEntryCollection<BuilderMethodReference>(internedItems.values()) { 103 @Override protected int getValue(@Nonnull BuilderMethodReference key) { 104 return key.index; 105 } 106 107 @Override protected int setValue(@Nonnull BuilderMethodReference key, int value) { 108 int prev = key.index; 109 key.index = value; 110 return prev; 111 } 112 }; 113 } 114 115 private static class MethodKey extends BaseMethodReference implements MethodReference { 116 @Nonnull private final String definingClass; 117 @Nonnull private final String name; 118 @Nonnull private final List<? extends CharSequence> parameterTypes; 119 @Nonnull private final String returnType; 120 121 public MethodKey(@Nonnull String definingClass, @Nonnull String name, 122 @Nonnull List<? extends CharSequence> parameterTypes, @Nonnull String returnType) { 123 this.definingClass = definingClass; 124 this.name = name; 125 this.parameterTypes = parameterTypes; 126 this.returnType = returnType; 127 } 128 129 @Nonnull @Override public String getDefiningClass() { 130 return definingClass; 131 } 132 133 @Nonnull @Override public String getName() { 134 return name; 135 } 136 137 @Nonnull @Override public List<? extends CharSequence> getParameterTypes() { 138 return parameterTypes; 139 } 140 141 @Nonnull @Override public String getReturnType() { 142 return returnType; 143 } 144 } 145} 146