Mercurial > hg > release > thermostat-1.2
view distribution/tools/ListExportedClasses.java @ 1660:c6ae78b6f3ac
[Thermostat 1.2] Update copyright year to 2015
Reviewed-by: omajid
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-March/013127.html
PR2273
author | Severin Gehwolf <sgehwolf@redhat.com> |
---|---|
date | Wed, 11 Mar 2015 15:07:27 +0100 |
parents | 0f2fbbea20bf |
children |
line wrap: on
line source
/* * Copyright 2012-2015 Red Hat, Inc. * * This file is part of Thermostat. * * Thermostat 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, or (at your * option) any later version. * * Thermostat 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 Thermostat; see the file COPYING. If not see * <http://www.gnu.org/licenses/>. * * Linking this code with other modules is making a combined work * based on this code. Thus, the terms and conditions of the GNU * General Public License cover the whole combination. * * As a special exception, the copyright holders of this code give * you permission to link this code with independent modules to * produce an executable, regardless of the license terms of these * independent modules, and to copy and distribute the resulting * executable under terms of your choice, provided that you also * meet, for each linked independent module, the terms and conditions * of the license of that module. An independent module is a module * which is not derived from or based on this code. If you modify * this code, you may extend this exception to your version of the * library, but you are not obligated to do so. If you do not wish * to do so, delete this exception statement from your version. */ import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.zip.ZipEntry; public class ListExportedClasses { public static void main(String[] args) { if (args.length == 0) { System.out.println("Usage:"); System.out.println("\tjava ListExportedClass [options] path/to/jar1 [path/to/jar2 [path/to/jar3 [...]]]"); System.out.println(); System.out.println("Prints a list of OSGi-exported packages and public classes in those packages"); System.out.println(); System.out.println("Options:"); System.out.println("\t--private\t\tshow only OSGi-private packages"); System.out.println("\t--packages\t\tshow packages only"); } // whether to show public or private packages boolean listPublicPackages = true; boolean listPackagesOnly = false; List<String> jarNames = new ArrayList<>(Arrays.asList(args)); for (String arg : args) { if (arg.equals("--private")) { listPublicPackages = false; jarNames.remove(arg); } else if (arg.equals("--packages")) { listPackagesOnly = true; jarNames.remove(arg); } } for (String jarName : jarNames) { if (!listPackagesOnly) { System.out.println(jarName); } try { JarFile jarFile = new JarFile(jarName); if (listPublicPackages) { for (String exportedPackage : findOSGiExportedPackages(jarFile)) { System.out.println("\t" + exportedPackage); if (!listPackagesOnly) { for (String exportedClass : findOSGiExportedClassesInPackage(jarFile, exportedPackage)) { System.out.println("\t\t" + exportedClass); } } } } else { for (String privatePackage : findOSGiPrivatePackages(jarFile)) { System.out.println(privatePackage); if (!listPackagesOnly) { System.err.println("not implemented"); } } } } catch (IOException ioe) { System.err.println("error reading " + jarName); } } } private static List<String> findOSGiExportedClassesInPackage(JarFile jarFile, String packageName) throws IOException { List<String> exportedClasses = new ArrayList<>(); List<String> allClasses = findClassNames(jarFile); for (String className : allClasses) { if (!packageName.equals(getPackageName(className))) { continue; } if (!isClassPublic(jarFile, className)) { continue; } exportedClasses.add(className); } Collections.sort(exportedClasses); return exportedClasses; } private static List<String> findClassNames(JarFile file) { List<String> result = new ArrayList<>(); Enumeration<JarEntry> entries = file.entries(); while (entries.hasMoreElements()) { String entryName = entries.nextElement().getName(); if (!entryName.endsWith(".class")) { continue; } String className = entryName.substring(0, entryName.length() - ".class".length()); className = className.replace('/', '.'); result.add(className); } return result; } private static boolean isClassPublic(JarFile jarFile, String className) throws IOException { /* * we can not use reflection without loading the class itself (and its * dependencies). so lets just parse the class file itself. */ ZipEntry entry = jarFile.getEntry(className.replace('.', '/').concat(".class")); InputStream classInputStream = jarFile.getInputStream(entry); DataInputStream in = new DataInputStream(classInputStream); int magic = in.readInt(); if (!(magic == 0xCAFEBABE)) { throw new InternalError("Tried parsing a maformed class file"); } /* int minorVersion = */in.readUnsignedShort(); /* int majorVersion = */in.readUnsignedShort(); int constPoolCount = in.readUnsignedShort(); for (int i = 1; i < constPoolCount; i++) { int tag = in.readUnsignedByte(); switch (tag) { case 7: case 8: in.readUnsignedShort(); break; case 3: case 4: case 9: case 10: case 11: case 12: in.readInt(); break; case 5: case 6: in.readLong(); i++; // these take up two entries in the pool break; case 1: int length = in.readUnsignedShort(); for (int j = 0; j < length; j++) { in.readUnsignedByte(); } break; } } int accessFlags = in.readUnsignedShort(); return (accessFlags & 0x0001) == 0x0001; } private static String getPackageName(String fullyQualifiedClassName) { int lastDot = fullyQualifiedClassName.lastIndexOf('.'); if (lastDot == -1) { return ""; } return fullyQualifiedClassName.substring(0, lastDot); } private static List<String> findOSGiExportedPackages(JarFile jarFile) throws IOException { Manifest manifest = jarFile.getManifest(); String exportedPackages = manifest.getMainAttributes().getValue("Export-Package"); return convertPackageStringToList(exportedPackages); } private static List<String> findOSGiPrivatePackages(JarFile jarFile) throws IOException { Manifest manifest = jarFile.getManifest(); String privatePackages = manifest.getMainAttributes().getValue("Private-Package"); return convertPackageStringToList(privatePackages); } private static List<String> convertPackageStringToList(String packages) { if (packages == null) { return new ArrayList<>(); } List<String> packagesList = Arrays.asList(packages.split(",")); for (int i = 0; i < packagesList.size(); i++) { String exportedPackage = packagesList.get(i); // exports can have a ";uses.." part after the package name. remove it. int indexOfUses = exportedPackage.indexOf(";"); if (indexOfUses != -1) { exportedPackage = exportedPackage.substring(0, indexOfUses); } packagesList.set(i, exportedPackage); } Collections.sort(packagesList); return packagesList; } }