1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
5b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.classfile.util;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.ClassConstants;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.Stack;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * A <code>DescriptorClassEnumeration</code> provides an enumeration of all
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes mentioned in a given descriptor or signature.
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class DescriptorClassEnumeration
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String  descriptor;
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int     index;
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int     nestingLevel;
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean isInnerClassName;
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String  accumulatedClassName;
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Stack   accumulatedClassNames;
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new DescriptorClassEnumeration for the given descriptor.
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public DescriptorClassEnumeration(String descriptor)
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.descriptor = descriptor;
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the number of classes contained in the descriptor. This
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * is the number of class names that the enumeration will return.
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public int classCount()
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int count = 0;
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        nextFluff();
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (hasMoreClassNames())
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            count++;
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            nextClassName();
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            nextFluff();
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        index = 0;
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return count;
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the enumeration can provide more class names from the
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * descriptor.
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean hasMoreClassNames()
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return index < descriptor.length();
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the next fluff (surrounding class names) from the descriptor.
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public String nextFluff()
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int fluffStartIndex = index;
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Find the first token marking the start of a class name 'L' or '.'.
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        loop: while (index < descriptor.length())
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch (descriptor.charAt(index++))
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_GENERIC_START:
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    nestingLevel++;
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Make sure we have a stack.
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (accumulatedClassNames == null)
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        accumulatedClassNames = new Stack();
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Remember the accumulated class name.
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    accumulatedClassNames.push(accumulatedClassName);
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_GENERIC_END:
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    nestingLevel--;
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Return to the accumulated class name outside the
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // generic block.
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    accumulatedClassName = (String)accumulatedClassNames.pop();
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    continue loop;
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_GENERIC_BOUND:
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    continue loop;
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_CLASS_START:
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // We've found the start of an ordinary class name.
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    nestingLevel += 2;
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    isInnerClassName = false;
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break loop;
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_CLASS_END:
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    nestingLevel -= 2;
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.EXTERNAL_INNER_CLASS_SEPARATOR:
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // We've found the start of an inner class name in a signature.
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    isInnerClassName = true;
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break loop;
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_GENERIC_VARIABLE_START:
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // We've found the start of a type identifier. Skip to the end.
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    while (descriptor.charAt(index++) != ClassConstants.INTERNAL_TYPE_CLASS_END);
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (nestingLevel == 1 &&
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                descriptor.charAt(index) != ClassConstants.INTERNAL_TYPE_GENERIC_END)
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // We're at the start of a type parameter. Skip to the start
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // of the bounds.
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                while (descriptor.charAt(index++) != ClassConstants.INTERNAL_TYPE_GENERIC_BOUND);
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return descriptor.substring(fluffStartIndex, index);
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the next class name from the descriptor.
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public String nextClassName()
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int classNameStartIndex = index;
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Find the first token marking the end of a class name '<' or ';'.
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        loop: while (true)
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch (descriptor.charAt(index))
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_GENERIC_START:
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.INTERNAL_TYPE_CLASS_END:
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case ClassConstants.EXTERNAL_INNER_CLASS_SEPARATOR:
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break loop;
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            index++;
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String className = descriptor.substring(classNameStartIndex, index);
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Recompose the inner class name if necessary.
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        accumulatedClassName = isInnerClassName ?
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            accumulatedClassName + ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR + className :
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            className;
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return accumulatedClassName;
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the most recently returned class name was a recomposed
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * inner class name from a signature.
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean isInnerClassName()
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return isInnerClassName;
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * A main method for testing the class name enumeration.
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public static void main(String[] args)
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            for (int index = 0; index < args.length; index++)
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                String descriptor = args[index];
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.out.println("Descriptor ["+descriptor+"]");
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                DescriptorClassEnumeration enumeration = new DescriptorClassEnumeration(descriptor);
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.out.println("  Fluff: ["+enumeration.nextFluff()+"]");
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                while (enumeration.hasMoreClassNames())
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    System.out.println("  Name:  ["+enumeration.nextClassName()+"]");
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    System.out.println("  Fluff: ["+enumeration.nextFluff()+"]");
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (Exception ex)
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ex.printStackTrace();
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
237