1 18 19 package org.apache.jorphan.reflect; 20 21 import java.io.File ; 22 import java.io.FilenameFilter ; 23 import java.io.IOException ; 24 import java.lang.reflect.Modifier ; 25 import java.util.ArrayList ; 26 import java.util.Enumeration ; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Set ; 31 import java.util.StringTokenizer ; 32 import java.util.TreeSet ; 33 import java.util.zip.ZipFile ; 34 35 import org.apache.jorphan.logging.LoggingManager; 36 import org.apache.log.Logger; 37 38 45 public final class ClassFinder 46 { 47 transient private static Logger log = LoggingManager.getLoggerForClass(); 48 private ClassFinder() 49 { 50 } 51 52 60 public static List findClassesThatExtend( 61 String [] paths, 62 Class [] superClasses) 63 throws IOException , ClassNotFoundException 64 { 65 return findClassesThatExtend(paths, superClasses, false); 66 } 67 68 73 private static String [] addJarsInPath(String [] paths) 74 { 75 Set fullList = new HashSet (); 76 for (int i = 0; i < paths.length; i++) 77 { 78 fullList.add(paths[i]); 79 if (!paths[i].endsWith(".jar")) 80 { 81 File dir = new File (paths[i]); 82 if (dir.exists() && dir.isDirectory()) 83 { 84 String [] jars = dir.list(new FilenameFilter () 85 { 86 public boolean accept(File f, String name) 87 { 88 if (name.endsWith(".jar")) 89 { 90 return true; 91 } 92 return false; 93 } 94 }); 95 for (int x = 0; x < jars.length; x++) 96 { 97 fullList.add(jars[x]); 98 } 99 } 100 } 101 } 102 return (String []) fullList.toArray(new String [0]); 103 } 104 public static List findClassesThatExtend( 105 String [] strPathsOrJars, 106 Class [] superClasses, 107 boolean innerClasses) 108 throws IOException , ClassNotFoundException 109 { 110 List listPaths = null; 111 Set listClasses = null; 112 List listSuperClasses = null; 113 strPathsOrJars = addJarsInPath(strPathsOrJars); 114 if (log.isDebugEnabled()) 115 { 116 for (int k = 0; k < strPathsOrJars.length; k++) 117 { 118 log.debug("strPathsOrJars : " + strPathsOrJars[k]); 119 } 120 } 121 listPaths = getClasspathMatches(strPathsOrJars); 122 if (log.isDebugEnabled()) 123 { 124 Iterator tIter = listPaths.iterator(); 125 for (; tIter.hasNext();) 126 { 127 log.debug("listPaths : " + tIter.next()); 128 } 129 } 130 listClasses = new TreeSet (); 131 listSuperClasses = new ArrayList (); 132 for (int i = 0; i < superClasses.length; i++) 133 { 134 listSuperClasses.add(superClasses[i].getName()); 135 } 136 findClassesInPaths(listPaths, listClasses); 138 if (log.isDebugEnabled()) 139 { 140 Iterator tIter = listClasses.iterator(); 141 for (; tIter.hasNext();) 142 { 143 log.debug("listClasses : " + tIter.next()); 144 } 145 } 146 Set subClassList = 147 findAllSubclasses(listSuperClasses, listClasses, innerClasses); 148 return new ArrayList (subClassList); 149 } 150 151 private static List getClasspathMatches(String [] strPathsOrJars) 152 { 153 ArrayList listPaths = null; 154 StringTokenizer stPaths = null; 155 String strPath = null; 156 int i; 157 listPaths = new ArrayList (); 158 log.debug("Classpath = " + System.getProperty("java.class.path")); 159 stPaths = 160 new StringTokenizer ( 161 System.getProperty("java.class.path"), 162 System.getProperty("path.separator")); 163 if (strPathsOrJars != null) 164 { 165 strPathsOrJars = fixDotDirs(strPathsOrJars); 166 strPathsOrJars = fixSlashes(strPathsOrJars); 167 strPathsOrJars = fixEndingSlashes(strPathsOrJars); 168 } 169 if (log.isDebugEnabled()) 170 { 171 for (i = 0; i < strPathsOrJars.length; i++) 172 { 173 log.debug("strPathsOrJars[" + i + "] : " + strPathsOrJars[i]); 174 } 175 } 176 177 while (stPaths.hasMoreTokens()) 179 { 180 strPath = fixDotDir((String ) stPaths.nextToken()); 181 strPath = fixSlashes(strPath); 182 strPath = fixEndingSlashes(strPath); 183 if (strPathsOrJars == null) 184 { 185 log.debug("Adding: " + strPath); 186 listPaths.add(strPath); 187 } 188 else 189 { 190 boolean found=false; 191 for (i = 0; i < strPathsOrJars.length; i++) 192 { 193 if (strPath.endsWith(strPathsOrJars[i])) 194 { 195 found=true; 196 log.debug("Adding "+strPath+" found at "+i); 197 listPaths.add(strPath); 198 break; } 200 } 201 if (!found){ 202 log.debug("Did not find: "+strPath); 203 } 204 } 205 } 206 return listPaths; 207 } 208 209 229 private static String [] fixDotDirs(String [] paths) 230 { 231 for (int i = 0; i < paths.length; i++) 232 { 233 paths[i] = fixDotDir(paths[i]); 234 } 235 return paths; 236 } 237 private static String fixDotDir(String path) 238 { 239 if (path == null) return null; 240 if (path.equals(".")) 241 { 242 return System.getProperty("user.dir"); 243 } 244 else 245 { 246 return path.trim(); 247 } 248 } 249 private static String [] fixEndingSlashes(String [] strings) 250 { 251 String [] strNew = new String [strings.length]; 252 for (int i = 0; i < strings.length; i++) 253 { 254 strNew[i] = fixEndingSlashes(strings[i]); 255 } 256 return strNew; 257 } 258 private static String fixEndingSlashes(String string) 259 { 260 if (string.endsWith("/") || string.endsWith("\\")) 261 { 262 string = string.substring(0, string.length() - 1); 263 string = fixEndingSlashes(string); 264 } 265 return string; 266 } 267 private static String [] fixSlashes(String [] strings) 268 { 269 String [] strNew = new String [strings.length]; 270 for (int i = 0; i < strings.length; i++) 271 { 272 strNew[i] = fixSlashes(strings[i]) ; 273 } 274 return strNew; 275 } 276 private static String fixSlashes(String str) 277 { 278 str = str.replace('\\', '/'); 280 str = replaceString(str, "//", "_____"); 284 str = replaceString(str, "_____", "/"); 285 return str; 286 } 287 private static String replaceString( 288 String s, 289 String strToFind, 290 String strToReplace) 291 { 292 int index; 293 int currentPos; 294 StringBuffer buffer = null; 295 if (s.indexOf(strToFind) == -1) 296 { 297 return s; 298 } 299 currentPos = 0; 300 buffer = new StringBuffer (); 301 while (true) 302 { 303 index = s.indexOf(strToFind, currentPos); 304 if (index == -1) 305 { 306 break; 307 } 308 buffer.append(s.substring(currentPos, index)); 309 buffer.append(strToReplace); 310 currentPos = index + strToFind.length(); 311 } 312 buffer.append(s.substring(currentPos)); 313 return buffer.toString(); 314 } 315 316 344 345 362 363 373 private static Set findAllSubclasses( 374 List listSuperClasses, 375 Set listAllClasses, 376 boolean innerClasses) 377 { 378 Iterator iterClasses = null; 379 Set listSubClasses = null; 380 String strClassName = null; 381 Class tempClass = null; 382 listSubClasses = new TreeSet (); 383 iterClasses = listSuperClasses.iterator(); 384 while (iterClasses.hasNext()) 385 { 386 strClassName = (String ) iterClasses.next(); 387 if ((strClassName.indexOf("$") == -1) || innerClasses) 390 { 391 try 393 { 394 tempClass = 395 Class.forName( 396 strClassName, 397 false, 398 Thread.currentThread().getContextClassLoader()); 399 findAllSubclassesOneClass( 400 tempClass, 401 listAllClasses, 402 listSubClasses, 403 innerClasses); 404 } 406 catch (Throwable ignored) 407 { 408 } 409 } 410 } 411 return listSubClasses; 412 } 413 414 436 437 447 private static void findAllSubclassesOneClass( 448 Class theClass, 449 Set listAllClasses, 450 Set listSubClasses, 451 boolean innerClasses) 452 { 453 Iterator iterClasses = null; 454 String strClassName = null; 455 Class c = null; 456 boolean bIsSubclass = false; 457 iterClasses = listAllClasses.iterator(); 458 while (iterClasses.hasNext()) 459 { 460 strClassName = (String ) iterClasses.next(); 461 if ((strClassName.indexOf("$") == -1) || innerClasses) 464 { 465 try 467 { 468 c = 469 Class.forName( 470 strClassName, 471 false, 472 Thread.currentThread().getContextClassLoader()); 473 474 if (!c.isInterface() 475 && !Modifier.isAbstract(c.getModifiers())) 476 { 477 bIsSubclass = theClass.isAssignableFrom(c); 478 } 479 else 480 { 481 bIsSubclass = false; 482 } 483 if (bIsSubclass) 484 { 485 listSubClasses.add(strClassName); 486 } 487 } 488 catch (Throwable ignored) 489 { 490 } 491 } 492 } 493 } 494 495 502 private static String fixClassName(String strClassName) 503 { 504 strClassName = strClassName.replace('\\', '.'); 505 strClassName = strClassName.replace('/', '.'); 506 strClassName = strClassName.substring(0, strClassName.length() - 6); 507 return strClassName; 509 } 510 511 private static void findClassesInOnePath(String strPath, Set listClasses) 512 throws IOException 513 { 514 File file = null; 515 ZipFile zipFile = null; 516 Enumeration entries = null; 517 String strEntry = null; 518 file = new File (strPath); 519 if (file.isDirectory()) 520 { 521 findClassesInPathsDir(strPath, file, listClasses); 522 } 523 else if (file.exists()) 524 { 525 zipFile = new ZipFile (file); 526 entries = zipFile.entries(); 527 while (entries.hasMoreElements()) 528 { 529 strEntry = entries.nextElement().toString(); 530 if (strEntry.endsWith(".class")) 531 { 532 listClasses.add(fixClassName(strEntry)); 533 } 534 } 535 } 536 } 537 538 private static void findClassesInPaths(List listPaths, Set listClasses) 539 throws IOException 540 { 541 Iterator iterPaths = listPaths.iterator(); 542 while (iterPaths.hasNext()) 543 { 544 findClassesInOnePath((String ) iterPaths.next(), listClasses); 545 } 546 } 547 548 private static void findClassesInPathsDir( 549 String strPathElement, 550 File dir, 551 Set listClasses) 552 throws IOException 553 { 554 File file = null; 555 String [] list = dir.list(); 556 for (int i = 0; i < list.length; i++) 557 { 558 file = new File (dir, list[i]); 559 if (file.isDirectory()) 560 { 561 findClassesInPathsDir(strPathElement, file, listClasses); 562 } 563 else if ( 564 file.exists() 565 && (file.length() != 0) 566 && list[i].endsWith(".class")) 567 { 568 listClasses.add( 569 file 570 .getPath() 571 .substring( 572 strPathElement.length() + 1, 573 file.getPath().lastIndexOf(".")) 574 .replace(File.separator.charAt(0), '.')); 575 } 576 } 577 } 578 } | Popular Tags |