PackageIdentifier.java :  » Development » jode » jode » obfuscator » Java Open Source

Java Open Source » Development » jode 
jode » jode » obfuscator » PackageIdentifier.java
/* PackageIdentifier Copyright (C) 1999-2002 Jochen Hoenicke.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, 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 Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: PackageIdentifier.java.in,v 1.6.2.3 2002/05/28 17:34:14 hoenicke Exp $
 */

package jode.obfuscator;
import jode.GlobalOptions;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import java.lang.reflect.Modifier;
import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class PackageIdentifier extends Identifier {
    ClassBundle bundle;
    PackageIdentifier parent;
    String name;
    String fullName;

    boolean loadOnDemand;
    Map loadedClasses;
    List swappedClasses;

    public PackageIdentifier(ClassBundle bundle, 
           PackageIdentifier parent,
           String fullName, String name) {
  super(name);
  this.bundle = bundle;
  this.parent = parent;
  this.fullName = fullName;
  this.name = name;
  this.loadedClasses = new HashMap();
    }

    /**
     * Marks the parent package as preserved, too.
     */
    protected void setSinglePreserved() {
  if (parent != null)
      parent.setPreserved();
    }

    public void setLoadOnDemand() {
  if (loadOnDemand)
      return;
  loadOnDemand = true;
  if ((Main.stripping & Main.STRIP_UNREACH) == 0) {
      String fullNamePrefix =
    (fullName.length() > 0) ? fullName + "." : "";

      // Load all classes and packages now, so they don't get stripped
      Enumeration enum = 
    ClassInfo.getClassesAndPackages(getFullName());
      while (enum.hasMoreElements()) {
    String subclazz = ((String)enum.nextElement()).intern();
    if (loadedClasses.containsKey(subclazz))
        continue;
    String subFull = (fullNamePrefix + subclazz).intern();
    
    if (ClassInfo.isPackage(subFull)) {
        PackageIdentifier ident = new PackageIdentifier
      (bundle, this, subFull, subclazz);
        loadedClasses.put(subclazz, ident);
        swappedClasses = null;
        ident.setLoadOnDemand();
    } else {
        ClassIdentifier ident = new ClassIdentifier
      (this, subFull, subclazz, ClassInfo.forName(subFull));
        
        if (GlobalOptions.verboseLevel > 1)
      GlobalOptions.err.println("preloading Class "
              + subFull);
        loadedClasses.put(subclazz, ident);
        swappedClasses = null;
        bundle.addClassIdentifier(ident);
        ((ClassIdentifier) ident).initClass();
    }
      }
      // Everything is loaded, we don't need to load on demand anymore.
      loadOnDemand = false;
  }
    }

    public Identifier getIdentifier(String name) {
  if (loadOnDemand) {
      Identifier ident = loadClass(name);
      return ident;
  }
  int index = name.indexOf('.');
  if (index == -1)
      return (Identifier) loadedClasses.get(name);
  else {
      PackageIdentifier pack = (PackageIdentifier) 
    loadedClasses.get(name.substring(0, index));
      if (pack != null)
    return pack.getIdentifier(name.substring(index+1));
      else
    return null;
  }
    }

    public Identifier loadClass(String name) {
  int index = name.indexOf('.');
  if (index == -1) {
      Identifier ident = (Identifier) loadedClasses.get(name);
      if (ident == null) {
    String subFull = 
       (fullName.length() > 0) ? fullName + "."+ name : name;
    subFull = subFull.intern();
    if (ClassInfo.isPackage(subFull)) {
        PackageIdentifier pack
      = new PackageIdentifier(bundle, this, subFull, name);
        loadedClasses.put(name, pack);
        swappedClasses = null;
        pack.setLoadOnDemand();
        ident = pack;
    } else if (!ClassInfo.exists(subFull)) {
        GlobalOptions.err.println("Warning: Can't find class "
                + subFull);
        Thread.dumpStack();
    } else {
        ident = new ClassIdentifier(this, subFull, name, 
            ClassInfo.forName(subFull));
        loadedClasses.put(name, ident);
        swappedClasses = null;
        bundle.addClassIdentifier(ident);
        ((ClassIdentifier) ident).initClass();
    }
      }
      return ident;
  } else {
      String subpack = name.substring(0, index);
      PackageIdentifier pack = 
    (PackageIdentifier) loadedClasses.get(subpack);
      if (pack == null) {
    String subFull = (fullName.length() > 0)
        ? fullName + "."+ subpack : subpack;
    subFull = subFull.intern();
    if (ClassInfo.isPackage(subFull)) {
        pack = new PackageIdentifier(bundle, this, 
             subFull, subpack);
        loadedClasses.put(subpack, pack);
        swappedClasses = null;
        if (loadOnDemand)
      pack.setLoadOnDemand();
    }
      }
      
      if (pack != null)
    return pack.loadClass(name.substring(index+1));
      else
    return null;
  }
    }

    public void loadMatchingClasses(IdentifierMatcher matcher) {
  String component = matcher.getNextComponent(this);
  if (component != null) {
      Identifier ident = (Identifier) loadedClasses.get(component);
      if (ident == null) {
    component = component.intern();
    String subFull = (fullName.length() > 0)
        ? fullName + "."+ component : component;
    subFull = subFull.intern();
    if (ClassInfo.isPackage(subFull)) {
        ident = new PackageIdentifier(bundle, this, 
              subFull, component);
        loadedClasses.put(component, ident);
        swappedClasses = null;
        if (loadOnDemand)
      ((PackageIdentifier) ident).setLoadOnDemand();
    } else if (ClassInfo.exists(subFull)) {
        if (GlobalOptions.verboseLevel > 1)
      GlobalOptions.err.println("loading Class " +subFull);
        ident = new ClassIdentifier(this, subFull, component, 
            ClassInfo.forName(subFull));
        if (loadOnDemand || matcher.matches(ident)) {
      loadedClasses.put(component, ident);
      swappedClasses = null;
      bundle.addClassIdentifier(ident);
      ((ClassIdentifier) ident).initClass();
        }
    } else {
        GlobalOptions.err.println
      ("Warning: Can't find class/package " + subFull);
    }
      }
      if (ident instanceof PackageIdentifier) {
    if (matcher.matches(ident)) {
        if (GlobalOptions.verboseLevel > 0)
      GlobalOptions.err.println("loading Package "
              +ident.getFullName());
        ((PackageIdentifier) ident).setLoadOnDemand();
    }

    if (matcher.matchesSub(ident, null))
        ((PackageIdentifier) ident).loadMatchingClasses(matcher);
      }
  } else {
      String fullNamePrefix = 
    (fullName.length() > 0) ? fullName + "." : "";
      /* Load all matching classes and packages */
      Enumeration enum = 
    ClassInfo.getClassesAndPackages(getFullName());
      while (enum.hasMoreElements()) {
    String subclazz = ((String)enum.nextElement()).intern();
    if (loadedClasses.containsKey(subclazz))
        continue;
    String subFull = (fullNamePrefix + subclazz).intern();
    
    if (matcher.matchesSub(this, subclazz)) {
        if (ClassInfo.isPackage(subFull)) {
      if (GlobalOptions.verboseLevel > 0)
          GlobalOptions.err.println("loading Package "
                  + subFull);
      PackageIdentifier ident = new PackageIdentifier
          (bundle, this, subFull, subclazz);
      loadedClasses.put(subclazz, ident);
      swappedClasses = null;
      if (loadOnDemand || matcher.matches(ident))
          ident.setLoadOnDemand();
        } else {
      ClassIdentifier ident = new ClassIdentifier
          (this, subFull, subclazz, 
           ClassInfo.forName(subFull));

      if (loadOnDemand || matcher.matches(ident)) {
          if (GlobalOptions.verboseLevel > 1)
        GlobalOptions.err.println("loading Class "
                + subFull);
          loadedClasses.put(subclazz, ident);
          swappedClasses = null;
          bundle.addClassIdentifier(ident);
          ((ClassIdentifier) ident).initClass();
      }
        }
    }
      }
      List list = new ArrayList();
      list.addAll(loadedClasses.values());
      for (Iterator i = list.iterator(); i.hasNext(); ) {
    Identifier ident = (Identifier) i.next();
    if (ident instanceof PackageIdentifier) {
        if (matcher.matches(ident))
      ((PackageIdentifier) ident).setLoadOnDemand();
        
        if (matcher.matchesSub(ident, null))
      ((PackageIdentifier) ident)
          .loadMatchingClasses(matcher);
    }
      }
  }
    }

    public void applyPreserveRule(IdentifierMatcher preserveRule) {
  if (loadOnDemand)
      loadMatchingClasses(preserveRule);
  super.applyPreserveRule(preserveRule);
    }

    /**
     * @return the full qualified name.
     */
    public String getFullName() {
  return fullName;
    }

    /**
     * @return the full qualified alias.
     */
    public String getFullAlias() {
  if (parent != null) {
      String parentAlias = parent.getFullAlias();
      String alias = getAlias();
      if (alias.length() == 0)
    return parentAlias;
      else if (parentAlias.length() == 0)
    return alias;
      else
    return parentAlias + "." + alias;
  }
  return "";
    }

    public void buildTable(Renamer renameRule) {
  loadOnDemand = false;
  super.buildTable(renameRule);
    }

    public void doTransformations() {
  for (Iterator i = getChilds(); i.hasNext(); ) {
      Identifier ident = (Identifier) i.next();
      if (ident instanceof ClassIdentifier) {
    ((ClassIdentifier) ident).doTransformations();
      } else
    ((PackageIdentifier) ident).doTransformations();
  }
    }

    public void readTable(Map table) {
  if (parent != null)
      setAlias((String) table.get(getFullName()));
  for (Iterator i = loadedClasses.values().iterator(); i.hasNext(); ) {
      Identifier ident = (Identifier) i.next();
      if ((Main.stripping & Main.STRIP_UNREACH) == 0
    || ident.isReachable())
    ident.readTable(table);
  }
    }

    public Identifier getParent() {
  return parent;
    }

    public String getName() {
  return name;
    }

    public String getType() {
  return "package";
    }

    public Iterator getChilds() {
  /* Since loadedClasses is somewhat sorted by the hashcode
   * of the _original_ names, swap it here to prevent to guess
   * even parts of the names.
   */
  if (swappedClasses == null) {
      swappedClasses = Arrays.asList(loadedClasses.values().toArray());
      Collections.shuffle(swappedClasses, Main.rand);
  }
  return swappedClasses.iterator();
    }

    public void storeClasses(ZipOutputStream zip) {
  for (Iterator i = getChilds(); i.hasNext(); ) {
      Identifier ident = (Identifier) i.next();
      if ((Main.stripping & Main.STRIP_UNREACH) != 0
    && !ident.isReachable()) {
    if (GlobalOptions.verboseLevel > 4)
        GlobalOptions.err.println("Class/Package "
             + ident.getFullName()
             + " is not reachable");
    continue;
      }
      if (ident instanceof PackageIdentifier)
    ((PackageIdentifier) ident).storeClasses(zip);
      else {
    try {
        String filename = ident.getFullAlias().replace('.','/')
      + ".class";
        zip.putNextEntry(new ZipEntry(filename));
        DataOutputStream out = new DataOutputStream
      (new BufferedOutputStream(zip));
        ((ClassIdentifier) ident).storeClass(out);
        out.flush();
        zip.closeEntry();
    } catch (java.io.IOException ex) {
        GlobalOptions.err.println("Can't write Class "
                + ident.getName());
        ex.printStackTrace(GlobalOptions.err);
    }
      }
  }
    }

    public void storeClasses(File destination) {
  File newDest = (parent == null) ? destination 
      : new File(destination, getAlias());
  if (!newDest.exists() && !newDest.mkdir()) {
      GlobalOptions.err.println("Could not create directory "
           +newDest.getPath()+", check permissions.");
  }
  for (Iterator i = getChilds(); i.hasNext(); ) {
      Identifier ident = (Identifier) i.next();
      if ((Main.stripping & Main.STRIP_UNREACH) != 0
    && !ident.isReachable()) {
    if (GlobalOptions.verboseLevel > 4)
        GlobalOptions.err.println("Class/Package "
                + ident.getFullName()
                + " is not reachable");
    continue;
      }
      if (ident instanceof PackageIdentifier)
    ((PackageIdentifier) ident)
        .storeClasses(newDest);
      else {
    try {
        File file = new File(newDest, ident.getAlias()+".class");
//         if (file.exists()) {
//       GlobalOptions.err.println
//           ("Refuse to overwrite existing class file "
//            +file.getPath()+".  Remove it first.");
//       return;
//         }
        DataOutputStream out = new DataOutputStream
      (new BufferedOutputStream
       (new FileOutputStream(file)));
        ((ClassIdentifier) ident).storeClass(out);
        out.close();
    } catch (java.io.IOException ex) {
        GlobalOptions.err.println("Can't write Class "
             + ident.getName());
        ex.printStackTrace(GlobalOptions.err);
    }
      }
  }
    }

    public String toString() {
  return (parent == null) ? "base package" : getFullName();
    }

    public boolean contains(String newAlias, Identifier except) {
  for (Iterator i = loadedClasses.values().iterator(); i.hasNext(); ) {
      Identifier ident = (Identifier)i.next();
      if (ident != except) {
    if (((Main.stripping & Main.STRIP_UNREACH) == 0
         || ident.isReachable())
      && ident.getAlias().equalsIgnoreCase(newAlias))
        return true;
    if (ident instanceof PackageIdentifier
        && ident.getAlias().length() == 0
        && (((PackageIdentifier) ident)
      .contains(newAlias, this)))
        return true;
      }
  }
  if (getAlias().length() == 0
      && parent != null
      && parent != except
      && parent.contains(newAlias, this))
      return true;
  return false;
    }

    public boolean conflicting(String newAlias) {
  return parent.contains(newAlias, this);
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.