Home | History | Annotate | Download | only in obfuscate
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2009 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.obfuscate;
     22 
     23 import java.util.*;
     24 
     25 
     26 /**
     27  * This <code>NameFactory</code> generates unique short names, using mixed-case
     28  * characters or lower-case characters only.
     29  *
     30  * @author Eric Lafortune
     31  */
     32 public class SimpleNameFactory implements NameFactory
     33 {
     34     private static final int CHARACTER_COUNT = 26;
     35 
     36     private static final List cachedMixedCaseNames = new ArrayList();
     37     private static final List cachedLowerCaseNames = new ArrayList();
     38 
     39     private final boolean generateMixedCaseNames;
     40     private int     index = 0;
     41 
     42 
     43     /**
     44      * Creates a new <code>SimpleNameFactory</code> that generates mixed-case names.
     45      */
     46     public SimpleNameFactory()
     47     {
     48         this(true);
     49     }
     50 
     51 
     52     /**
     53      * Creates a new <code>SimpleNameFactory</code>.
     54      * @param generateMixedCaseNames a flag to indicate whether the generated
     55      *                               names will be mixed-case, or lower-case only.
     56      */
     57     public SimpleNameFactory(boolean generateMixedCaseNames)
     58     {
     59         this.generateMixedCaseNames = generateMixedCaseNames;
     60     }
     61 
     62 
     63     // Implementations for NameFactory.
     64 
     65     public void reset()
     66     {
     67         index = 0;
     68     }
     69 
     70 
     71     public String nextName()
     72     {
     73         return name(index++);
     74     }
     75 
     76 
     77     /**
     78      * Returns the name at the given index.
     79      */
     80     private String name(int index)
     81     {
     82         // Which cache do we need?
     83         List cachedNames = generateMixedCaseNames ?
     84             cachedMixedCaseNames :
     85             cachedLowerCaseNames;
     86 
     87         // Do we have the name in the cache?
     88         if (index < cachedNames.size())
     89         {
     90             return (String)cachedNames.get(index);
     91         }
     92 
     93         // Create a new name and cache it.
     94         String name = newName(index);
     95         cachedNames.add(index, name);
     96 
     97         return name;
     98     }
     99 
    100 
    101     /**
    102      * Creates and returns the name at the given index.
    103      */
    104     private String newName(int index)
    105     {
    106         // If we're allowed to generate mixed-case names, we can use twice as
    107         // many characters.
    108         int totalCharacterCount = generateMixedCaseNames ?
    109             2 * CHARACTER_COUNT :
    110             CHARACTER_COUNT;
    111 
    112         int baseIndex = index / totalCharacterCount;
    113         int offset    = index % totalCharacterCount;
    114 
    115         char newChar = charAt(offset);
    116 
    117         String newName = baseIndex == 0 ?
    118             new String(new char[] { newChar }) :
    119             (name(baseIndex-1) + newChar);
    120 
    121         return newName;
    122     }
    123 
    124 
    125     /**
    126      * Returns the character with the given index, between 0 and the number of
    127      * acceptable characters.
    128      */
    129     private char charAt(int index)
    130     {
    131         return (char)((index < CHARACTER_COUNT ? 'a' - 0               :
    132                                                  'A' - CHARACTER_COUNT) + index);
    133     }
    134 
    135 
    136     public static void main(String[] args)
    137     {
    138         System.out.println("Some mixed-case names:");
    139         printNameSamples(new SimpleNameFactory(true), 60);
    140         System.out.println("Some lower-case names:");
    141         printNameSamples(new SimpleNameFactory(false), 60);
    142         System.out.println("Some more mixed-case names:");
    143         printNameSamples(new SimpleNameFactory(true), 80);
    144         System.out.println("Some more lower-case names:");
    145         printNameSamples(new SimpleNameFactory(false), 80);
    146     }
    147 
    148 
    149     private static void printNameSamples(SimpleNameFactory factory, int count)
    150     {
    151         for (int counter = 0; counter < count; counter++)
    152         {
    153             System.out.println("  ["+factory.nextName()+"]");
    154         }
    155     }
    156 }
    157