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

soot.DexClassProvider Maven / Gradle / Ivy

package soot;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 2012 Michael Markert, Frank Hartmann
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.iface.ClassDef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import soot.dexpler.DexFileProvider;
import soot.dexpler.Util;
import soot.options.Options;

/**
 * Looks for a dex file which includes the definition of a class.
 */
public class DexClassProvider implements ClassProvider {
  private static final Logger logger = LoggerFactory.getLogger(DexClassProvider.class);

  public static Set classesOfDex(DexBackedDexFile dexFile) {
    Set classes = new HashSet();
    for (ClassDef c : dexFile.getClasses()) {
      String name = Util.dottedClassName(c.getType());
      classes.add(name);
    }
    return classes;
  }

  /**
   * Provides the DexClassSource for the class.
   *
   * @param className
   *          class to provide.
   * @return a DexClassSource that defines the className named class.
   */
  public ClassSource find(String className) {
    ensureDexIndex();

    Map index = SourceLocator.v().dexClassIndex();
    File file = index.get(className);
    if (file == null) {
      return null;
    }

    return new DexClassSource(className, file);
  }

  /**
   * Checks whether the dex class index needs to be (re)built and triggers the build if necessary
   */
  protected void ensureDexIndex() {
    Map index = SourceLocator.v().dexClassIndex();
    if (index == null) {
      index = new HashMap();
      buildDexIndex(index, SourceLocator.v().classPath());
      SourceLocator.v().setDexClassIndex(index);
    }

    // Process the classpath extensions
    if (SourceLocator.v().getDexClassPathExtensions() != null) {
      buildDexIndex(SourceLocator.v().dexClassIndex(), new ArrayList<>(SourceLocator.v().getDexClassPathExtensions()));
      SourceLocator.v().clearDexClassPathExtensions();
    }
  }

  /**
   * Build index of ClassName-to-File mappings.
   *
   * @param index
   *          map to insert mappings into
   * @param classPath
   *          paths to index
   */
  private void buildDexIndex(Map index, List classPath) {
    for (String path : classPath) {
      try {
        File dexFile = new File(path);
        if (dexFile.exists()) {
          for (DexFileProvider.DexContainer container : DexFileProvider.v().getDexFromSource(dexFile)) {
            for (String className : classesOfDex(container.getBase())) {
              if (!index.containsKey(className)) {
                index.put(className, container.getFilePath());
              } else if (Options.v().verbose()) {
                logger.debug("" + String.format(
                    "Warning: Duplicate of class '%s' found in dex file '%s' from source '%s'. Omitting class.", className,
                    container.getDexName(), container.getFilePath().getCanonicalPath()));
              }
            }
          }
        }
      } catch (IOException e) {
        logger.warn("IO error while processing dex file '" + path + "'");
        logger.debug("Exception: " + e);
      } catch (Exception e) {
        logger.warn("exception while processing dex file '" + path + "'");
        logger.debug("Exception: " + e);
      }
    }

  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy