From fa5d0cc73a3f77fcf9245deebea6c3ed023a645f Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Wed, 31 Jan 2018 13:31:46 -0800 Subject: [PATCH] Add Immutable implementations of the new structures --- .../reference/ImmutableCallSiteReference.java | 92 +++++++++++++++++++ .../ImmutableMethodHandleReference.java | 87 ++++++++++++++++++ .../ImmutableMethodProtoReference.java | 10 +- .../reference/ImmutableReferenceFactory.java | 10 ++ .../value/ImmutableEncodedValueFactory.java | 4 + .../ImmutableMethodHandleEncodedValue.java | 57 ++++++++++++ .../ImmutableMethodTypeEncodedValue.java | 57 ++++++++++++ 7 files changed, 315 insertions(+), 2 deletions(-) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableCallSiteReference.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodHandleReference.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodHandleEncodedValue.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodTypeEncodedValue.java diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableCallSiteReference.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableCallSiteReference.java new file mode 100644 index 00000000..8b3c17f4 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableCallSiteReference.java @@ -0,0 +1,92 @@ +/* + * Copyright 2018, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.immutable.reference; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.reference.BaseCallSiteReference; +import org.jf.dexlib2.iface.reference.CallSiteReference; +import org.jf.dexlib2.iface.reference.MethodHandleReference; +import org.jf.dexlib2.iface.reference.MethodProtoReference; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValueFactory; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableCallSiteReference extends BaseCallSiteReference implements ImmutableReference { + @Nonnull protected final String name; + @Nonnull protected final ImmutableMethodHandleReference methodHandle; + @Nonnull protected final String methodName; + @Nonnull protected final ImmutableMethodProtoReference methodProto; + @Nonnull protected final ImmutableList extraArguments; + + public ImmutableCallSiteReference(@Nonnull String name, @Nonnull MethodHandleReference methodHandle, + @Nonnull String methodName, @Nonnull MethodProtoReference methodProto, + @Nonnull Iterable extraArguments) { + this.name = name; + this.methodHandle = ImmutableMethodHandleReference.of(methodHandle); + this.methodName = methodName; + this.methodProto = ImmutableMethodProtoReference.of(methodProto); + this.extraArguments = ImmutableEncodedValueFactory.immutableListOf(extraArguments); + } + + public ImmutableCallSiteReference(@Nonnull String name, @Nonnull ImmutableMethodHandleReference methodHandle, + @Nonnull String methodName, @Nonnull ImmutableMethodProtoReference methodProto, + @Nullable ImmutableList extraArguments) { + this.name = name; + this.methodHandle = methodHandle; + this.methodName = methodName; + this.methodProto = methodProto; + this.extraArguments = ImmutableUtils.nullToEmptyList(extraArguments); + } + + @Nonnull + public static ImmutableCallSiteReference of(@Nonnull CallSiteReference callSiteReference) { + if (callSiteReference instanceof ImmutableCallSiteReference) { + return (ImmutableCallSiteReference) callSiteReference; + } + return new ImmutableCallSiteReference(callSiteReference.getName(), + ImmutableMethodHandleReference.of(callSiteReference.getMethodHandle()), + callSiteReference.getMethodName(), + ImmutableMethodProtoReference.of(callSiteReference.getMethodProto()), + ImmutableEncodedValueFactory.immutableListOf(callSiteReference.getExtraArguments())); + } + + @Nonnull @Override public String getName() { return name; } + @Nonnull @Override public MethodHandleReference getMethodHandle() { return methodHandle; } + @Nonnull @Override public String getMethodName() { return methodName; } + @Nonnull @Override public MethodProtoReference getMethodProto() { return methodProto; } + @Nonnull @Override public List getExtraArguments() { return extraArguments; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodHandleReference.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodHandleReference.java new file mode 100644 index 00000000..733dd541 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodHandleReference.java @@ -0,0 +1,87 @@ +/* + * Copyright 2018, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.immutable.reference; + +import org.jf.dexlib2.MethodHandleType; +import org.jf.dexlib2.base.reference.BaseMethodHandleReference; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodHandleReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; + +public class ImmutableMethodHandleReference extends BaseMethodHandleReference implements ImmutableReference { + protected final int methodHandleType; + @Nonnull protected final ImmutableReference memberReference; + + public ImmutableMethodHandleReference(int methodHandleType, @Nonnull ImmutableReference memberReference) { + this.methodHandleType = methodHandleType; + this.memberReference = memberReference; + } + + public ImmutableMethodHandleReference(int methodHandleType, @Nonnull Reference memberReference) { + this.methodHandleType = methodHandleType; + this.memberReference = ImmutableReferenceFactory.of(memberReference); + } + + @Nonnull + public static ImmutableMethodHandleReference of(@Nonnull MethodHandleReference methodHandleReference) { + if (methodHandleReference instanceof ImmutableMethodHandleReference) { + return (ImmutableMethodHandleReference) methodHandleReference; + } + int methodHandleType = methodHandleReference.getMethodHandleType(); + ImmutableReference memberReference; + + switch (methodHandleType) { + case MethodHandleType.INSTANCE_GET: + case MethodHandleType.INSTANCE_PUT: + case MethodHandleType.STATIC_GET: + case MethodHandleType.STATIC_PUT: + memberReference = ImmutableFieldReference.of( + (FieldReference) methodHandleReference.getMemberReference()); + break; + case MethodHandleType.INVOKE_INSTANCE: + case MethodHandleType.INVOKE_STATIC: + memberReference = ImmutableMethodReference.of( + (MethodReference) methodHandleReference.getMemberReference()); + break; + default: + throw new ExceptionWithContext("Invalid method handle type: %d", methodHandleType); + } + return new ImmutableMethodHandleReference(methodHandleType, memberReference); + } + + @Override public int getMethodHandleType() { return methodHandleType; } + @Nonnull @Override public Reference getMemberReference() { return memberReference; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java index 8c2afe59..d1c62e14 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java @@ -35,16 +35,22 @@ import com.google.common.collect.ImmutableList; import org.jf.dexlib2.base.reference.BaseMethodProtoReference; import org.jf.dexlib2.iface.reference.MethodProtoReference; import org.jf.dexlib2.immutable.util.CharSequenceConverter; - -import java.util.List; +import org.jf.util.ImmutableUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class ImmutableMethodProtoReference extends BaseMethodProtoReference implements ImmutableReference { @Nonnull protected final ImmutableList parameters; @Nonnull protected final String returnType; + public ImmutableMethodProtoReference(@Nullable ImmutableList parameters, + @Nonnull String returnType) { + this.parameters = ImmutableUtils.nullToEmptyList(parameters); + this.returnType = returnType; + } + public ImmutableMethodProtoReference(@Nullable Iterable parameters, @Nonnull String returnType) { this.parameters = CharSequenceConverter.immutableStringList(parameters); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java index d0007479..c611844c 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java @@ -55,6 +55,12 @@ public class ImmutableReferenceFactory { if (reference instanceof MethodProtoReference) { return ImmutableMethodProtoReference.of((MethodProtoReference) reference); } + if (reference instanceof CallSiteReference) { + return ImmutableCallSiteReference.of((CallSiteReference) reference); + } + if (reference instanceof MethodHandleReference) { + return ImmutableMethodHandleReference.of((MethodHandleReference) reference); + } throw new ExceptionWithContext("Invalid reference type"); } @@ -71,6 +77,10 @@ public class ImmutableReferenceFactory { return ImmutableMethodReference.of((MethodReference)reference); case ReferenceType.METHOD_PROTO: return ImmutableMethodProtoReference.of((MethodProtoReference)reference); + case ReferenceType.CALL_SITE: + return ImmutableCallSiteReference.of((CallSiteReference) reference); + case ReferenceType.METHOD_HANDLE: + return ImmutableMethodHandleReference.of((MethodHandleReference) reference); } throw new ExceptionWithContext("Invalid reference type: %d", referenceType); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java index db5c84ab..f22e8c58 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java @@ -77,6 +77,10 @@ public class ImmutableEncodedValueFactory { return ImmutableNullEncodedValue.INSTANCE; case ValueType.BOOLEAN: return ImmutableBooleanEncodedValue.of((BooleanEncodedValue)encodedValue); + case ValueType.METHOD_HANDLE: + return ImmutableMethodHandleEncodedValue.of((MethodHandleEncodedValue) encodedValue); + case ValueType.METHOD_TYPE: + return ImmutableMethodTypeEncodedValue.of((MethodTypeEncodedValue) encodedValue); default: Preconditions.checkArgument(false); return null; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodHandleEncodedValue.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodHandleEncodedValue.java new file mode 100644 index 00000000..cc893ea7 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodHandleEncodedValue.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseMethodHandleEncodedValue; +import org.jf.dexlib2.iface.value.MethodHandleEncodedValue; +import org.jf.dexlib2.immutable.reference.ImmutableMethodHandleReference; + +import javax.annotation.Nonnull; + +public class ImmutableMethodHandleEncodedValue extends BaseMethodHandleEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final ImmutableMethodHandleReference methodHandleReference; + + public ImmutableMethodHandleEncodedValue(@Nonnull ImmutableMethodHandleReference methodHandleReference) { + this.methodHandleReference = methodHandleReference; + } + + @Nonnull + public static ImmutableMethodHandleEncodedValue of(@Nonnull MethodHandleEncodedValue methodHandleEncodedValue) { + if (methodHandleEncodedValue instanceof ImmutableMethodHandleEncodedValue) { + return (ImmutableMethodHandleEncodedValue) methodHandleEncodedValue; + } + return new ImmutableMethodHandleEncodedValue( + ImmutableMethodHandleReference.of(methodHandleEncodedValue.getValue())); + } + + @Nonnull @Override public ImmutableMethodHandleReference getValue() { return methodHandleReference; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodTypeEncodedValue.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodTypeEncodedValue.java new file mode 100644 index 00000000..3aa13a10 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodTypeEncodedValue.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseMethodTypeEncodedValue; +import org.jf.dexlib2.iface.value.MethodTypeEncodedValue; +import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference; + +import javax.annotation.Nonnull; + +public class ImmutableMethodTypeEncodedValue extends BaseMethodTypeEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final ImmutableMethodProtoReference methodProtoReference; + + public ImmutableMethodTypeEncodedValue(@Nonnull ImmutableMethodProtoReference methodProtoReference) { + this.methodProtoReference = methodProtoReference; + } + + @Nonnull + public static ImmutableMethodTypeEncodedValue of(@Nonnull MethodTypeEncodedValue methodTypeEncodedValue) { + if (methodTypeEncodedValue instanceof ImmutableMethodTypeEncodedValue) { + return (ImmutableMethodTypeEncodedValue) methodTypeEncodedValue; + } + return new ImmutableMethodTypeEncodedValue( + ImmutableMethodProtoReference.of(methodTypeEncodedValue.getValue())); + } + + @Nonnull @Override public ImmutableMethodProtoReference getValue() { return methodProtoReference; } +}