All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.evaluation.executor.StringReflectionExecutor Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2023 Guardsquare NV
 *
 * 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 proguard.evaluation.executor;

import static proguard.classfile.ClassConstants.NAME_JAVA_LANG_STRING;
import static proguard.classfile.ClassConstants.NAME_JAVA_LANG_STRING_BUFFER;
import static proguard.classfile.ClassConstants.NAME_JAVA_LANG_STRING_BUILDER;
import static proguard.classfile.ClassConstants.TYPE_JAVA_LANG_STRING;
import static proguard.classfile.ClassConstants.TYPE_JAVA_LANG_STRING_BUFFER;
import static proguard.classfile.ClassConstants.TYPE_JAVA_LANG_STRING_BUILDER;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import proguard.classfile.MethodSignature;
import proguard.evaluation.executor.instancehandler.ExecutorInstanceHandler;
import proguard.evaluation.executor.instancehandler.ExecutorMethodInstanceHandler;
import proguard.evaluation.value.ParticularReferenceValue;
import proguard.evaluation.value.ReferenceValue;
import proguard.evaluation.value.object.AnalyzedObject;
import proguard.evaluation.value.object.AnalyzedObjectFactory;
import proguard.util.ConstantMatcher;
import proguard.util.FixedStringMatcher;
import proguard.util.StringMatcher;

/**
 * This {@link ReflectionExecutor} supports methods of the classes {@link String}, {@link
 * StringBuilder} and {@link StringBuffer}.
 */
public class StringReflectionExecutor extends ReflectionExecutor {
  @Override
  public Optional getInstanceOrCopyIfMutable(ReferenceValue instanceValue) {

    if (!(instanceValue instanceof ParticularReferenceValue)) {
      return Optional.empty();
    }

    AnalyzedObject instanceObject = instanceValue.getValue();

    if (instanceObject.isModeled()) {
      // Types we want to execute reflective are allowed to be modeled in some situations by the
      // analysis, in this case execution via reflection is not possible
      return Optional.empty();
    }

    if (instanceObject.isNull()) {
      // A null instance would throw a NPE but the analysis does not support it, so we just do not
      // perform the execution
      return Optional.empty();
    }

    String type = instanceObject.getType();
    if (type == null) {
      throw new IllegalStateException("Unexpected null type on non-null instance object!");
    }
    switch (type) {
      case TYPE_JAVA_LANG_STRING_BUILDER:
        return Optional.of(
            new InstanceCopyResult(
                AnalyzedObjectFactory.createPrecise(
                    new StringBuilder((StringBuilder) instanceObject.getPreciseValue())),
                true));
      case TYPE_JAVA_LANG_STRING_BUFFER:
        return Optional.of(
            new InstanceCopyResult(
                AnalyzedObjectFactory.createPrecise(
                    new StringBuffer((StringBuffer) instanceObject.getPreciseValue())),
                true));
      case TYPE_JAVA_LANG_STRING:
        return Optional.of(new InstanceCopyResult(instanceObject, false));
      default:
        return Optional.empty();
    }
  }

  @Override
  public ExecutorInstanceHandler getDefaultInstanceHandler() {
    Map matcherMap = new HashMap<>();
    matcherMap.put(NAME_JAVA_LANG_STRING, new FixedStringMatcher("toString"));
    matcherMap.put(NAME_JAVA_LANG_STRING_BUFFER, new ConstantMatcher(true));
    matcherMap.put(NAME_JAVA_LANG_STRING_BUILDER, new ConstantMatcher(true));

    return new ExecutorMethodInstanceHandler(matcherMap);
  }

  @Override
  public List getSupportedMethodSignatures() {
    return Stream.of(
            new MethodSignature(NAME_JAVA_LANG_STRING),
            new MethodSignature(NAME_JAVA_LANG_STRING_BUILDER),
            new MethodSignature(NAME_JAVA_LANG_STRING_BUFFER))
        .collect(Collectors.toList());
  }

  /** A builder for {@link StringReflectionExecutor}. */
  public static class Builder implements Executor.Builder {
    @Override
    public StringReflectionExecutor build() {
      return new StringReflectionExecutor();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy