142627b850c8f68a594f105e04b97c512b292b698Ben Gruver/*
242627b850c8f68a594f105e04b97c512b292b698Ben Gruver * Copyright 2013, Google Inc.
342627b850c8f68a594f105e04b97c512b292b698Ben Gruver * All rights reserved.
442627b850c8f68a594f105e04b97c512b292b698Ben Gruver *
542627b850c8f68a594f105e04b97c512b292b698Ben Gruver * Redistribution and use in source and binary forms, with or without
642627b850c8f68a594f105e04b97c512b292b698Ben Gruver * modification, are permitted provided that the following conditions are
742627b850c8f68a594f105e04b97c512b292b698Ben Gruver * met:
842627b850c8f68a594f105e04b97c512b292b698Ben Gruver *
942627b850c8f68a594f105e04b97c512b292b698Ben Gruver *     * Redistributions of source code must retain the above copyright
1042627b850c8f68a594f105e04b97c512b292b698Ben Gruver * notice, this list of conditions and the following disclaimer.
1142627b850c8f68a594f105e04b97c512b292b698Ben Gruver *     * Redistributions in binary form must reproduce the above
1242627b850c8f68a594f105e04b97c512b292b698Ben Gruver * copyright notice, this list of conditions and the following disclaimer
1342627b850c8f68a594f105e04b97c512b292b698Ben Gruver * in the documentation and/or other materials provided with the
1442627b850c8f68a594f105e04b97c512b292b698Ben Gruver * distribution.
1542627b850c8f68a594f105e04b97c512b292b698Ben Gruver *     * Neither the name of Google Inc. nor the names of its
1642627b850c8f68a594f105e04b97c512b292b698Ben Gruver * contributors may be used to endorse or promote products derived from
1742627b850c8f68a594f105e04b97c512b292b698Ben Gruver * this software without specific prior written permission.
1842627b850c8f68a594f105e04b97c512b292b698Ben Gruver *
1942627b850c8f68a594f105e04b97c512b292b698Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2042627b850c8f68a594f105e04b97c512b292b698Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2142627b850c8f68a594f105e04b97c512b292b698Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2242627b850c8f68a594f105e04b97c512b292b698Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2342627b850c8f68a594f105e04b97c512b292b698Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2442627b850c8f68a594f105e04b97c512b292b698Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2542627b850c8f68a594f105e04b97c512b292b698Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2642627b850c8f68a594f105e04b97c512b292b698Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2742627b850c8f68a594f105e04b97c512b292b698Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2842627b850c8f68a594f105e04b97c512b292b698Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2942627b850c8f68a594f105e04b97c512b292b698Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3042627b850c8f68a594f105e04b97c512b292b698Ben Gruver */
3142627b850c8f68a594f105e04b97c512b292b698Ben Gruver
3242627b850c8f68a594f105e04b97c512b292b698Ben Gruverpackage org.jf.dexlib2.writer.builder;
3342627b850c8f68a594f105e04b97c512b292b698Ben Gruver
3442627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport com.google.common.collect.Maps;
3542627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport org.jf.dexlib2.base.reference.BaseMethodReference;
3642627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport org.jf.dexlib2.iface.reference.MethodReference;
3742627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport org.jf.dexlib2.writer.MethodSection;
3842627b850c8f68a594f105e04b97c512b292b698Ben Gruver
3942627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport javax.annotation.Nonnull;
4042627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport java.util.Collection;
4142627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport java.util.List;
4242627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport java.util.Map.Entry;
4342627b850c8f68a594f105e04b97c512b292b698Ben Gruverimport java.util.concurrent.ConcurrentMap;
4442627b850c8f68a594f105e04b97c512b292b698Ben Gruver
4542627b850c8f68a594f105e04b97c512b292b698Ben Gruverclass BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference,
4642627b850c8f68a594f105e04b97c512b292b698Ben Gruver        BuilderProtoReference, BuilderMethodReference, BuilderMethod>{
4742627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull private final BuilderContext context;
4842627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems =
4942627b850c8f68a594f105e04b97c512b292b698Ben Gruver            Maps.newConcurrentMap();
5042627b850c8f68a594f105e04b97c512b292b698Ben Gruver
5142627b850c8f68a594f105e04b97c512b292b698Ben Gruver    BuilderMethodPool(@Nonnull BuilderContext context) {
5242627b850c8f68a594f105e04b97c512b292b698Ben Gruver        this.context = context;
5342627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
5442627b850c8f68a594f105e04b97c512b292b698Ben Gruver
5542627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull public BuilderMethodReference internMethod(@Nonnull MethodReference methodReference) {
5642627b850c8f68a594f105e04b97c512b292b698Ben Gruver        BuilderMethodReference ret = internedItems.get(methodReference);
5742627b850c8f68a594f105e04b97c512b292b698Ben Gruver        if (ret != null) {
5842627b850c8f68a594f105e04b97c512b292b698Ben Gruver            return ret;
5942627b850c8f68a594f105e04b97c512b292b698Ben Gruver        }
6042627b850c8f68a594f105e04b97c512b292b698Ben Gruver
6142627b850c8f68a594f105e04b97c512b292b698Ben Gruver        BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference(
6242627b850c8f68a594f105e04b97c512b292b698Ben Gruver                context.typePool.internType(methodReference.getDefiningClass()),
6342627b850c8f68a594f105e04b97c512b292b698Ben Gruver                context.stringPool.internString(methodReference.getName()),
6442627b850c8f68a594f105e04b97c512b292b698Ben Gruver                context.protoPool.internProto(methodReference));
6542627b850c8f68a594f105e04b97c512b292b698Ben Gruver        ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference);
6642627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return ret==null?dexPoolMethodReference:ret;
6742627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
6842627b850c8f68a594f105e04b97c512b292b698Ben Gruver
6942627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull public BuilderMethodReference internMethod(@Nonnull String definingClass, @Nonnull String name,
7042627b850c8f68a594f105e04b97c512b292b698Ben Gruver                                                        @Nonnull List<? extends CharSequence> parameters,
7142627b850c8f68a594f105e04b97c512b292b698Ben Gruver                                                        @Nonnull String returnType) {
7242627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return internMethod(new MethodKey(definingClass, name, parameters, returnType));
7342627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
7442627b850c8f68a594f105e04b97c512b292b698Ben Gruver
7542627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull @Override
7642627b850c8f68a594f105e04b97c512b292b698Ben Gruver    public BuilderTypeReference getDefiningClass(@Nonnull BuilderMethodReference key) {
7742627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return key.definingClass;
7842627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
7942627b850c8f68a594f105e04b97c512b292b698Ben Gruver
8042627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull @Override
8142627b850c8f68a594f105e04b97c512b292b698Ben Gruver    public BuilderProtoReference getPrototype(@Nonnull BuilderMethodReference key) {
8242627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return key.proto;
8342627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
8442627b850c8f68a594f105e04b97c512b292b698Ben Gruver
8542627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull @Override public BuilderProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) {
8642627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return builderMethod.methodReference.proto;
8742627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
8842627b850c8f68a594f105e04b97c512b292b698Ben Gruver
8942627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull @Override public BuilderStringReference getName(@Nonnull BuilderMethodReference key) {
9042627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return key.name;
9142627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
9242627b850c8f68a594f105e04b97c512b292b698Ben Gruver
9342627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Override public int getMethodIndex(@Nonnull BuilderMethod builderMethod) {
9442627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return builderMethod.methodReference.index;
9542627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
9642627b850c8f68a594f105e04b97c512b292b698Ben Gruver
9742627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Override public int getItemIndex(@Nonnull BuilderMethodReference key) {
9842627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return key.index;
9942627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
10042627b850c8f68a594f105e04b97c512b292b698Ben Gruver
10142627b850c8f68a594f105e04b97c512b292b698Ben Gruver    @Nonnull @Override public Collection<? extends Entry<? extends BuilderMethodReference, Integer>> getItems() {
10242627b850c8f68a594f105e04b97c512b292b698Ben Gruver        return new BuilderMapEntryCollection<BuilderMethodReference>(internedItems.values()) {
10342627b850c8f68a594f105e04b97c512b292b698Ben Gruver            @Override protected int getValue(@Nonnull BuilderMethodReference key) {
10442627b850c8f68a594f105e04b97c512b292b698Ben Gruver                return key.index;
10542627b850c8f68a594f105e04b97c512b292b698Ben Gruver            }
10642627b850c8f68a594f105e04b97c512b292b698Ben Gruver
10742627b850c8f68a594f105e04b97c512b292b698Ben Gruver            @Override protected int setValue(@Nonnull BuilderMethodReference key, int value) {
10842627b850c8f68a594f105e04b97c512b292b698Ben Gruver                int prev = key.index;
10942627b850c8f68a594f105e04b97c512b292b698Ben Gruver                key.index = value;
11042627b850c8f68a594f105e04b97c512b292b698Ben Gruver                return prev;
11142627b850c8f68a594f105e04b97c512b292b698Ben Gruver            }
11242627b850c8f68a594f105e04b97c512b292b698Ben Gruver        };
11342627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
11442627b850c8f68a594f105e04b97c512b292b698Ben Gruver
11542627b850c8f68a594f105e04b97c512b292b698Ben Gruver    private static class MethodKey extends BaseMethodReference implements MethodReference {
11642627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull private final String definingClass;
11742627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull private final String name;
11842627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull private final List<? extends CharSequence> parameterTypes;
11942627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull private final String returnType;
12042627b850c8f68a594f105e04b97c512b292b698Ben Gruver
12142627b850c8f68a594f105e04b97c512b292b698Ben Gruver        public MethodKey(@Nonnull String definingClass, @Nonnull String name,
12242627b850c8f68a594f105e04b97c512b292b698Ben Gruver                         @Nonnull List<? extends CharSequence> parameterTypes, @Nonnull String returnType) {
12342627b850c8f68a594f105e04b97c512b292b698Ben Gruver            this.definingClass = definingClass;
12442627b850c8f68a594f105e04b97c512b292b698Ben Gruver            this.name = name;
12542627b850c8f68a594f105e04b97c512b292b698Ben Gruver            this.parameterTypes = parameterTypes;
12642627b850c8f68a594f105e04b97c512b292b698Ben Gruver            this.returnType = returnType;
12742627b850c8f68a594f105e04b97c512b292b698Ben Gruver        }
12842627b850c8f68a594f105e04b97c512b292b698Ben Gruver
12942627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull @Override public String getDefiningClass() {
13042627b850c8f68a594f105e04b97c512b292b698Ben Gruver            return definingClass;
13142627b850c8f68a594f105e04b97c512b292b698Ben Gruver        }
13242627b850c8f68a594f105e04b97c512b292b698Ben Gruver
13342627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull @Override public String getName() {
13442627b850c8f68a594f105e04b97c512b292b698Ben Gruver            return name;
13542627b850c8f68a594f105e04b97c512b292b698Ben Gruver        }
13642627b850c8f68a594f105e04b97c512b292b698Ben Gruver
13742627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull @Override public List<? extends CharSequence> getParameterTypes() {
13842627b850c8f68a594f105e04b97c512b292b698Ben Gruver            return parameterTypes;
13942627b850c8f68a594f105e04b97c512b292b698Ben Gruver        }
14042627b850c8f68a594f105e04b97c512b292b698Ben Gruver
14142627b850c8f68a594f105e04b97c512b292b698Ben Gruver        @Nonnull @Override public String getReturnType() {
14242627b850c8f68a594f105e04b97c512b292b698Ben Gruver            return returnType;
14342627b850c8f68a594f105e04b97c512b292b698Ben Gruver        }
14442627b850c8f68a594f105e04b97c512b292b698Ben Gruver    }
14542627b850c8f68a594f105e04b97c512b292b698Ben Gruver}
146