{"id":131,"date":"2007-09-28T16:36:28","date_gmt":"2007-09-28T15:36:28","guid":{"rendered":"http:\/\/www.sahits.ch\/blog\/?p=131"},"modified":"2009-01-08T16:11:59","modified_gmt":"2009-01-08T15:11:59","slug":"durchsuchen-des-classpath","status":"publish","type":"post","link":"http:\/\/sahits.ch\/blog\/blog\/2007\/09\/28\/durchsuchen-des-classpath\/","title":{"rendered":"Durchsuchen des Classpath"},"content":{"rendered":"<p>Das JDK bringt von Haus aus bereits ein m\u00e4chtiges Framework mit sich, mit dem sich zur Runtime Informationen \u00fcber die Applikation gewinnen lassen, wie auch schon in einem <a href=\"http:\/\/www.sahits.ch\/blog\/?p=15\">fr\u00fcheren Beitrag<\/a> beschrieben. Dies funktioniert solange einwandfrei als ich weiss auf welche Klasse ich die Reflection los lasse.<br \/>\nMit Annotation l\u00e4sst sich eine Vielzahl von Dingen bewerkstelligen, so kann man auch auf den Gedanken verfallen, dass man Bestimmte Aufgaben definiert (beispielsweise in einer Enumeration). Die Ausf\u00fchrung dieser Aufgaben \u00fcbernehmen Methoden mit einer nicht n\u00e4her bekannten Signatur. Was aber bekannt ist, ist dass die Methode mit einer Annotation gekennzeichnet ist, die besagt, dass diese Methode jene Aufgabe erf\u00fcllt.<br \/>\nWie gelange ich nun an die Klasse in der die Methode definiert ist? Nur mit dem JDK ist dies nicht m\u00f6glich. Dazu m\u00fcssen aus dem Classpath alle Klassen ausgelesen werden. Dann kann jede einzelne Klasse nach der Methode untersucht werden, die die spezifizierte Annotation besitzt.<br \/>\nWem dies alles etwas zu abstrakt war hier das Beispiel:<\/p>\n<pre>\r\npublic class ClassFinder {\r\n        \/**\r\n         * Defined classpath\r\n         *\/\r\n\tprivate static final String CLASSPATH = System.getProperty(\"java.class.path\");\r\n\t\/**\r\n\t * List with the jar files on the classpath\r\n\t *\/\r\n\tprivate static String[] jarFiles;\r\n\t\/**\r\n\t * List with the directories on the classpath (containing .class files)\r\n\t *\/\r\n\tprivate static String[] binDirs;\r\n\t\/**\r\n\t * All Classpath elements\r\n\t *\/\r\n\tprivate static File[] classPathDirs = null;\r\n\t\/**\r\n\t * Default constructur initializes the directories indicated by the\r\n\t * CLASSPATH, if they are not yet initialized.\r\n\t *\/\r\n\tpublic ClassFinder() {\r\n\t\tif (classPathDirs == null) {\r\n\t\t\tinitClassPathDir();\r\n\t\t}\r\n\t}\r\n\t\/**\r\n\t * Initialize the directories based on the classpath\r\n\t *\/\r\n\tprivate void initClassPathDir() {\r\n\t\tStringTokenizer st = new StringTokenizer(CLASSPATH, File.pathSeparator);\r\n\t\tint count = st.countTokens();\r\n\t\tclassPathDirs = new File[count];\r\n\t\tVector<string> jar = new Vector<\/string><string>();\r\n\t\tVector<\/string><string> bin = new Vector<\/string><string>();\r\n\t\tfor (int i = 0; i < count; i++) {\r\n\t\t\tclassPathDirs[i] = new File(st.nextToken());\r\n\t\t\tif (classPathDirs[i].isDirectory()) {\r\n\t\t\t\tbin.add(classPathDirs[i].getAbsolutePath());\r\n\t\t\t} else {\r\n\t\t\t\tjar.add(classPathDirs[i].getAbsolutePath());\r\n\t\t\t}\r\n\t\t}\r\n\t\tjarFiles = new String[jar.size()];\r\n\t\tbinDirs = new String[bin.size()];\r\n\t\tjar.copyInto(jarFiles);\r\n\t\tbin.copyInto(binDirs);\r\n\t}\r\n\r\n\t\/**\r\n\t * Retrive all classes of the indicated package. The package is searched in\r\n\t * all classpath directories that are directories\r\n\t * \r\n\t * @param packageName\r\n\t *            name of the package as 'ch.sahits.civ'\r\n\t * @return Array of found classes\r\n\t * @throws ClassNotFoundException\r\n\t *\/\r\n\tpublic Class[] getAll(String packageName) throws ClassNotFoundException {\r\n\t\tString packageDir = convertPackege(packageName);\r\n\t\tVector<Class> classes = new Vector<class>();\r\n\t\tfor (int i = 0; i < binDirs.length; i++) {\r\n\t\t\tpackageDir = binDirs[i] + File.separator + packageDir;\r\n\t\t\tFile dir = new File(packageDir);\r\n\t\t\tclasses.addAll(extractClasses(packageName, dir));\r\n\t\t}\r\n\t\tClass[] result = new Class[classes.size()];\r\n\t\tclasses.copyInto(result);\r\n\t\treturn result;\r\n\t}\r\n\t\/**\r\n\t * Extract all the classes from a directory\r\n\t * @param packageName name of the package as 'ch.sahits.civ'\r\n\t * @param dir Package as directory\r\n\t * @return Vector with all found directories\r\n\t * @throws ClassNotFoundException\r\n\t *\/\r\n\tprivate Vector<Class> extractClasses(String packageName, File dir) throws ClassNotFoundException {\r\n\t\tVector<\/class><class> classes = new Vector<\/class><class>();\r\n\t\tFile[] files = dir.listFiles(new FilenameFilter() {\r\n\t\t\tpublic boolean accept(File dir, String filename) {\r\n\t\t\t\treturn filename.endsWith(\".class\");\r\n\t\t\t}\r\n\t\t});\r\n\t\tif (files!=null) {\t\/\/ directories without .class files may exist\r\n\t\t\tfor (int j = 0; j < files.length; j++) {\r\n\t\t\t\tString className = packageName + \".\" + files[j].getName();\r\n\t\t\t\tclassName = className.substring(0, className\r\n\t\t\t\t\t\t.lastIndexOf(\".class\"));\r\n\t\t\t\tclasses.add(Class.forName(className));\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn classes;\r\n\t}\r\n\t\/**\r\n\t * Convert the package name into a relative directory path\r\n\t * @param packageName name of the package as 'ch.sahits.civ'\r\n\t * @return relativ directory to the package\r\n\t *\/\r\n\tprivate String convertPackege(String packageName) {\r\n\t\tString sep = File.separator;\r\n\t\treturn packageName.replace(\".\", sep);\r\n\t}\r\n\t\/**\r\n\t * Retrive all classes of the indicated package and all subpackages. The package is searched in\r\n\t * all classpath directories that are directories\r\n\t * \r\n\t * @param packageName\r\n\t *            name of the package as 'ch.sahits.civ'\r\n\t * @return Array of found classes\r\n\t * @throws ClassNotFoundException\r\n\t *\/\r\n\tpublic Class[] getAllRecursive(String packageName) throws ClassNotFoundException {\r\n\t\tString packageDir = convertPackege(packageName);\r\n\t\tVector<Class> classes = new Vector<\/class><class>();\r\n\t\tfor (int i = 0; i < binDirs.length; i++) {\r\n\t\t\tpackageDir = binDirs[i] + File.separator + packageDir;\r\n\t\t\tFile dir = new File(packageDir);\r\n\t\t\tclasses.addAll(extractClasses(packageName, dir));\r\n\t\t\tif (dir.isDirectory()) {\r\n\t\t\t\tFile[] sub = dir.listFiles();\r\n\t\t\t\tfor (int j = 0; j < sub.length; j++) {\r\n\t\t\t\t\tif (sub[j].isDirectory()) {\r\n\t\t\t\t\t\tClass[] rec = getAllRecursive(packageName + \".\"\r\n\t\t\t\t\t\t\t\t+ sub[j].getName());\r\n\t\t\t\t\t\tVector<Class> temp = new Vector<\/class><class>(rec.length);\r\n\t\t\t\t\t\tfor (int k = 0; k < rec.length; k++) {\r\n\t\t\t\t\t\t\ttemp.add(rec[k]);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tclasses.addAll(temp);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tClass[] result = new Class[classes.size()];\r\n\t\tclasses.copyInto(result);\r\n\t\treturn result;\r\n\t}\r\n}<\/pre>\n<p>Vielleicht sollte an dieser Stelle noch bemerkt werden, dass ein solches Vorgehen wohl \u00fcberlegt sein soll, denn nur mit diesen Informationen ist es nicht nicht m\u00f6glich, die Methode auszuf\u00fchren, den dazu wird noch ein Objekt ben\u00f6tigt, auf welchem die Methode ausgef\u00fchrt werden kann und wenn man dieses hat, kann man sich den Umweg \u00fcber den Classpath sparen.<\/class><\/string><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Das JDK bringt von Haus aus bereits ein m\u00e4chtiges Framework mit sich, mit dem sich zur Runtime Informationen \u00fcber die Applikation gewinnen lassen, wie auch schon in einem fr\u00fcheren Beitrag beschrieben. Dies funktioniert solange einwandfrei als ich weiss auf welche Klasse ich die Reflection los lasse. Mit Annotation l\u00e4sst sich eine Vielzahl von Dingen bewerkstelligen, &hellip; <a href=\"http:\/\/sahits.ch\/blog\/blog\/2007\/09\/28\/durchsuchen-des-classpath\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eDurchsuchen des Classpath\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,6],"tags":[16,99,301,300,18,15,17,25],"class_list":["post-131","post","type-post","status-publish","format-standard","hentry","category-java","category-programmieren","tag-classpath","tag-de","tag-java","tag-programmieren","tag-reflection","tag-source-code","tag-suchen","tag-tutorial"],"_links":{"self":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/131","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/comments?post=131"}],"version-history":[{"count":4,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/131\/revisions"}],"predecessor-version":[{"id":451,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/131\/revisions\/451"}],"wp:attachment":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/media?parent=131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/categories?post=131"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/tags?post=131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}