Packetnamen aus einem Packet auslesen

  • Themenstarter Themenstarter Annun
  • Beginndatum Beginndatum
A

Annun

Hallo zusammen,

ich habe das folgende Problem, dass ich die Namen aller Klassen aus einem Java-Packet auslesen möchte. Da ich die Anwendung in ein Jar verpacken muss, habe ich nicht die Möglichkeit die Namen durch ein File-Objekt auslesen zu lassen. Was könnte man noch probieren.

Gruss Annun
 
Hallo!

Das ist etwas komplizierter... wenn du einen Java Package Namen hast und dazu alle untergeordneten Klassen auflisten möchtest musst du zunächst einmal den Classpath nach Jars/ Verzeichnissen durchsuchen in welchen das entsprechende Java Package vorkommt. Anschließend musst du jedes vorkommen (Beispielsweise ein jar) Analysieren und die gefundenen Klassen ausgeben lassen.

Schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author Thomas.Darimont
 * 
 */
public class PackageAnalyzer {

    /**
     * @param args
     */
    public static void main(String[] args) {
        List<String> classNames = findAllClassesContainedBy(Package
                .getPackage("de.tutorials"));
        System.out.println(classNames);
        System.out.println(classNames.size());
        
        classNames = findAllClassesContainedBy(Package
                .getPackage("java.lang"));
        System.out.println(classNames);
        System.out.println(classNames.size());
    }

    private static List<String> findAllClassesContainedBy(Package thePackage) {
        List<String> classes = new ArrayList<String>();
        String thePackagePattern = thePackage.getName().replace('.', '/')
                + "/[_$\\w]*.class";
        String classPath = System.getProperty("sun.boot.class.path") + ";"
                + System.getProperty("java.class.path");
        URL[] classPathUrls = getClasspathUrls(classPath);
        for (int i = 0; i < classPathUrls.length; i++) {
            URL url = classPathUrls[i];
            if (url.getFile().endsWith(".jar")) { // TODO add support for Zip
                classes.addAll(findAllClassesInJarContainedBy(
                        thePackagePattern, url));
            } else { // Url is Directory
                classes.addAll(findAllClassesInDirectoryContainedBy(thePackage,
                        url));
            }
        }
        return classes;
    }

