Skip to content

Commit

Permalink
[DEX] Detail dalvik annotation signature processing
Browse files Browse the repository at this point in the history
  • Loading branch information
REAndroid committed Dec 5, 2024
1 parent a46891a commit 4f2d30d
Show file tree
Hide file tree
Showing 7 changed files with 1,204 additions and 14 deletions.
33 changes: 19 additions & 14 deletions src/main/java/com/reandroid/dex/dalvik/DalvikSignature.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,20 @@
import com.reandroid.dex.common.AnnotationVisibility;
import com.reandroid.dex.key.*;
import com.reandroid.dex.program.AnnotatedProgram;
import com.reandroid.utils.StringsUtil;

import java.util.Iterator;

public class DalvikSignature extends DalvikAnnotation {

private DalvikSignature(AnnotatedProgram annotatedProgram) {
super(annotatedProgram, TypeKey.DALVIK_Signature);
}

public String[] values() {
String[] values = getArrayKey().getStringValues();
if (values == null) {
values = new String[0];
}
return values;
}
public void values(String[] values) {
setArrayKey(ArrayValueKey.of(values));
public Iterator<String> values() {
return getArrayKey().stringValuesIterator();
}

public ArrayValueKey getArrayKey() {
ArrayValueKey key = (ArrayValueKey) getKey().getValue(Key.DALVIK_value);
if (key == null) {
Expand All @@ -47,12 +44,20 @@ public void setArrayKey(ArrayValueKey arrayKey) {
}

public String getString() {
String[] values = values();
StringBuilder builder = new StringBuilder();
for (String value : values) {
builder.append(value);
return StringsUtil.join(values(), "");
}
public DalvikSignatureKey getSignature() {
return DalvikSignatureKey.parse(getString());
}
public void setSignature(DalvikSignatureKey key) {
setArrayKey(key.toStringValues());
}

public void replace(TypeKey search, TypeKey replace) {
DalvikSignatureKey signatureKey = getSignature();
if (signatureKey != null) {
setSignature(signatureKey.replaceKey(search, replace));
}
return builder.toString();
}

@Override
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/reandroid/dex/key/ArrayKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ public String toString(String separator) {
}
}

@Override
public ArrayKey replaceKey(Key search, Key replace) {
return (ArrayKey) super.replaceKey(search, replace);
}

@Override
public int compareTo(Object obj) {
if (obj == this) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/reandroid/dex/key/ArrayValueKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
import com.reandroid.dex.smali.SmaliParseException;
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.collection.ComputeIterator;

import java.io.IOException;
import java.util.Comparator;
import java.util.Iterator;
import java.util.function.Predicate;

public class ArrayValueKey extends ArrayKey {
Expand All @@ -35,6 +37,10 @@ private ArrayValueKey(Key[] elements) {
super(elements);
}

public Iterator<String> stringValuesIterator() {
return ComputeIterator.of(iterator(StringKey.class), StringKey::getString);
}

public boolean isStrings() {
return ArrayKeyHelper.isAllTypeOf(StringKey.class, this);
}
Expand Down
165 changes: 165 additions & 0 deletions src/main/java/com/reandroid/dex/key/DalvikSignatureKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reandroid.dex.key;

import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.ObjectsUtil;
import com.reandroid.utils.StringsUtil;
import com.reandroid.utils.collection.ArrayCollection;
import com.reandroid.utils.collection.CombiningIterator;
import com.reandroid.utils.collection.IterableIterator;

import java.io.IOException;
import java.util.Iterator;

public class DalvikSignatureKey implements Key {

private final ArrayKey elements;

private DalvikSignatureKey(ArrayKey elements) {
this.elements = elements;
}

public Iterator<ParameterisedTypeKey> iterator() {
return ObjectsUtil.cast(getElements().iterator());
}
public int size() {
return getElements().size();
}
public ParameterisedTypeKey get(int i) {
return (ParameterisedTypeKey) getElements().get(i);
}

private ArrayKey getElements() {
return elements;
}
private DalvikSignatureKey changeElements(ArrayKey elements) {
if (getElements().equals(elements)) {
return this;
}
return new DalvikSignatureKey(elements);
}

public Iterator<TypeKey> getTypes() {
return new IterableIterator<ParameterisedTypeKey, TypeKey>(iterator()) {
@Override
public Iterator<TypeKey> iterator(ParameterisedTypeKey element) {
return element.getTypes();
}
};
}

public ArrayValueKey toStringValues() {
SignatureStringsBuilder builder = new SignatureStringsBuilder();
ArrayKey elements = getElements();
int size = elements.size();
for (int i = 0; i < size; i++) {
ParameterisedTypeKey key = (ParameterisedTypeKey) elements.get(i);
key.buildSignature(builder);
}
builder.flush();
return builder.build();
}

@Override
public DalvikSignatureKey replaceKey(Key search, Key replace) {
if (search.equals(this)) {
return (DalvikSignatureKey) replace;
}
ArrayKey arrayKey = getElements();
arrayKey = arrayKey.replaceKey(search, replace);
return changeElements(arrayKey);
}

@Override
public Iterator<? extends Key> mentionedKeys() {
return CombiningIterator.singleOne(this,
new IterableIterator<ParameterisedTypeKey, Key>(iterator()) {
@Override
public Iterator<Key> iterator(ParameterisedTypeKey element) {
return ObjectsUtil.cast(element.mentionedKeys());
}
});
}

@Override
public int compareTo(Object obj) {
if (obj == null) {
return -1;
}
if (!(obj instanceof DalvikSignatureKey)) {
return StringsUtil.compareToString(this, obj);
}
DalvikSignatureKey key = (DalvikSignatureKey) obj;
return CompareUtil.compare(getElements(), key.getElements());
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof DalvikSignatureKey)) {
return false;
}
DalvikSignatureKey that = (DalvikSignatureKey) obj;
return ObjectsUtil.equals(getElements(), that.getElements());
}

@Override
public int hashCode() {
return ObjectsUtil.hash(getElements());
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
ArrayKey elements = getElements();
int size = elements.size();
for (int i = 0; i < size; i ++) {
((ParameterisedTypeKey) elements.get(i)).appendString(builder);
}
return builder.toString();
}

public static DalvikSignatureKey parseAnnotationValue(ArrayValueKey stringsKey) {
if (stringsKey != null) {
return parse(StringsUtil.join(stringsKey.stringValuesIterator(), ""));
}
return null;
}
public static DalvikSignatureKey parse(String text) {
try {
return read(SmaliReader.of(text));
} catch (IOException ignored) {
return null;
}
}
public static DalvikSignatureKey read(SmaliReader reader) throws IOException {
reader.skipWhitespacesOrComment();
Key[] elements = parseElements(reader);
return new DalvikSignatureKey(ArrayKey.create(elements));
}
private static Key[] parseElements(SmaliReader reader) throws IOException {
ArrayCollection<ParameterisedTypeKey> keyList = new ArrayCollection<>();
while (!reader.finished() && !reader.skipWhitespaces()) {
ParameterisedTypeKey typeKey = ParameterisedTypeKey.read(reader);
keyList.add(typeKey);
}
return keyList.toArrayFill(new Key[keyList.size()]);
}

}
Loading

0 comments on commit 4f2d30d

Please sign in to comment.