/* * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) * * 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 of the License, 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; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package proguard; import java.io.*; import java.util.*; /** * This class checks and prints out information about the GPL. * * @author Eric Lafortune */ public class GPL { /** * Prints out a note about the GPL if ProGuard is linked against unknown * code. */ public static void check() { ByteArrayOutputStream out = new ByteArrayOutputStream(); new Exception().printStackTrace(new PrintStream(out)); LineNumberReader reader = new LineNumberReader( new InputStreamReader( new ByteArrayInputStream(out.toByteArray()))); Set unknownPackageNames = unknownPackageNames(reader); if (unknownPackageNames.size() > 0) { String uniquePackageNames = uniquePackageNames(unknownPackageNames); System.out.println("ProGuard is released under the GNU General Public License. You therefore"); System.out.println("must ensure that programs that link to it ("+uniquePackageNames+"...)"); System.out.println("carry the GNU General Public License as well. Alternatively, you can"); System.out.println("apply for an exception with the author of ProGuard."); } } /** * Returns a set of package names from the given stack trace. */ private static Set unknownPackageNames(LineNumberReader reader) { Set packageNames = new HashSet(); try { while (true) { String line = reader.readLine(); if (line == null) { break; } line = line.trim(); if (line.startsWith("at ")) { line = line.substring(2).trim(); line = trimSuffix(line, '('); line = trimSuffix(line, '.'); line = trimSuffix(line, '.'); if (line.length() > 0 && !isKnown(line)) { packageNames.add(line); } } } } catch (IOException ex) { // We'll just stop looking for more names. } return packageNames; } /** * Returns a comma-separated list of package names from the set, excluding * any subpackages of packages in the set. */ private static String uniquePackageNames(Set packageNames) { StringBuffer buffer = new StringBuffer(); Iterator iterator = packageNames.iterator(); while (iterator.hasNext()) { String packageName = (String)iterator.next(); if (!containsPrefix(packageNames, packageName)) { buffer.append(packageName).append(", "); } } return buffer.toString(); } /** * Returns a given string without the suffix, as defined by the given * separator. */ private static String trimSuffix(String string, char separator) { int index = string.lastIndexOf(separator); return index < 0 ? "" : string.substring(0, index); } /** * Returns whether the given set contains a prefix of the given name. */ private static boolean containsPrefix(Set set, String name) { int index = 0; while (!set.contains(name.substring(0, index))) { index = name.indexOf('.', index + 1); if (index < 0) { return false; } } return true; } /** * Returns whether the given package name has been granted an exception * against the GPL linking clause, by the copyright holder of ProGuard. * This method is not legally binding, but of course the actual license is. * Please contact the copyright holder if you would like an exception for * your code as well. */ private static boolean isKnown(String packageName) { return packageName.startsWith("java") || packageName.startsWith("sun.reflect") || packageName.startsWith("proguard") || packageName.startsWith("org.apache.tools.ant") || packageName.startsWith("org.apache.tools.maven") || packageName.startsWith("org.gradle") || packageName.startsWith("org.codehaus.groovy") || packageName.startsWith("org.eclipse") || packageName.startsWith("org.netbeans") || packageName.startsWith("com.android") || packageName.startsWith("com.sun.kvem") || packageName.startsWith("com.intel") || packageName.startsWith("net.certiv.proguarddt") || packageName.startsWith("groovy") || packageName.startsWith("scala") || packageName.startsWith("sbt") || packageName.startsWith("xsbt") || packageName.startsWith("eclipseme") || packageName.startsWith("com.neomades") || packageName.startsWith("jg.j2me") || packageName.startsWith("jg.common") || packageName.startsWith("jg.buildengine"); } public static void main(String[] args) { LineNumberReader reader = new LineNumberReader( new InputStreamReader(System.in)); Set unknownPackageNames = unknownPackageNames(reader); if (unknownPackageNames.size() > 0) { String uniquePackageNames = uniquePackageNames(unknownPackageNames); System.out.println(uniquePackageNames); } } }