1 23 24 package com.sun.enterprise.loader; 25 26 import com.sun.appserv.server.util.ASClassLoaderUtil; 27 import com.sun.appserv.server.util.ASURLClassLoader; 28 import com.sun.appserv.server.util.ClassLoaderChain; 29 import com.sun.enterprise.deployment.Application; 30 import com.sun.enterprise.deployment.deploy.shared.FileArchive; 31 import com.sun.enterprise.deployment.io.ApplicationDeploymentDescriptorFile; 32 import com.sun.enterprise.deployment.util.ModuleDescriptor; 33 import com.sun.enterprise.instance.AppsManager; 34 import com.sun.enterprise.instance.BaseManager; 35 import com.sun.enterprise.server.ApplicationServer; 36 import com.sun.enterprise.server.PELaunch; 37 import com.sun.enterprise.server.ServerContext; 38 import com.sun.enterprise.util.io.FileUtils; 39 import com.sun.logging.LogDomains; 40 41 import java.io.File ; 42 import java.io.FileInputStream ; 43 import java.io.InputStream ; 44 import java.io.IOException ; 45 import java.net.MalformedURLException ; 46 import java.net.URL ; 47 import java.util.ArrayList ; 48 import java.util.HashMap ; 49 import java.util.Iterator ; 50 import java.util.Map ; 51 import java.util.jar.Attributes ; 52 import java.util.jar.JarFile ; 53 import java.util.jar.Manifest ; 54 import java.util.List ; 55 import java.util.logging.Level ; 56 import java.util.logging.Logger ; 57 import java.util.StringTokenizer ; 58 59 import javax.enterprise.deploy.shared.ModuleType ; 60 61 import org.xml.sax.SAXParseException ; 62 63 70 public class EJBClassPathUtils { 71 72 static Logger _logger = LogDomains.getLogger(LogDomains.LOADER_LOGGER); 73 78 private static Map <URL ,ClassLoader > classLoaderRegistry = 79 new HashMap <URL ,ClassLoader >(); 80 81 90 public static List getAppClasspath(Application application, BaseManager apps) { 91 92 String appName = application.getRegistrationName(); 93 94 try { 95 96 String appRoot = apps.getLocation(appName); 97 return getAppClassPath(application, appRoot, apps); 98 99 } catch (Exception e) { 100 _logger.log(Level.SEVERE,"ejb.classpath",e); 101 return new ArrayList (); 102 } 103 } 104 105 public static List getAppClassPath(Application application, String appRoot, BaseManager apps) { 106 107 List classpath = new ArrayList (); 108 String appName = application.getRegistrationName(); 109 110 try { 111 112 List appPath = getApplicationClassPath(application, appRoot); 113 114 if (appPath.size() > 0) { 115 classpath.addAll(appPath); 116 } 117 118 classpath.add(apps.getStubLocation(appName)); 120 121 } catch (Exception e) { 122 _logger.log(Level.SEVERE,"ejb.classpath",e); 123 } 124 125 if (_logger.isLoggable(Level.FINE)) { 127 _logger.log(Level.FINE, "[EJBClassPathUtils] EJB Class Path for [" 128 + appName + "] is ...\n" + classpath.toString()); 129 } 130 131 return classpath; 132 } 133 134 public static List getModuleClasspath(String moduleName, String moduleRoot, BaseManager mgr) { 135 136 List classpath = new ArrayList (); 137 138 try { 139 140 if (moduleRoot==null) { 142 moduleRoot = mgr.getLocation(moduleName); 143 } 144 classpath.add(moduleRoot); 145 146 classpath.add( mgr.getStubLocation(moduleName) ); 148 149 classpath.addAll(getModuleClassPath(mgr.getModuleType(), moduleRoot, moduleRoot)); 150 151 } catch (Exception e) { 152 _logger.log(Level.SEVERE,"ejb.classpath",e); 153 } 154 155 return classpath; 156 } 157 158 public static List getModuleClassPath(ModuleType type, String moduleRoot, String appRoot) 159 throws IOException 160 { 161 162 List classpath = new ArrayList (); 163 164 Manifest mf = getManifest(moduleRoot); 166 167 List manifestClassPath = getManifestClassPath(mf, appRoot); 168 classpath.addAll(manifestClassPath); 169 170 171 if (ModuleType.WAR.equals(type)) { 172 173 String classesDir = moduleRoot + File.separator + WAR_CLASSES_DIR; 175 176 String libDir = moduleRoot + File.separator + WAR_LIB_DIR; 178 179 List warClassPath = ClassLoaderUtils.getUrlList 183 (new File[] {new File(classesDir)}, 184 new File[] {new File(libDir)} ); 185 186 classpath.addAll(warClassPath); 188 189 } else { 190 classpath.add(moduleRoot); 191 192 List moduleClassPath = ClassLoaderUtils.getUrlList 195 (null, 196 new File[] {new File(moduleRoot)} ); 197 classpath.addAll(moduleClassPath); 198 } 199 200 return classpath; 201 } 202 203 217 public static List getApplicationClassPath(Application app, String appRoot) 218 throws IOException { 219 220 List classpath = new ArrayList (); 221 222 if (!app.isVirtual()) { 224 if (app.getLibraryDirectory() != null) { 226 String libPath = 227 app.getLibraryDirectory().replace('/', File.separatorChar); 228 List dirLibraries = ClassLoaderUtils.getUrlList( 229 null, new File[] {new File(appRoot, libPath)}, true); 230 if (dirLibraries != null && !dirLibraries.isEmpty()) { 231 classpath.addAll(dirLibraries); 232 } 233 } 234 235 List rootLibraries = ClassLoaderUtils.getUrlList( 237 null, new File[] {new File(appRoot)}); 238 239 if (rootLibraries != null && !rootLibraries.isEmpty()) { 240 classpath.addAll(rootLibraries); 241 } 242 } 243 244 for (Iterator modules = app.getModules(); modules.hasNext();) { 245 246 ModuleDescriptor md = (ModuleDescriptor) modules.next(); 247 248 String moduleUri = md.getArchiveUri(); 249 String moduleRoot; 250 if (app.isVirtual()) { 251 moduleRoot = appRoot; 252 } else { 253 moduleRoot = appRoot + File.separator + FileUtils.makeFriendlyFilename(moduleUri); 254 } 255 256 classpath.addAll(getModuleClassPath(md.getModuleType(), moduleRoot, appRoot)); 257 } 258 return classpath; 259 } 260 261 263 280 public static Manifest getManifest(String rootPath) { 281 282 InputStream in = null; 283 Manifest mf = null; 284 285 try { 287 in = new FileInputStream (rootPath+File.separator+MANIFEST_ENTRY); 288 289 if (in != null) { 290 mf = new Manifest (in); 291 } 292 } catch (IOException ioe) { 293 } finally { 295 if (in != null) { 296 try { 297 in.close(); 298 } catch (IOException ioe) { 299 } 301 } 302 } 303 return mf; 304 } 305 306 315 private static List getManifestClassPath(Manifest manifest, 316 String rootPath) { 317 318 List classPaths = new ArrayList (); 319 320 if (manifest != null) { 321 Attributes mainAttributes = manifest.getMainAttributes(); 322 323 for (Iterator itr=mainAttributes.keySet().iterator(); 324 itr.hasNext();) { 325 326 Attributes.Name next = (Attributes.Name ) itr.next(); 327 328 if (next.equals(Attributes.Name.CLASS_PATH)) { 329 330 String classpathString = (String ) mainAttributes.get(next); 331 StringTokenizer st = 332 new StringTokenizer (classpathString, " "); 333 334 while(st.hasMoreTokens()) { 335 String mc = st.nextToken(); 336 classPaths.add(rootPath+File.separator+mc); 337 } 338 } 339 } 340 } 341 342 return classPaths; 343 } 344 345 public static EJBClassLoader createEJBClassLoader(String [] classPaths, 346 String moduleRoot, String id, ClassLoader parentClassLoader, 347 ModuleType moduleType) { 348 URL [] classPathURLs = new URL [0]; 349 if (classPaths != null) { 350 351 int classPathSize = classPaths.length; 352 classPathURLs = new URL [classPathSize]; 353 354 for (int i=0; i<classPathSize; i++) { 355 try { 356 classPathURLs[i] = (new File(classPaths[i])).toURI().toURL(); 357 } catch (MalformedURLException malEx) { 358 _logger.log(Level.WARNING, 359 "loader.cannot_convert_classpath_into_url", 360 classPaths[i]); 361 _logger.log(Level.WARNING,"loader.exception", malEx); 362 } 363 } 364 } 365 366 String libs = null; 367 if (moduleType.equals(ModuleType.EAR)) { 369 libs = ASClassLoaderUtil.getLibrariesForJ2EEApplication(id); 370 } else if (moduleType.equals(ModuleType.EJB)) { 371 libs = ASClassLoaderUtil.getLibrariesForEJBJars(id); 372 } 373 374 URL [] deployTimeLibraries = ASClassLoaderUtil.getLibraries(libs); 375 URL [] resolvedLibrariesList = null; 376 377 if (deployTimeLibraries != null) { 378 if (deployTimeLibraries.length > 0) { 379 resolvedLibrariesList = resolveVersionConflicts( 380 EJBClassPathUtils.getManifest(moduleRoot), 381 deployTimeLibraries,classPaths); 382 } 383 } 384 385 if (_logger.isLoggable(Level.FINE)) { 386 _logger.log(Level.FINE, "createEJBClassLoader :: Resolved libraries " + resolvedLibrariesList); 387 } 388 ClassLoader applicationLibrariesCL = createApplicationLibrariesClassLoader( 389 parentClassLoader, resolvedLibrariesList, id); 390 if (_logger.isLoggable(Level.FINE)) { 391 _logger.log(Level.FINE, "- applibsCL: " + applicationLibrariesCL); 392 } 393 return createEJBClassLoader(parentClassLoader, applicationLibrariesCL, classPathURLs); 394 } 395 396 397 416 private static URL [] resolveVersionConflicts(Manifest mf, URL [] deployTimeLibraries, 417 String [] applicationClasspath) { 418 try { 419 String appList = mf.getMainAttributes().getValue( 420 Attributes.Name.EXTENSION_LIST); 421 if (appList == null) return deployTimeLibraries; 422 String [] appExtensions = appList.split(" " ); 423 if (_logger.isLoggable(Level.FINE)) { 424 _logger.log(Level.FINE, "Application Extension List" + appExtensions); 425 } 426 427 List <URL > conflictingLibraries = new ArrayList <URL >(); 428 for (int i = 0; i < appExtensions.length; i++) { 429 String extensionName = mf.getMainAttributes(). 430 getValue(appExtensions[i] + "-Extension-Name"); 431 String extensionSpecVersion = mf.getMainAttributes(). 432 getValue(appExtensions[i] + "-Extension-Specification-Version"); 433 String extensionImplVersion = mf.getMainAttributes(). 434 getValue(appExtensions[i] + "-Extension-Implementation-Version"); 435 if(bundledExtensionMatches(applicationClasspath, extensionName, 436 extensionSpecVersion, 437 extensionImplVersion )){ 438 URL url = isExtensionInLibraries(extensionName, deployTimeLibraries); 439 if(url != null){ 440 conflictingLibraries.add(url); 441 } 442 } 443 } 444 445 List <URL > resolvedList = new ArrayList <URL >(); 447 for (int i = 0; i < deployTimeLibraries.length; i++) { 448 if (!conflictingLibraries.contains(deployTimeLibraries[i])) { 449 resolvedList.add(deployTimeLibraries[i]); 450 } else { 451 if (_logger.isLoggable(Level.FINE)) { 452 _logger.log(Level.FINE, " conflict " + deployTimeLibraries[i] + 453 "being ignored"); 454 } 455 } 456 } 457 458 if (_logger.isLoggable(Level.FINE)) { 459 _logger.log(Level.FINE, " Final resolved list after conflict" 460 + "checking " + resolvedList); 461 } 462 return resolvedList.toArray(new URL []{}); 463 } catch (IOException ioe) { 464 _logger.log(Level.WARNING, ioe.getMessage()); 465 _logger.log(Level.FINE, "Exception while checking for version " + 466 "conflict in bundled vs provided libraries", ioe); 467 } 468 return deployTimeLibraries; 469 } 470 471 475 private static URL isExtensionInLibraries(String extensionName, 476 URL [] deployTimeLibrariesList) throws IOException { 477 for (int i = 0; i < deployTimeLibrariesList.length; i++) { 478 JarFile jf = new JarFile (deployTimeLibrariesList[i].getFile()); 479 String extnName = jf.getManifest().getMainAttributes().getValue( 480 Attributes.Name.EXTENSION_NAME); 481 if (extnName.equals(extensionName)) { 482 if (_logger.isLoggable(Level.FINE)) { 483 _logger.log(Level.FINE, "extensionName" + extensionName + 484 "matched by " + deployTimeLibrariesList[i] + " = CONFLICT"); 485 } 486 return deployTimeLibrariesList[i]; 487 } 488 } 489 return null; 490 } 491 492 495 private static boolean bundledExtensionMatches(String [] applicationClasspath, 496 String extnName, String extnSpecVersion, String extnImplVersion) throws IOException { 497 for (int i = 0; i < applicationClasspath.length; i++) { 498 JarFile jf = new JarFile (applicationClasspath[i]); 499 String bundledExtnName = jf.getManifest().getMainAttributes(). 500 getValue(Attributes.Name.EXTENSION_NAME); 501 String bundledExtnImplVersion = jf.getManifest().getMainAttributes(). 502 getValue(Attributes.Name.IMPLEMENTATION_VERSION); 503 String bundledExtnSpecVersion = jf.getManifest().getMainAttributes(). 504 getValue(Attributes.Name.SPECIFICATION_VERSION); 505 if ( 506 (extnName.equals(bundledExtnName)) && 507 ((extnSpecVersion != null) && (bundledExtnSpecVersion.compareTo(extnSpecVersion) >=0)) 508 && ((extnImplVersion != null) && (bundledExtnImplVersion.compareTo(extnImplVersion) >=0)) 509 ) { 510 if (_logger.isLoggable(Level.FINE)) { 511 _logger.log(Level.FINE, "extensionName" + bundledExtnName + 512 "spec version: " + bundledExtnSpecVersion + 513 "impl version: " + bundledExtnImplVersion + 514 "matches within the application"); 515 } 516 return true; 517 } 518 } 519 return false; 520 } 521 522 523 528 private static ClassLoader createApplicationLibrariesClassLoader( 529 ClassLoader parentClassLoader, URL [] urlList, String moduleId) { 530 if( urlList != null ) { 531 ClassLoaderChain appChain = new ClassLoaderChain(parentClassLoader); 532 appChain.setName("Application library chain for " + moduleId); 533 for(URL url:urlList){ 534 ClassLoader urlLoader = classLoaderRegistry.get(url); 535 if(urlLoader == null) { 538 urlLoader = new ASURLClassLoader(new URL []{url}, parentClassLoader); 539 classLoaderRegistry.put(url,urlLoader); 540 } 541 appChain.addToList(urlLoader); 542 } 543 544 ClassLoader optionalChain = PELaunch.getOptionalChain(); 548 appChain.addToList(optionalChain); 549 return appChain; 550 } 551 return null; 552 } 553 554 private static EJBClassLoader createEJBClassLoader( ClassLoader parentClassLoader, 555 ClassLoader appLibLoader,URL [] URLs ) { 556 EJBClassLoader loader = null; 557 if (appLibLoader != null) { 558 loader = new EJBClassLoader(appLibLoader); 559 } else { 560 loader = new EJBClassLoader(parentClassLoader); 561 } 562 563 if (URLs != null) { 564 for(int i=0; i<URLs.length; i++) { 565 loader.appendURL(URLs[i]); 566 } 567 } 568 return loader; 569 } 570 571 572 573 574 private static final String MANIFEST_ENTRY = 575 "META-INF" + File.separator + "MANIFEST.MF"; 576 577 private static final String WAR_CLASSES_DIR = 578 "WEB-INF"+ File.separator + "classes"; 579 580 private static final String WAR_LIB_DIR = 581 "WEB-INF"+ File.separator + "lib"; 582 } 583 | Popular Tags |