/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.wcs.netbeans.liquiface.util; /* * #%L * Liquiface - GUI for Liquibase * %% * Copyright (C) 2013 Webstar Csoport Kft. * %% * 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 3 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, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author tveki */ public class ClassUtil { public static final String CLASS_EXTENSION = ".class"; public static Iterable<Class> getAllClassesRecursivelyFromPackageOf(Class clazz) throws Exception { List<Class> classes = new ArrayList<Class>(); String packageName = clazz.getPackage().getName(); String path = toPath(packageName); Enumeration<URL> resources = clazz.getClassLoader().getResources(path); URL resource = null; while (resources.hasMoreElements()) { resource = resources.nextElement(); classes.addAll(findClasses(resource, packageName)); } if (resource == null) { resource = asResource(clazz); classes.addAll(findClasses(resource, packageName)); } return classes; } private static URL asResource(Class clazz) { return clazz.getClassLoader().getResource(toPath(clazz)); } private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException { List<Class> classes = new ArrayList<Class>(); if (!directory.exists()) { return classes; } logger().log(Level.FINE, "Searching for classes in directory {0} of package or subpackages of {1}", new Object[]{directory.getAbsolutePath(), packageName}); File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) { classes.addAll(findClasses(file, packageName + "." + file.getName())); } else if (isClass(file)) { classes.add(Class.forName(className(packageName, file))); } } return classes; } private static List<Class> findClasses(URL resource, String packageName) throws URISyntaxException, IOException, ClassNotFoundException { if ("file".equals(resource.getProtocol())) { File dir = new File(resource.getFile()); return findClasses(dir, packageName); } else if ("jar".equals(resource.getProtocol())) { String jarPath = jarPath(resource); JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); return findClasses(jar, packageName); } else { logger().log(Level.WARNING, "Unhandled protocol: {0}", resource.getProtocol()); } return new ArrayList<Class>(); } private static List<Class> findClasses(JarFile jar, String packageName) throws URISyntaxException, IOException, ClassNotFoundException { logger().log(Level.FINE, "Searching for classes in jar {0} of package or subpackages of {1}", new Object[]{jar.getName(), packageName}); Enumeration<JarEntry> entries = jar.entries(); List<Class> classes = new ArrayList<Class>(); String path = toPath(packageName) + "/"; while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); if (isClass(jarEntry) && jarEntry.getName().startsWith(path)) { classes.add(Class.forName(className(jarEntry))); } } return classes; } private static boolean isClass(File file) { return isClass(file.getName()); } private static boolean isClass(JarEntry entry) { return isClass(entry.getName()); } private static boolean isClass(String fileName) { return fileName.endsWith(CLASS_EXTENSION); } private static String className(String packageName, File file) { if (!isClass(file)) { throw new IllegalArgumentException("It's not a *.class file!"); } int extensionStart = file.getName().length() - CLASS_EXTENSION.length(); String className = file.getName().substring(0, extensionStart); return packageName + '.' + className; } private static String className(JarEntry entry) { if (!isClass(entry)) { throw new IllegalArgumentException("It's not a *.class entry!"); } String entryName = entry.getName(); int classNameStart = entryName.lastIndexOf('/') + 1; int extensionStart = entryName.length() - CLASS_EXTENSION.length(); String packageName = toPackage(entryName.substring(0, classNameStart - 1)); String className = entryName.substring(classNameStart, extensionStart); return packageName + '.' + className; } private static String jarPath(URL jarResource) { if (!"jar".equals(jarResource.getProtocol())) { throw new IllegalArgumentException("Not a jar"); } int jarEnd = jarResource.getPath().indexOf("!"); return jarResource.getPath().substring("file:".length(), jarEnd); } private static String toPath(String packageName) { return packageName.replace('.', '/'); } private static String toPackage(String path) { return path.replace('/', '.'); } private static String toPath(Package pack) { return toPath(pack.getName()); } private static String toPath(Class klazz) { return toPath(klazz.getName()) + CLASS_EXTENSION; } private static Logger logger() { return Logger.getLogger(ClassUtil.class.getName()); } }