ShortestUsagePrinter.java revision b9cc48a43ed984587c939d02fba5316bf5c0df6e
1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
5b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Copyright (c) 2002-2013 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.shrink;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.attribute.*;
25b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.attribute.visitor.AttributeVisitor;
26b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.util.*;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.*;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.io.PrintStream;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This ClassVisitor     and MemberVisitor prints out the reasons why
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes and class members have been marked as being used.
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see UsageMarker
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ShortestUsagePrinter
41b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangextends      SimplifiedVisitor
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   ClassVisitor,
43b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             MemberVisitor,
44b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             AttributeVisitor
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final ShortestUsageMarker shortestUsageMarker;
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean             verbose;
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final PrintStream         ps;
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new UsagePrinter that prints verbosely to <code>System.out</code>.
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param shortestUsageMarker the usage marker that was used to mark the
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                            classes and class members.
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker)
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(shortestUsageMarker, true);
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new UsagePrinter that prints to the given stream.
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param shortestUsageMarker the usage marker that was used to mark the
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                            classes and class members.
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param verbose             specifies whether the output should be verbose.
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker,
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                boolean             verbose)
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(shortestUsageMarker, verbose, System.out);
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new UsagePrinter that prints to the given stream.
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param shortestUsageMarker the usage marker that was used to mark the
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                            classes and class members.
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param verbose             specifies whether the output should be verbose.
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param printStream         the stream to which to print.
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker,
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                boolean             verbose,
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                PrintStream         printStream)
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.shortestUsageMarker = shortestUsageMarker;
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.verbose             = verbose;
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.ps                  = printStream;
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ClassVisitor.
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramClass(ProgramClass programClass)
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the name of this class.
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println(ClassUtil.externalClassName(programClass.getName()));
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the reason for keeping this class.
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        printReason(programClass);
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitLibraryClass(LibraryClass libraryClass)
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the name of this class.
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println(ClassUtil.externalClassName(libraryClass.getName()));
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the reason for keeping this class.
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println("  is a library class.\n");
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for MemberVisitor.
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramField(ProgramClass programClass, ProgramField programField)
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the name of this field.
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String name = programField.getName(programClass);
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String type = programField.getDescriptor(programClass);
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println(ClassUtil.externalClassName(programClass.getName()) +
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   (verbose ?
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        ": " + ClassUtil.externalFullFieldDescription(0, name, type):
124b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                        "."  + name));
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the reason for keeping this method.
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        printReason(programField);
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the name of this method.
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String name = programMethod.getName(programClass);
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String type = programMethod.getDescriptor(programClass);
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
137b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        ps.print(ClassUtil.externalClassName(programClass.getName()) +
138b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                 (verbose ?
139b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                      ": " + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, name, type):
140b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                      "."  + name));
141b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        programMethod.attributesAccept(programClass, this);
142b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        ps.println();
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the reason for keeping this method.
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        printReason(programMethod);
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the name of this field.
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String name = libraryField.getName(libraryClass);
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String type = libraryField.getDescriptor(libraryClass);
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println(ClassUtil.externalClassName(libraryClass.getName()) +
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   (verbose ?
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        ": " + ClassUtil.externalFullFieldDescription(0, name, type):
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        "."  + name));
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the reason for keeping this field.
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println("  is a library field.\n");
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the name of this method.
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String name = libraryMethod.getName(libraryClass);
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String type = libraryMethod.getDescriptor(libraryClass);
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println(ClassUtil.externalClassName(libraryClass.getName()) +
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   (verbose ?
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        ": " + ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, name, type):
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        "."  + name));
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print the reason for keeping this method.
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ps.println("  is a library method.\n");
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
181b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Implementations for AttributeVisitor.
182b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
183b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
184b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
185b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
186b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
187b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
188b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        codeAttribute.attributesAccept(clazz, method, this);
189b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
190b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
191b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
192b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
193b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
194b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        ps.print(" (" +
195b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                 lineNumberTableAttribute.getLowestLineNumber() + ":" +
196b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                 lineNumberTableAttribute.getHighestLineNumber() + ")");
197b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
198b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
199b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Small utility methods.
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void printReason(VisitorAccepter visitorAccepter)
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (shortestUsageMarker.isUsed(visitorAccepter))
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ShortestUsageMark shortestUsageMark = shortestUsageMarker.getShortestUsageMark(visitorAccepter);
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Print the reason for keeping this class.
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ps.print("  " + shortestUsageMark.getReason());
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Print the class or method that is responsible, with its reasons.
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            shortestUsageMark.acceptClassVisitor(this);
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            shortestUsageMark.acceptMemberVisitor(this);
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ps.println("  is not being kept.\n");
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
221