    private static Collection<? extends String> findAllClassesInDirectoryContainedBy(
            Package thePackage, URL url) {
        List<String> classes = new ArrayList<String>();
        try {
            File file = new File(url.toURI());
            if (!file.exists()) {
                return classes;
            }
            String thePackagePattern = thePackage.getName().replace('.', '/');
            File thePackageFolder = new File(file, thePackagePattern);
            if (!thePackageFolder.exists()) {
                return classes;
            }

            return Arrays.asList(thePackageFolder.list(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return name.endsWith(".class");
                }
            }));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return classes;
    }

    private static Collection<? extends String> findAllClassesInJarContainedBy(
            String thePackagePattern, URL url) {
        List<String> classes = new ArrayList<String>();

        try {
            File file = new File(url.toURI());
            if (!file.exists()) {
                System.out.println("Skipping: " + file);
                return classes;
            }
            JarFile jarFile = new JarFile(file);
            Enumeration<JarEntry> jarEntries = jarFile.entries();
            while (jarEntries.hasMoreElements()) {
                JarEntry jarEntry = jarEntries.nextElement();
                if (jarEntry.getName().matches(thePackagePattern)) {
                    classes.add(jarEntry.getName());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classes;
    }

    private static URL[] getClasspathUrls(String classPath) {
        String[] classPaths = classPath.split(";");
        URL[] classPathUrls = new URL[classPaths.length];
        for (int i = 0; i < classPaths.length; i++) {
            String url = classPaths[i];
            try {
                classPathUrls[i] = new File(url).toURI().toURL();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
        return classPathUrls;
    }

}

Ausgabe:
Code:
Skipping: C:\Programme\Java\jdk1.6.0\jre\lib\sunrsasign.jar
[Debugger.class, Main.class, PackageAnalyzer$1.class, PackageAnalyzer.class]
4
Skipping: C:\Programme\Java\jdk1.6.0\jre\lib\sunrsasign.jar
[java/lang/AbstractMethodError.class, java/lang/AssertionError.class, java/lang/AssertionStatusDirectives.class, java/lang/Byte$ByteCache.class, java/lang/Character$Subset.class, java/lang/Character$UnicodeBlock.class, java/lang/CharacterData00.class, java/lang/CharacterData01.class, java/lang/CharacterData02.class, java/lang/CharacterData0E.class, java/lang/CharacterDataPrivateUse.class, java/lang/CharacterDataUndefined.class, java/lang/Class$2.class, java/lang/Class$EnclosingMethodInfo.class, java/lang/Class$MethodArray.class, java/lang/ClassCircularityError.class, java/lang/ConditionalSpecialCasing$Entry.class, java/lang/ConditionalSpecialCasing.class, java/lang/Deprecated.class, java/lang/EnumConstantNotPresentException.class, java/lang/IllegalThreadStateException.class, java/lang/InstantiationError.class, java/lang/NegativeArraySizeException.class, java/lang/NoSuchFieldError.class, java/lang/Override.class, java/lang/Package$1.class, java/lang/Package$1PackageInfoProxy.class, java/lang/Process.class, java/lang/ProcessBuilder.class, java/lang/ProcessEnvironment$1.class, java/lang/ProcessEnvironment$CheckedEntry.class, java/lang/ProcessEnvironment$CheckedEntrySet$1.class, java/lang/ProcessEnvironment$CheckedEntrySet.class, java/lang/ProcessEnvironment$CheckedKeySet.class, java/lang/ProcessEnvironment$CheckedValues.class, java/lang/ProcessEnvironment$EntryComparator.class, java/lang/ProcessEnvironment$NameComparator.class, java/lang/ProcessEnvironment.class, java/lang/ProcessImpl$1.class, java/lang/ProcessImpl.class, java/lang/SecurityManager$2.class, java/lang/Shutdown$1.class, java/lang/String$1.class, java/lang/StringCoding$1.class, java/lang/SuppressWarnings.class, java/lang/System$1.class, java/lang/ThreadLocal$1.class, java/lang/TypeNotPresentException.class, java/lang/UnknownError.class, java/lang/UnsupportedClassVersionError.class, java/lang/VerifyError.class, java/lang/ClassLoader$1.class, java/lang/Thread$1.class, java/lang/SecurityManager$1.class, java/lang/SecurityManager.class, java/lang/ExceptionInInitializerError.class, java/lang/StringIndexOutOfBoundsException.class, java/lang/ClassFormatError.class, java/lang/Thread$State.class, java/lang/UnsatisfiedLinkError.class, java/lang/StringCoding$StringEncoder.class, java/lang/Long$LongCache.class, java/lang/Void.class, java/lang/CloneNotSupportedException.class, java/lang/IllegalAccessError.class, java/lang/ArrayIndexOutOfBoundsException.class, java/lang/IndexOutOfBoundsException.class, java/lang/InstantiationException.class, java/lang/NoSuchFieldException.class, java/lang/SecurityException.class, java/lang/InternalError.class, java/lang/InheritableThreadLocal.class, java/lang/NumberFormatException.class, java/lang/IllegalArgumentException.class, java/lang/StrictMath.class, java/lang/Package.class, java/lang/IllegalAccessException.class, java/lang/Character$CharacterCache.class, java/lang/UnsupportedOperationException.class, java/lang/ClassLoader$2.class, java/lang/Short$ShortCache.class, java/lang/IllegalStateException.class, java/lang/NoSuchMethodException.class, java/lang/Integer$IntegerCache.class, java/lang/Class$4.class, java/lang/Enum.class, java/lang/InterruptedException.class, java/lang/StringCoding$StringDecoder.class, java/lang/ThreadLocal$ThreadLocalMap$Entry.class, java/lang/ThreadLocal$ThreadLocalMap.class, java/lang/StringCoding.class, java/lang/SystemClassLoaderAction.class, java/lang/CharacterDataLatin1.class, java/lang/Compiler$1.class, java/lang/Compiler.class, java/lang/System$2.class, java/lang/ApplicationShutdownHooks.class, java/lang/Shutdown$Lock.class, java/lang/Shutdown.class, java/lang/Terminator$1.class, java/lang/Terminator.class, java/lang/ClassLoader$NativeLibrary.class, java/lang/ClassLoader$3.class, java/lang/Readable.class, java/lang/Runtime.class, java/lang/Class$1.class, java/lang/StringBuilder.class, java/lang/Math.class, java/lang/ThreadLocal.class, java/lang/Class$3.class, java/lang/NoSuchMethodError.class, java/lang/IncompatibleClassChangeError.class, java/lang/RuntimePermission.class, java/lang/String$CaseInsensitiveComparator.class, java/lang/ArithmeticException.class, java/lang/NullPointerException.class, java/lang/Long.class, java/lang/Integer.class, java/lang/Short.class, java/lang/Byte.class, java/lang/Double.class, java/lang/Float.class, java/lang/Number.class, java/lang/Character.class, java/lang/Boolean.class, java/lang/StackTraceElement.class, java/lang/StringBuffer.class, java/lang/AbstractStringBuilder.class, java/lang/Appendable.class, java/lang/Iterable.class, java/lang/ThreadGroup.class, java/lang/Thread$UncaughtExceptionHandler.class, java/lang/Thread.class, java/lang/Runnable.class, java/lang/IllegalMonitorStateException.class, java/lang/StackOverflowError.class, java/lang/OutOfMemoryError.class, java/lang/VirtualMachineError.class, java/lang/ArrayStoreException.class, java/lang/ClassCastException.class, java/lang/NoClassDefFoundError.class, java/lang/LinkageError.class, java/lang/ClassNotFoundException.class, java/lang/RuntimeException.class, java/lang/Exception.class, java/lang/ThreadDeath.class, java/lang/Error.class, java/lang/Throwable.class, java/lang/System.class, java/lang/ClassLoader.class, java/lang/Cloneable.class, java/lang/Class.class, java/lang/String.class, java/lang/CharSequence.class, java/lang/Comparable.class, java/lang/Object.class]
156

Gruß Tom
 
Vielen Dank euch beiden.

Ich habe da noch zwei Sachen zu ergänzen.

1. Es darf nur Java 1.4 verwenden werden.
2. Es muss nur eine Packetstruktur durchsucht werden, ungefär so etwas:

com.dasprojekt.zudurchsuchendeklassen

Der Duchsuchungsvorgang muss aus einer eingejarten Klasse heraus aufgerufen werden, das ist mein größtes Problem. Deshalb kann ich ja auch nicht wie Erdal es vorschlug in dem Archiv mit Hilfe eines File Objektes suchen. Die Liste mit den Klassennamen muss zur Laufzeit der Anwendung erstellt werden, denn ihr Inhalt wird auch zur Laufzeit benötigt.


Gruss Annun
 
Hallo!

Na dann ists ja nicht mehr so schwer... den obigen Code kann man recht flott nach Java 1.4 portieren. Anschließend gehst du dann so vor dass du statt des gesamten Classpaths einfach nur das "eigene" Jar analysierst...

Gruß Tom
 
OK Thomas, das mit dem Umbauen zu J2SE 1.4 ist wirklich nicht schwer, aber wie soll ich "nur" das eigene Jar durchsuchen, was muss ich da machen. Zudem habe ich das Problem, wie ich das testeen kann , wenn ich noch gar kein jar habe, sondern einfach das zu durchsuchende Packet als Testlauf von der IDE aus (Eclipse) testen möchte.

jar
- MANIFEST.mf
- com
dasprojekt.
zudurchsuchendeklassen //da will ich hin


Gruss Annun
 
Hallo!

Das ist doch auch nicht schwer... du könntest beispielsweise die findAllClassesInDirectoryContainedBy(...) Methode aus meinem Beispiel einfach mit der URL des entsprechenden Package Verzeichnisses füttern, fertig.

Gruß Tom
 
Viel Dank Thomas, es funtzt.
Ich kann jetzt von einer Klasse in einem Jar den Inhalt eines Packets in dem Jar ermitteln. Das einzige, wo ich noch ein wenig rumexperimentieren muss, ist das dieses Jar in ein anderes Jar gepackt werden soll. Wenn man das mit einem Tool wie FatJar oder aber nen eigenen Class Loader dafür implentiert (es gibt ja genug Tutorials dazu)klappt das mit den bisherigen Funktionen nicht so ganz. Das liegt ja daran, dass das Jar im Jar nicht direkt im Classpath liegt, aber da komm ich auch noch dran.

So long Annun.
 
Zurück