001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.obfuscate;
022:
023: import java.util.*;
024:
025: /**
026: * This <code>NameFactory</code> generates unique short names, using mixed-case
027: * characters or lower-case characters only.
028: *
029: * @author Eric Lafortune
030: */
031: public class SimpleNameFactory implements NameFactory {
032: private static final int CHARACTER_COUNT = 26;
033:
034: private static final List cachedMixedCaseNames = new ArrayList();
035: private static final List cachedLowerCaseNames = new ArrayList();
036:
037: private final boolean generateMixedCaseNames;
038: private int index = 0;
039:
040: /**
041: * Creates a new <code>SimpleNameFactory</code> that generates mixed-case names.
042: */
043: public SimpleNameFactory() {
044: this (true);
045: }
046:
047: /**
048: * Creates a new <code>SimpleNameFactory</code>.
049: * @param generateMixedCaseNames a flag to indicate whether the generated
050: * names will be mixed-case, or lower-case only.
051: */
052: public SimpleNameFactory(boolean generateMixedCaseNames) {
053: this .generateMixedCaseNames = generateMixedCaseNames;
054: }
055:
056: // Implementations for NameFactory.
057:
058: public void reset() {
059: index = 0;
060: }
061:
062: public String nextName() {
063: return name(index++);
064: }
065:
066: /**
067: * Returns the name at the given index.
068: */
069: private String name(int index) {
070: // Which cache do we need?
071: List cachedNames = generateMixedCaseNames ? cachedMixedCaseNames
072: : cachedLowerCaseNames;
073:
074: // Do we have the name in the cache?
075: if (index < cachedNames.size()) {
076: return (String) cachedNames.get(index);
077: }
078:
079: // Create a new name and cache it.
080: String name = newName(index);
081: cachedNames.add(index, name);
082:
083: return name;
084: }
085:
086: /**
087: * Creates and returns the name at the given index.
088: */
089: private String newName(int index) {
090: // If we're allowed to generate mixed-case names, we can use twice as
091: // many characters.
092: int totalCharacterCount = generateMixedCaseNames ? 2 * CHARACTER_COUNT
093: : CHARACTER_COUNT;
094:
095: int baseIndex = index / totalCharacterCount;
096: int offset = index % totalCharacterCount;
097:
098: char newChar = charAt(offset);
099:
100: String newName = baseIndex == 0 ? new String(
101: new char[] { newChar })
102: : (name(baseIndex - 1) + newChar);
103:
104: return newName;
105: }
106:
107: /**
108: * Returns the character with the given index, between 0 and the number of
109: * acceptable characters.
110: */
111: private char charAt(int index) {
112: return (char) ((index < CHARACTER_COUNT ? 'a' - 0
113: : 'A' - CHARACTER_COUNT) + index);
114: }
115:
116: public static void main(String[] args) {
117: System.out.println("Some mixed-case names:");
118: printNameSamples(new SimpleNameFactory(true), 60);
119: System.out.println("Some lower-case names:");
120: printNameSamples(new SimpleNameFactory(false), 60);
121: System.out.println("Some more mixed-case names:");
122: printNameSamples(new SimpleNameFactory(true), 80);
123: System.out.println("Some more lower-case names:");
124: printNameSamples(new SimpleNameFactory(false), 80);
125: }
126:
127: private static void printNameSamples(SimpleNameFactory factory,
128: int count) {
129: for (int counter = 0; counter < count; counter++) {
130: System.out.println(" [" + factory.nextName() + "]");
131: }
132: }
133: }
|