001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * Permission is hereby granted, without written agreement and without 005 * license or royalty fees, to use, copy, modify, and distribute this 006 * software and its documentation for any purpose, provided that the above 007 * copyright notice and the following two paragraphs appear in all copies 008 * of this software. 009 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 010 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 011 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 012 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 013 * SUCH DAMAGE. 014 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 015 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 016 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 017 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 018 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 019 * ENHANCEMENTS, OR MODIFICATIONS. 020 * PT_COPYRIGHT_VERSION_2 021 * COPYRIGHTENDKEY 022 */ 023package org.kepler.kar; 024 025import java.io.File; 026import java.io.IOException; 027import java.io.Serializable; 028import java.util.ArrayList; 029import java.util.Enumeration; 030import java.util.Hashtable; 031import java.util.Iterator; 032import java.util.List; 033import java.util.Map; 034import java.util.Set; 035import java.util.Vector; 036import java.util.jar.Attributes; 037import java.util.jar.Attributes.Name; 038import java.util.jar.JarEntry; 039import java.util.jar.JarFile; 040import java.util.zip.ZipEntry; 041 042import org.apache.commons.logging.Log; 043import org.apache.commons.logging.LogFactory; 044import org.kepler.build.modules.Module; 045import org.kepler.build.util.Version; 046import org.kepler.configuration.ConfigurationManager; 047import org.kepler.configuration.ConfigurationManagerException; 048import org.kepler.configuration.ConfigurationProperty; 049import org.kepler.configuration.NamespaceException; 050import org.kepler.objectmanager.cache.CacheException; 051import org.kepler.objectmanager.cache.CacheManager; 052import org.kepler.objectmanager.cache.CacheObject; 053import org.kepler.objectmanager.cache.LocalRepositoryManager; 054import org.kepler.objectmanager.lsid.KeplerLSID; 055 056import ptolemy.actor.gui.TableauFrame; 057 058/** 059 * A KAR file is just a jar file that requires a manifest to be present that has 060 * "KAR-Version" and "lsid" main attributes. This KARFile is used for reading 061 * KAR files. For Writing KARFiles see KARBuilder class. 062 * 063 * @author Aaron Schultz 064 */ 065public class KARFile extends JarFile implements Serializable { 066 private static final long serialVersionUID = 1522142700198331341L; 067 private static final Log log = LogFactory.getLog(KARFile.class.getName()); 068 private static final boolean isDebugging = log.isDebugEnabled(); 069 070 /** 071 * This is the current KAR version. 072 */ 073 public static final String VERSION_2_1 = "2.1"; 074 public static final String CURRENT_VERSION = VERSION_2_1; 075 076 /** 077 * Old versions still supported. 078 */ 079 public static final String VERSION_2_0 = "2.0"; 080 public static final String VERSION_1_0 = "1.0"; 081 082 //TODO these variables might be better placed elsewhere 083 /** "strict"*/ 084 public static final String KAR_COMPLIANCE_STRICT = "strict"; 085 /** "relaxed"*/ 086 public static final String KAR_COMPLIANCE_RELAXED = "relaxed"; 087 /** "relaxed" if you change this you should also change KARFILE_CONFIG_PROP_MODULE's configuration.xml 088 we need to keep both for users that started with an earlier version of configuration.xml 089 that lacks the KAR_COMPLIANCE_PROPERTY 090 */ 091 public static final String KAR_COMPLIANCE_DEFAULT = KAR_COMPLIANCE_RELAXED; 092 /** "KARComplianceMode"*/ 093 public static final String KAR_COMPLIANCE_PROPERTY_NAME = "KARComplianceMode"; 094 /** "core" Module*/ 095 public static final Module KARFILE_CONFIG_PROP_MODULE = ConfigurationManager.getModule("core"); 096 097 /** "karVersions"*/ 098 public static final String KAR_VERSIONS_PROPERTY_NAME = "karVersions"; 099 /** "currentVersion" sub-element of karVersions*/ 100 public static final String KAR_CURRENT_VERSION_PROPERTY_NAME = "currentVersion"; 101 /** "karVersion" sub-element of karVersions*/ 102 public static final String KAR_VERSION_PROPERTY_NAME = "karVersion"; 103 /** "version" sub-element of karVersion*/ 104 public static final String KAR_VERSION_VERSION_PROPERTY_NAME = "version"; 105 /** "namespace" sub-element of karVersion*/ 106 public static final String KAR_VERSION_NAMESPACE_PROPERTY_NAME = "namespace"; 107 /** "schemaUrl" sub-element of karVersion*/ 108 public static final String KAR_VERSION_SCHEMAURL_PROPERTY_NAME = "schemaUrl"; 109 /** "resourceDir" sub-element of karVersion*/ 110 public static final String KAR_VERSION_RESOURCEDIR_PROPERTY_NAME = "resourceDir"; 111 /** "resourceFileName" sub-element of karVersion*/ 112 public static final String KAR_VERSION_RESOURCE_FILENAME_PROPERTY_NAME = "resourceFileName"; 113 114 //if you change any of these you must also change KARFILE_CONFIG_PROP_MODULE's configuration.xml 115 public static final String KAR_CURRENT_VERSION_DEFAULT = "2.1"; 116 public static final String KAR_VERSION_200_RESOURCEDIR_DEFAULT = "kar-2.0.0"; 117 public static final String KAR_VERSION_200_RESOURCE_FILENAME_DEFAULT = "KARFile.xsd"; 118 public static final String KAR_VERSION_200_VERSION_DEFAULT = "2.0"; 119 public static final String KAR_VERSION_200_NAMESPACE_DEFAULT = "http://www.kepler-project.org/kar-2.0.0"; 120 public static final String KAR_VERSION_200_SCHEMAURL_DEFAULT = "https://code.kepler-project.org/code/kepler/branches/releases/release-branches/core-2.0/resources/KARFile.xsd"; 121 public static final String KAR_VERSION_210_RESOURCEDIR_DEFAULT = "kar-2.1.0"; 122 public static final String KAR_VERSION_210_RESOURCE_FILENAME_DEFAULT = "KARFile-2.1.0.xsd"; 123 public static final String KAR_VERSION_210_VERSION_DEFAULT = "2.1"; 124 public static final String KAR_VERSION_210_NAMESPACE_DEFAULT = "http://www.kepler-project.org/kar-2.1.0"; 125 public static final String KAR_VERSION_210_SCHEMAURL_DEFAULT = "https://code.kepler-project.org/code/kepler/branches/releases/release-branches/core-2.1/resources/KARFile-2.1.0.xsd"; 126 127 /** 128 * This is the File extension to be used for KAR files. 129 */ 130 public static final String EXTENSION = "kar"; 131 132 /** 133 * This is the list of all supported versions. 134 */ 135 private Vector<String> _supportedVersions = new Vector<String>(); 136 137 /** 138 * <code>Name</code> object for <code>lsid</code> manifest attribute used 139 * for globally identifying KAREntries as unique. 140 */ 141 public static final Name LSID = new Name("lsid"); 142 143 /** 144 * <code>Name</code> object for <code>KAR-Version</code> manifest attribute. 145 * This attribute indicates the version number of the manifest standard to 146 * which a KAR file's manifest conforms. 147 */ 148 public static final Name KAR_VERSION = new Name("KAR-Version"); 149 150 /** 151 * <code>Name</code> object for <code>MOD_DEPEND</code> manifest attribute. 152 * This attribute indicates modules that are needed in order to open this 153 * KAR file. 154 */ 155 public static final Name MOD_DEPEND = new Name("module-dependencies"); 156 157 /** 158 * <code>Name</code> object for <code>OPENABLE</code> manifest attribute. 159 * This attribute indicates whether or not this KAR file is openable. 160 */ 161 public static final Name OPENABLE = new Name("openable"); 162 163 /** 164 * Separator to be used for dependency lists. 165 */ 166 public static final String DEP_SEPARATOR = ";"; 167 168 /** 169 * If the KARFile object was created from a KARFile on disk this is the File 170 * path and name of that file. 171 */ 172 private File _fileOnDisk; 173 174 /** 175 * A list of all the entry types contained in this KARFile indexed by LSID. 176 */ 177 private Hashtable<KeplerLSID, String> _lsidTypes = new Hashtable<KeplerLSID, String>(); 178 179 /** 180 * A list of all the entry names contained in this KARFile indexed by LSID. 181 */ 182 private Hashtable<KeplerLSID, String> _lsidNames = new Hashtable<KeplerLSID, String>(); 183 184 /** 185 * Constructor for creating a KARFile from an existing file. 186 * 187 * @param f 188 * the file to create the KAR from 189 * @throws IOException 190 */ 191 public KARFile(File f) throws IOException { 192 super(f); 193 if (isDebugging) 194 log.debug("KARFile(" + f + ")"); 195 196 _fileOnDisk = f; 197 198 initializeSupportedVersions(); 199 200 if (getManifest() == null) { 201 throw new IOException("This KAR file does not contain a Manifest."); 202 } 203 204 String lsidStr = getManifest().getMainAttributes().getValue(LSID); 205 if (isDebugging) 206 log.debug(lsidStr); 207 if (lsidStr == null) { 208 throw new IOException( 209 "The KAR file does not contain an lsid attribute in the manifest"); 210 } 211 if (!KeplerLSID.isKeplerLSIDFormat(lsidStr)) { 212 throw new IOException( 213 "The LSID of the KAR file is not properly formatted."); 214 } 215 216 String version = getManifest().getMainAttributes() 217 .getValue(KAR_VERSION); 218 if (version == null) { 219 throw new IOException( 220 "The KAR file does not contain a KAR-Version attribute in the manifest."); 221 } 222 if (!_supportedVersions.contains(version)) { 223 throw new IOException(version 224 + " is not a supported KAR version.\n" 225 + getSupportedVersionString()); 226 } 227 228 Enumeration<JarEntry> karFileEnum = entries(); 229 while (karFileEnum.hasMoreElements()) { 230 JarEntry entry = (JarEntry) karFileEnum.nextElement(); 231 KeplerLSID lsid = getEntryLSID(entry); 232 String type = getEntryType(entry); 233 if (lsid != null && type != null) { 234 _lsidNames.put(lsid, entry.getName()); 235 _lsidTypes.put(lsid, type); 236 } 237 } 238 239 } 240 241 private void initializeSupportedVersions() { 242 _supportedVersions.add(VERSION_1_0); 243 _supportedVersions.add(VERSION_2_0); 244 _supportedVersions.add(VERSION_2_1); 245 } 246 247 public KeplerLSID getLSID() { 248 try { 249 return new KeplerLSID(getManifest().getMainAttributes().getValue( 250 LSID)); 251 } catch (Exception e) { 252 return null; 253 } 254 } 255 256 /** 257 * @param lsid 258 * @throws IOException 259 */ 260 public void setLSID(KeplerLSID lsid) throws IOException { 261 Attributes atts = getManifest().getMainAttributes(); 262 if (atts.containsKey(LSID)) { 263 atts.remove(LSID); 264 } 265 atts.put(LSID, lsid.toString()); 266 } 267 268 public String getKARVersion() { 269 try { 270 Attributes atts = getManifest().getMainAttributes(); 271 String karVersion = atts.getValue(KAR_VERSION); 272 return karVersion; 273 } catch (IOException e) { 274 return null; 275 } 276 } 277 278 public boolean isOpenable() { 279 try { 280 Attributes atts = getManifest().getMainAttributes(); 281 String openable = atts.getValue(OPENABLE); 282 if (openable != null) { 283 openable = openable.trim(); 284 if (openable.equalsIgnoreCase("false")) { 285 return false; 286 } 287 } 288 } catch (IOException e) { 289 e.printStackTrace(); 290 } 291 Vector<String>moduleDependencies = getModuleDependencies(); 292 if (ModuleDependencyUtil.checkIfModuleDependenciesSatisfied(moduleDependencies)){ 293 return true; 294 } 295 return false; 296 } 297 298 /** 299 * Set the version of the KARFile. 300 * 301 * @param version 302 * @throws IOException 303 * if the given version is not supported 304 */ 305 public void setVersion(String version) throws IOException { 306 if (_supportedVersions.contains(version)) { 307 Attributes atts = getManifest().getMainAttributes(); 308 if (atts.containsKey(KAR_VERSION)) { 309 atts.remove(KAR_VERSION); 310 } 311 atts.put(KAR_VERSION, version); 312 } else { 313 throw new IOException(version 314 + " is not a supported KAR version.\n" 315 + getSupportedVersionString()); 316 } 317 } 318 319 public Vector<String> getModuleDependencies() { 320 Vector<String> dependencies = new Vector<String>(); 321 try { 322 String depStr = getManifest().getMainAttributes().getValue( 323 MOD_DEPEND); 324 if (depStr == null) { 325 return dependencies; 326 } 327 dependencies = ModuleDependencyUtil.parseDependencyString(depStr); 328 } catch (Exception e) { 329 } 330 return dependencies; 331 } 332 333 /** 334 * Return the LSIDs of all of the entries contained by this KARFile. 335 * 336 * */ 337 public Set<KeplerLSID> getContainedLSIDs() { 338 return _lsidTypes.keySet(); 339 } 340 341 public String getEntryType(KeplerLSID lsid) { 342 return _lsidTypes.get(lsid); 343 } 344 345 public String getEntryName(KeplerLSID lsid) { 346 return _lsidNames.get(lsid); 347 } 348 349 /** 350 * Return the name of the local repository that this KAR is stored in. 351 * 352 * @return null if no name is found 353 */ 354 public String getLocalRepoName() { 355 LocalRepositoryManager lrm = LocalRepositoryManager.getInstance(); 356 LocalRepositoryManager.LocalRepository repository = lrm.getContainingLocalRepository(getFileLocation()); 357 if(repository != null) { 358 return lrm.getLocalRepositories().get(repository); 359 } 360 return null; 361 } 362 363 /** 364 * Return the path where this kar file is found on disk. 365 */ 366 public String getPath() { 367 String filePath = getFileLocation().getPath(); 368 String fileName = getFileLocation().getName(); 369 if (isDebugging) 370 log.debug(filePath + " " + fileName); 371 372 if (filePath.endsWith(fileName)) { 373 // remove the filename 374 int i = filePath.length() - fileName.length(); 375 if (i > 0) { 376 filePath = filePath.substring(0, i); 377 } 378 if (isDebugging) 379 log.debug("New filePath: " + filePath); 380 } 381 return filePath; 382 } 383 384 public File getFileLocation() { 385 return _fileOnDisk; 386 } 387 388 /** 389 * returns a KAREntry for the given lsid. If there is not KAREntry then 390 * return null. 391 * 392 * @param name 393 * the name of the entry to return 394 */ 395 public ZipEntry getKAREntry(KeplerLSID lsid) { 396 String path = _lsidNames.get(lsid); 397 ZipEntry ze = super.getEntry(path); 398 if (ze != null) { 399 return ze; 400 } 401 return null; 402 } 403 404 /** 405 * Returns only valid KAREntries contained in this KARFile. To get all of 406 * the JarEntries use the entries() method. 407 * 408 * @return List<KAREntry> of all valid KAREntries in this KARFile. 409 */ 410 public List<KAREntry> karEntries() { 411 if (isDebugging) 412 log.debug("karEntries()"); 413 Enumeration<JarEntry> entries = entries(); 414 Vector<KAREntry> karEntries = new Vector<KAREntry>(); 415 while (entries.hasMoreElements()) { 416 JarEntry entry = entries.nextElement(); 417 if (isDebugging) 418 log.debug(entry.getName()); 419 if (entry.getName().equals("MANIFEST.MF") 420 || entry.getName().equals("META-INF/") 421 || entry.getName().equals(JarFile.MANIFEST_NAME)) { 422 // skip manifest entries 423 } else { 424 KAREntry karEntry = new KAREntry(entry); 425 if (karEntry.isValid()) { 426 if (isDebugging) 427 log.debug("karEntry.isValid() == true"); 428 karEntries.add(karEntry); 429 } else { 430 if (isDebugging) 431 log.debug("karEntry.isValid() == false"); 432 } 433 } 434 } 435 return karEntries; 436 } 437 438 /** 439 * Return an array of lsids of a certain type from within this kar. if the 440 * type is null return all of the lsids 441 * 442 * @param getType 443 * the type of the content to get 444 */ 445 public KeplerLSID[] getContentOfType(String getType) throws Exception { 446 447 Vector<KeplerLSID> returnVec = new Vector<KeplerLSID>(); 448 for (KeplerLSID lsid : this.getContainedLSIDs()) { 449 String type = this.getEntryType(lsid); 450 if (getType == null || getType.equals(type)) { 451 returnVec.addElement(lsid); 452 } else if (isSubclass(getType, type)) { 453 returnVec.addElement(lsid); 454 } 455 } 456 457 KeplerLSID[] lsids = new KeplerLSID[returnVec.size()]; 458 for (int i = 0; i < returnVec.size(); i++) { 459 lsids[i] = (KeplerLSID) returnVec.elementAt(i); 460 } 461 return lsids; 462 } 463 464 /** 465 * Determine if type is a subclass of getType. This belongs in a UTIL class 466 * somewhere? 467 * 468 * @param getType 469 * @param type 470 * @return 471 * @throws ClassNotFoundException 472 */ 473 public static boolean isSubclass(String getType, String type) 474 throws ClassNotFoundException { 475 476 // protect against nulls 477 if (getType == null || type == null) 478 return false; 479 480 // the superclass test 481 Class getClazz = Class.forName(getType); 482 483 // handle superclasses 484 Class theClazz = Class.forName(type); 485 Class superClazz = theClazz.getSuperclass(); 486 while (superClazz != null) { 487 if (superClazz.getName().equals(getClazz.getName())) { 488 return true; 489 } 490 superClazz = superClazz.getSuperclass(); 491 } 492 return false; 493 } 494 495 /** 496 * @return String of the supported KAR versions. 497 */ 498 private String getSupportedVersionString() { 499 String s = "Supported KAR versions:\n"; 500 for (String v : _supportedVersions) { 501 s += " " + v + "\n"; 502 } 503 return s; 504 } 505 506 /** 507 * Read the LSID from the attributes of the given entry and return it as a 508 * KeplerLSID. 509 * 510 * @param entry 511 * @return 512 * @throws IOException 513 */ 514 private KeplerLSID getEntryLSID(JarEntry entry) throws IOException { 515 Attributes atts = entry.getAttributes(); 516 if (atts == null) { 517 return null; 518 } 519 520 String lsidStr = atts.getValue(KAREntry.LSID); 521 if (lsidStr == null) { 522 log.error("KAREntries must have an LSID and a type."); 523 return null; 524 } 525 526 KeplerLSID lsid = null; 527 try { 528 lsid = new KeplerLSID(lsidStr); 529 } catch (Exception e) { 530 log.warn(lsidStr + " is not a properly formatted KeplerLSID"); 531 return null; 532 } 533 return lsid; 534 } 535 536 /** 537 * Read the type attribute from the given entry and return it as a string. 538 * 539 * @param entry 540 * @return 541 * @throws IOException 542 */ 543 private String getEntryType(JarEntry entry) throws IOException { 544 Attributes atts = entry.getAttributes(); 545 if (atts == null) { 546 return null; 547 } 548 String type = atts.getValue(KAREntry.TYPE); 549 return type; 550 } 551 552 /** 553 * This method makes sure that all of the entries of this KARFile are in the 554 * Cache. It caches the entries in the order that their dependencies 555 * dictate. 556 * 557 * @throws Exception 558 */ 559 public void cacheKARContents() throws Exception { 560 if (isDebugging) { 561 log.debug("openKAR: " + this.toString()); 562 } 563 try { 564 // get references to all the managers we'll be using 565 LocalRepositoryManager lrm = LocalRepositoryManager.getInstance(); 566 KARCacheManager kcm = KARCacheManager.getInstance(); 567 CacheManager cm = CacheManager.getInstance(); 568 569 // Make sure the file is in a local repository 570 if (!lrm.isInLocalRepository(getFileLocation())) { 571 log 572 .warn("KAR should be in a Local Repository Folder to be inserted in the cache: " 573 + getFileLocation()); 574 // return; 575 } 576 577 // Add a row to the KARS_CACHED table 578 boolean inserted = kcm.insertIntoCache(this); 579 if (!inserted) { 580 // This KAR has already been cached, don't do it again 581 return; 582 } 583 584 // keep two lists while traversing the dependencies, start with all 585 // of the entries (we don't know yet if they are cached or not) 586 // and move them into the cached entries as they are cached (or if 587 // they are already cached) 588 Vector<KAREntry> entries = (Vector<KAREntry>) karEntries(); 589 Hashtable<KeplerLSID, KAREntry> cachedEntries = new Hashtable<KeplerLSID, KAREntry>(); 590 591 // do one pass through the entries to see if any of them are already 592 // in the cache 593 for (KAREntry entry : entries) { 594 KeplerLSID lsid = entry.getLSID(); 595 596 // See if this entry is already in the Cache 597 boolean alreadyCached = cm.isContained(lsid); 598 if (alreadyCached) { 599 600 // add this entry into the cachedEntries list 601 cachedEntries.put(entry.getLSID(), entry); 602 603 // Insert a row into the KAR_CONTENTS table for this entry 604 File karFile = getFileLocation(); 605 KeplerLSID entryLsid = entry.getLSID(); 606 String entryName = entry.getName(); 607 String entryType = entry.getType(); 608 kcm.insertEntryIntoCache(karFile, entryLsid, entryName, 609 entryType); 610 } 611 } 612 613 // remove entries that were already cached 614 for (KAREntry entry : cachedEntries.values()) { 615 entries.remove(entry); 616 } 617 618 // keep cycling through the uncached entries until the list is empty 619 while (entries.size() > 0) { 620 621 // keep track of the entries cached during this pass 622 Vector<KAREntry> cachedThisPass = new Vector<KAREntry>(entries 623 .size()); 624 625 // cycle through all of the remaining, uncached entries 626 for (KAREntry entry : entries) { 627 if (isDebugging) 628 log.debug(entry.getName()); 629 630 // get the dependency list for this entry 631 List<KeplerLSID> depList = entry.getLsidDependencies(); 632 633 if (depList.size() == 0) { 634 // if there are no dependencies we just cache it 635 boolean success = cache(entry); 636 if (success) { 637 cachedEntries.put(entry.getLSID(), entry); 638 cachedThisPass.add(entry); 639 break; 640 } 641 if (isDebugging) 642 log.debug(success); 643 } else { 644 // if there are dependencies then we check to make sure 645 // that all of the dependencies have already been cached 646 boolean allDependenciesHaveBeenCached = true; 647 for (KeplerLSID lsid : depList) { 648 // if any of the dependencies have not been cached, 649 // set false 650 if (!cm.isContained(lsid)) { 651 allDependenciesHaveBeenCached = false; 652 } 653 } 654 if (allDependenciesHaveBeenCached) { 655 // all dependencies have been cached so it is 656 // OK to cache this entry 657 boolean success = cache(entry); 658 if (success) { 659 cachedEntries.put(entry.getLSID(), entry); 660 cachedThisPass.add(entry); 661 break; 662 } 663 if (isDebugging) 664 log.debug(success); 665 } 666 } 667 } 668 if (cachedThisPass.size() == 0) { 669 // Bad news, nothing is getting cached 670 // This means that there are uncached entries that 671 // have unsatisfied dependencies 672 // break out to avoid infinite loop 673 // Vector<KAREntry> entriesWithBrokenDependencies = entries; 674 break; 675 } 676 677 // remove any entries that got cached this pass 678 for (KAREntry entry : cachedThisPass) { 679 entries.remove(entry); 680 } 681 682 } 683 } catch (Exception e) { 684 e.printStackTrace(); 685 } 686 687 } 688 689 /** 690 * Here we go through all the KAREntries and call the open method of the 691 * appropriate KAREntryHandlers. It is assumed that cacheKARContents() has 692 * been called at some point before openKAR() In other words everything in 693 * the kar is already cached when calling the open() method of the 694 * KAREntryHandlers. 695 * 696 * Note: There is some issue with having this method here, since it is 697 * really a gui specific function it probably does not belong here in the 698 * core module. 699 * 700 * @param tableauFrame 701 * @param forceOpen 702 * @throws Exception 703 * @returns true if at least one of the entries in the KAR was opened 704 */ 705 public boolean openKARContents(TableauFrame tableauFrame, boolean forceOpen) throws Exception { 706 if (isDebugging) 707 log.debug("openKAR: " + this.toString()); 708 709 if (!forceOpen && !isOpenable()){ 710 return false; 711 } 712 713 try { 714 715 /** 716 * Loop through the kar entries and call the open method of the 717 * appropriate KAREntryHandler 718 */ 719 Vector<KAREntry> unopenedEntries = (Vector<KAREntry>) karEntries(); 720 Hashtable<KeplerLSID, KAREntry> openedEntries = new Hashtable<KeplerLSID, KAREntry>(); 721 722 // keep cycling through the unopened entries until the list is empty 723 while (unopenedEntries.size() > 0) { 724 725 // keep track of the entries that were opened during this pass 726 Vector<KAREntry> openedThisPass = new Vector<KAREntry>( 727 unopenedEntries.size()); 728 729 // cycle through all of the remaining, unopened entries 730 for (KAREntry entry : unopenedEntries) { 731 if (isDebugging) { 732 log.debug(entry.getName()); 733 } 734 735 // get the dependency list for this entry 736 List<KeplerLSID> depList = entry.getLsidDependencies(); 737 738 if (depList.size() == 0) { 739 // if there are no dependencies we just open it up 740 boolean success = open(entry, tableauFrame); 741 if (success) { 742 openedEntries.put(entry.getLSID(), entry); 743 openedThisPass.add(entry); 744 break; 745 } 746 if (isDebugging) 747 log.debug(success); 748 } else { 749 // if there are dependencies then we check to make sure 750 // that all of the dependencies have already been opened 751 boolean allDependenciesHaveBeenOpened = true; 752 for (KeplerLSID lsid : depList) { 753 // if any of the dependencies have not been opened, 754 // set false 755 if (!openedEntries.containsKey(lsid)) { 756 allDependenciesHaveBeenOpened = false; 757 } 758 } 759 if (allDependenciesHaveBeenOpened) { 760 // dependencies have been opened so OK to open this 761 // one 762 boolean success = open(entry, tableauFrame); 763 if (success) { 764 openedEntries.put(entry.getLSID(), entry); 765 openedThisPass.add(entry); 766 break; 767 } 768 if (isDebugging) 769 log.debug(success); 770 } 771 } 772 } 773 774 if (openedThisPass.size() == 0) { 775 // Bad news, nothing is getting opened 776 // break out to avoid infinite loop 777 break; 778 } 779 780 // remove the entries that were opened during this pass 781 for (KAREntry entry : openedThisPass) { 782 unopenedEntries.remove(entry); 783 } 784 } 785 786 787 if (openedEntries.size() == 0) { 788 return false; 789 } 790 } catch (Exception e) { 791 throw new Exception("Error on Open: " + e.getMessage()); 792 } 793 return true; 794 } 795 796 /** 797 * Get all the KAREntryHandlers that can handle the given entry. 798 * 799 * @param entry 800 * @return KAREntryHandlers that can handle the given entry. 801 */ 802 private Vector<KAREntryHandler> getHandlersForEntry(KAREntry entry) { 803 Vector<KAREntryHandler> handlers = new Vector<KAREntryHandler>(2); 804 805 // First we make sure that the EntryHandler that wrote the entry 806 // is present in the system 807 try { 808 // check for it in the classpath 809 Class.forName(entry.getHandler()); 810 } catch (Exception e) { 811 log.warn("KAREntryHandler not in classpath: " + entry.getHandler()); 812 return handlers; 813 } 814 815 try { 816 // check to see if it is registered with the KAREntryHandler 817 // extension point 818 boolean writeHandlerPresent = false; 819 for (KAREntryHandler k : CacheManager.getInstance() 820 .getKAREntryHandlers()) 821 { 822 if (k.getClass().getName().equals(entry.getHandler())) { 823 writeHandlerPresent = true; 824 break; 825 } 826 } 827 if (writeHandlerPresent) { 828 // continue looking for EntryHandlers that handle this type 829 } else { 830 log.warn("KAREntryHandler is not registered with suite: " 831 + entry.getHandler()); 832 return handlers; 833 } 834 } catch (CacheException e1) { 835 e1.printStackTrace(); 836 } catch (Exception e) { 837 } 838 839 KeplerLSID lsid = entry.getLSID(); 840 String type = entry.getType(); 841 if (isDebugging) 842 log.debug(lsid + " " + type); 843 if (lsid == null || type == null) { 844 return null; 845 } 846 try { 847 if (getKARVersion().equals(VERSION_1_0)) { 848 // In version 1.0 KARs the type is a one word string 849 // that identifies what type of file it is 850 for (KAREntryHandler k : CacheManager.getInstance() 851 .getKAREntryHandlers()) { 852 if (k.getTypeName().equals(type)) { 853 handlers.add(k); 854 } 855 } 856 } else if (getKARVersion().equals(VERSION_2_0) || 857 getKARVersion().equals(VERSION_2_1)) { 858 // In version 2.0 and 2.1 KARs the type is the binary class 859 // name for the type of file that the KAREntry is. 860 // A KAREntryHandler may be able to handle more than 861 // one type in version 2.0 and 2.1 862 for (KAREntryHandler k : CacheManager.getInstance() 863 .getKAREntryHandlers()) { 864 if (k.handlesType(type)) { 865 handlers.add(k); 866 } 867 } 868 } 869 } catch (CacheException e) { 870 e.printStackTrace(); 871 } 872 return handlers; 873 } 874 875 /** 876 * Insert the object into the cache and record it in the kar contents table. 877 * 878 * @param entry 879 * @return true if the entry could be cached 880 */ 881 private boolean cache(KAREntry entry) { 882 if (entry.getAttributes() == null) { 883 return false; 884 } 885 886 CacheManager cm; 887 KARCacheManager kcm; 888 try { 889 cm = CacheManager.getInstance(); 890 kcm = KARCacheManager.getInstance(); 891 892 if (cm.isContained(entry.getLSID())) { 893 // This entry is already cached 894 // make sure there is a row for it in the KAR_CONTENTS table 895 File karFile = getFileLocation(); 896 KeplerLSID entryLsid = entry.getLSID(); 897 String entryName = entry.getName(); 898 String entryType = entry.getType(); 899 kcm.insertEntryIntoCache(karFile, entryLsid, entryName, 900 entryType); 901 return true; 902 } 903 } catch (CacheException e1) { 904 e1.printStackTrace(); 905 return false; 906 } 907 908 // get all KAREntryHandlers for this KAREntry 909 Vector<KAREntryHandler> handlers = getHandlersForEntry(entry); 910 if (handlers == null) 911 return false; 912 913 if (handlers.size() <= 0) { 914 // this KAREntry type is not recognized ignore it 915 log.warn("No KAREntryHandlers found for KAREntry: " + entry.getName() +" ignoring this item."); 916 return false; 917 } 918 919 // loop through all of the handlers and pass the entry to their cache 920 // method 921 // if they return a cache object then insert it into the cache. 922 for (KAREntryHandler keh : handlers) { 923 try { 924 CacheObject co = keh.cache(this, entry); 925 if (co != null) { 926 927 // The handler returned a CacheObject, insert it into the 928 // cache 929 cm.insertObject(co); 930 931 // Insert a row into the KAR_CONTENTS table for this entry 932 File karFile = getFileLocation(); 933 KeplerLSID entryLsid = entry.getLSID(); 934 String entryName = entry.getName(); 935 String entryType = entry.getType(); 936 kcm.insertEntryIntoCache(karFile, entryLsid, entryName, 937 entryType); 938 939 } 940 } catch (CacheException ce) { 941 log.warn("KAREntry was not cached: " + entry.getName()); 942 } catch (Exception e) { 943 e.printStackTrace(); 944 } 945 } 946 947 return true; 948 } 949 950 /** 951 * Call the open methods of all KAREntryHandlers that support the type of 952 * the given entry. 953 * 954 * @param entry 955 * @param tableauFrame 956 * @return 957 */ 958 public boolean open(KAREntry entry, TableauFrame tableauFrame) { 959 Vector<KAREntryHandler> handlers = getHandlersForEntry(entry); 960 if (handlers == null) 961 return false; 962 963 if (handlers.size() <= 0) { 964 // this KAREntry type is not recognized ignore it 965 log.warn("No KAREntryHandlers found for KAREntry: " + entry.getName() +" ignoring this item."); 966 return false; 967 } 968 969 boolean allsuccess = true; 970 for (KAREntryHandler keh : handlers) { 971 try { 972 boolean success = keh.open(this, entry, tableauFrame); 973 if (!success) { 974 allsuccess = false; 975 } 976 if (isDebugging) 977 log.debug(success); 978 } catch (Exception e) { 979 e.printStackTrace(); 980 } 981 } 982 return allsuccess; 983 984 } 985 986 public boolean areAllModuleDependenciesSatisfied(){ 987 return ModuleDependencyUtil.checkIfModuleDependenciesSatisfied(this.getModuleDependencies()); 988 } 989 990 /** Get a map of missing module dependencies. */ 991 public Map<String, Version> getMissingDependencies() { 992 993 List<String> dependencies = getModuleDependencies(); 994 return ModuleDependencyUtil.getUnsatisfiedDependencies(dependencies); 995 996 } 997 998 /** 999 * @return karVersions configuration property, adding it to config file 1000 * if it doesn't exist. 1001 */ 1002 public static ConfigurationProperty getKARVersionsConfigProperty() { 1003 1004 ConfigurationManager cman = ConfigurationManager.getInstance(); 1005 ConfigurationProperty coreProperty = cman 1006 .getProperty(KARFILE_CONFIG_PROP_MODULE); 1007 ConfigurationProperty KARVersionsProp = coreProperty 1008 .getProperty(KAR_VERSIONS_PROPERTY_NAME); 1009 1010 try { 1011 1012 // add karVersions configuration property (and all sub props) if 1013 // necessary 1014 if (KARVersionsProp == null) { 1015 KARVersionsProp = new ConfigurationProperty( 1016 KARFILE_CONFIG_PROP_MODULE, KAR_VERSIONS_PROPERTY_NAME); 1017 coreProperty.addProperty(KARVersionsProp); 1018 1019 ConfigurationProperty KARCurrentVersionProp = new ConfigurationProperty( 1020 KARFile.KARFILE_CONFIG_PROP_MODULE, 1021 KARFile.KAR_CURRENT_VERSION_PROPERTY_NAME, 1022 KARFile.KAR_CURRENT_VERSION_DEFAULT); 1023 1024 ConfigurationProperty KARVersion200Prop = new ConfigurationProperty( 1025 KARFile.KARFILE_CONFIG_PROP_MODULE, 1026 KARFile.KAR_VERSION_PROPERTY_NAME); 1027 ConfigurationProperty KARVersion200VersionProp = new ConfigurationProperty( 1028 KARFile.KARFILE_CONFIG_PROP_MODULE, 1029 KARFile.KAR_VERSION_VERSION_PROPERTY_NAME, 1030 KARFile.KAR_VERSION_200_VERSION_DEFAULT); 1031 ConfigurationProperty KARVersion200SchemaUrlProp = new ConfigurationProperty( 1032 KARFile.KARFILE_CONFIG_PROP_MODULE, 1033 KARFile.KAR_VERSION_SCHEMAURL_PROPERTY_NAME, 1034 KARFile.KAR_VERSION_200_SCHEMAURL_DEFAULT); 1035 ConfigurationProperty KARVersion200NamespaceProp = new ConfigurationProperty( 1036 KARFile.KARFILE_CONFIG_PROP_MODULE, 1037 KARFile.KAR_VERSION_NAMESPACE_PROPERTY_NAME, 1038 KARFile.KAR_VERSION_200_NAMESPACE_DEFAULT); 1039 ConfigurationProperty KARVersion200ResourceDirProp = new ConfigurationProperty( 1040 KARFile.KARFILE_CONFIG_PROP_MODULE, 1041 KARFile.KAR_VERSION_RESOURCEDIR_PROPERTY_NAME, 1042 KARFile.KAR_VERSION_200_RESOURCEDIR_DEFAULT); 1043 ConfigurationProperty KARVersion200ResourceFileNameProp = new ConfigurationProperty( 1044 KARFile.KARFILE_CONFIG_PROP_MODULE, 1045 KARFile.KAR_VERSION_RESOURCE_FILENAME_PROPERTY_NAME, 1046 KARFile.KAR_VERSION_200_RESOURCE_FILENAME_DEFAULT); 1047 1048 ConfigurationProperty KARVersion210Prop = new ConfigurationProperty( 1049 KARFile.KARFILE_CONFIG_PROP_MODULE, 1050 KARFile.KAR_VERSION_PROPERTY_NAME); 1051 ConfigurationProperty KARVersion210VersionProp = new ConfigurationProperty( 1052 KARFile.KARFILE_CONFIG_PROP_MODULE, 1053 KARFile.KAR_VERSION_VERSION_PROPERTY_NAME, 1054 KARFile.KAR_VERSION_210_VERSION_DEFAULT); 1055 ConfigurationProperty KARVersion210SchemaUrlProp = new ConfigurationProperty( 1056 KARFile.KARFILE_CONFIG_PROP_MODULE, 1057 KARFile.KAR_VERSION_SCHEMAURL_PROPERTY_NAME, 1058 KARFile.KAR_VERSION_210_SCHEMAURL_DEFAULT); 1059 ConfigurationProperty KARVersion210NamespaceProp = new ConfigurationProperty( 1060 KARFile.KARFILE_CONFIG_PROP_MODULE, 1061 KARFile.KAR_VERSION_NAMESPACE_PROPERTY_NAME, 1062 KARFile.KAR_VERSION_210_NAMESPACE_DEFAULT); 1063 ConfigurationProperty KARVersion210ResourceDirProp = new ConfigurationProperty( 1064 KARFile.KARFILE_CONFIG_PROP_MODULE, 1065 KARFile.KAR_VERSION_RESOURCEDIR_PROPERTY_NAME, 1066 KARFile.KAR_VERSION_210_RESOURCEDIR_DEFAULT); 1067 ConfigurationProperty KARVersion210ResourceFileNameProp = new ConfigurationProperty( 1068 KARFile.KARFILE_CONFIG_PROP_MODULE, 1069 KARFile.KAR_VERSION_RESOURCE_FILENAME_PROPERTY_NAME, 1070 KARFile.KAR_VERSION_210_RESOURCE_FILENAME_DEFAULT); 1071 1072 KARVersion200Prop.addProperty(KARVersion200VersionProp); 1073 KARVersion200Prop.addProperty(KARVersion200SchemaUrlProp); 1074 KARVersion200Prop.addProperty(KARVersion200NamespaceProp); 1075 KARVersion200Prop.addProperty(KARVersion200ResourceDirProp); 1076 KARVersion200Prop.addProperty(KARVersion200ResourceFileNameProp); 1077 1078 KARVersion210Prop.addProperty(KARVersion210VersionProp); 1079 KARVersion210Prop.addProperty(KARVersion210SchemaUrlProp); 1080 KARVersion210Prop.addProperty(KARVersion210NamespaceProp); 1081 KARVersion210Prop.addProperty(KARVersion210ResourceDirProp); 1082 KARVersion210Prop.addProperty(KARVersion210ResourceFileNameProp); 1083 1084 KARVersionsProp.addProperty(KARCurrentVersionProp); 1085 KARVersionsProp.addProperty(KARVersion200Prop); 1086 KARVersionsProp.addProperty(KARVersion210Prop); 1087 } 1088 1089 } catch (NamespaceException e) { 1090 // TODO Auto-generated catch block 1091 e.printStackTrace(); 1092 } catch (ConfigurationManagerException e) { 1093 // TODO Auto-generated catch block 1094 e.printStackTrace(); 1095 } 1096 return KARVersionsProp; 1097 1098 } 1099 1100 /** 1101 * 1102 * @return all KAR namespaces found in karVersions config property 1103 */ 1104 public static List<String> getKARNamespaces() { 1105 1106 List<String> namespaces = new ArrayList<String>(); 1107 ConfigurationProperty KARVersionsProp = KARFile.getKARVersionsConfigProperty(); 1108 1109 Iterator<ConfigurationProperty> karVersionsItr = KARVersionsProp 1110 .getProperties().iterator(); 1111 1112 while (karVersionsItr.hasNext()) { 1113 ConfigurationProperty prop = karVersionsItr.next(); 1114 if (prop.getName().equals(KAR_VERSION_PROPERTY_NAME)) { 1115 ConfigurationProperty namespaceConfigProp = prop 1116 .getProperty(KAR_VERSION_NAMESPACE_PROPERTY_NAME); 1117 namespaces.add(namespaceConfigProp.getValue()); 1118 } 1119 } 1120 1121 return namespaces; 1122 } 1123 1124 /** 1125 * Return the local resource dir associated with given namespace, 1126 * null if can't be found. 1127 * 1128 * @param namespace 1129 * @return 1130 */ 1131 public static String getResourceDir(String namespace) { 1132 ConfigurationProperty KARVersionsProp = KARFile 1133 .getKARVersionsConfigProperty(); 1134 1135 Iterator<ConfigurationProperty> karVersionsItr = KARVersionsProp 1136 .getProperties().iterator(); 1137 1138 while (karVersionsItr.hasNext()) { 1139 ConfigurationProperty prop = karVersionsItr.next(); 1140 if (prop.getName().equals(KAR_VERSION_PROPERTY_NAME)) { 1141 String namespaceFromConfig = prop 1142 .getProperty(KAR_VERSION_NAMESPACE_PROPERTY_NAME).getValue(); 1143 if (namespace.equals(namespaceFromConfig)){ 1144 return prop.getProperty(KAR_VERSION_RESOURCEDIR_PROPERTY_NAME).getValue(); 1145 } 1146 } 1147 } 1148 if (isDebugging) 1149 log.error("Couldn't find resourceDir associated with namespace:"+namespace + " return null"); 1150 return null; 1151 } 1152 1153 /** 1154 * Return the local resource filename associated with given namespace, 1155 * null if can't be found. 1156 * 1157 * @param namespace 1158 * @return 1159 */ 1160 public static String getResourceFileName(String namespace) { 1161 ConfigurationProperty KARVersionsProp = KARFile 1162 .getKARVersionsConfigProperty(); 1163 1164 Iterator<ConfigurationProperty> karVersionsItr = KARVersionsProp 1165 .getProperties().iterator(); 1166 1167 while (karVersionsItr.hasNext()) { 1168 ConfigurationProperty prop = karVersionsItr.next(); 1169 if (prop.getName().equals(KAR_VERSION_PROPERTY_NAME)) { 1170 String namespaceFromConfig = prop 1171 .getProperty(KAR_VERSION_NAMESPACE_PROPERTY_NAME).getValue(); 1172 if (namespace.equals(namespaceFromConfig)){ 1173 return prop.getProperty(KAR_VERSION_RESOURCE_FILENAME_PROPERTY_NAME).getValue(); 1174 } 1175 } 1176 } 1177 if (isDebugging) 1178 log.error("Couldn't find resourceFileName associated with namespace:"+namespace + " return null"); 1179 return null; 1180 } 1181 1182}