1 19 20 package org.netbeans.modules.apisupport.project.suite; 21 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.OutputStream ; 28 import java.net.MalformedURLException ; 29 import java.net.URL ; 30 import java.util.Arrays ; 31 import java.util.HashMap ; 32 import java.util.HashSet ; 33 import java.util.Iterator ; 34 import java.util.Map ; 35 import java.util.Properties ; 36 import java.util.Set ; 37 import java.util.jar.JarEntry ; 38 import java.util.jar.JarFile ; 39 import org.netbeans.modules.apisupport.project.ManifestManager; 40 import org.netbeans.modules.apisupport.project.ui.customizer.SuiteProperties; 41 import org.netbeans.modules.apisupport.project.universe.ModuleEntry; 42 import org.netbeans.modules.apisupport.project.universe.ModuleList; 43 import org.netbeans.modules.apisupport.project.universe.NbPlatform; 44 import org.netbeans.spi.project.support.ant.EditableProperties; 45 import org.netbeans.spi.project.support.ant.PropertyUtils; 46 import org.openide.filesystems.FileUtil; 47 import org.openide.util.Utilities; 48 49 53 public final class BrandingSupport { 54 55 private final SuiteProject suiteProject; 56 private final SuiteProperties suiteProperties; 57 private Set brandedModules; 58 private Set brandedBundleKeys; 59 private Set brandedFiles; 60 61 private NbPlatform platform; 62 private final File brandingDir; 63 64 public static final String BRANDING_DIR_PROPERTY = "branding.dir"; private static final String BUNDLE_NAME = "Bundle.properties"; 67 public static BrandingSupport getInstance(final SuiteProperties suiteProperties) throws IOException { 68 return new BrandingSupport(suiteProperties); 69 } 70 71 private BrandingSupport(final SuiteProperties suiteProperties) throws IOException { 72 this.suiteProperties = suiteProperties; 73 this.suiteProject = suiteProperties.getProject(); 74 File suiteDir = suiteProject.getProjectDirectoryFile(); 75 assert suiteDir != null && suiteDir.exists(); 76 brandingDir = new File (suiteDir, getNameOfBrandingFolder()); init(); 78 } 79 80 83 public File getProjectDirectory() { 84 return suiteProject.getProjectDirectoryFile(); 85 } 86 87 90 public File getBrandingRoot() { 91 return new File (getProjectDirectory(), getNameOfBrandingFolder()); 92 } 93 94 98 public File getModuleEntryDirectory(ModuleEntry mEntry) { 99 String relativePath; 100 relativePath = PropertyUtils.relativizeFile( mEntry.getClusterDirectory(), 101 mEntry.getJarLocation()); 102 return new File (getBrandingRoot(),relativePath); 103 } 104 105 108 public File getLocalizingBundle(final ModuleEntry mEntry) { 109 ManifestManager mfm = ManifestManager.getInstanceFromJAR(mEntry.getJarLocation()); 110 File bundle = null; 111 if (mfm != null) { 112 String bundlePath = mfm.getLocalizingBundle(); 113 if (bundlePath != null) { 114 bundle = new File (getModuleEntryDirectory(mEntry),bundlePath); 115 } 116 } 117 return bundle; 118 } 119 120 public boolean isBranded(final BundleKey key) { 121 boolean retval = getBrandedBundleKeys().contains(key); 122 return retval; 123 124 } 125 126 public boolean isBranded(final BrandedFile bFile) { 127 boolean retval = getBrandedFiles().contains(bFile); 128 return retval; 129 130 } 131 132 133 136 public boolean isBranded(final ModuleEntry entry) { 137 boolean retval = getBrandedModules().contains(entry); 138 assert (retval == getModuleEntryDirectory(entry).exists()); 139 return retval; 140 } 141 142 public Set getBrandedModules() { 143 return brandedModules; 144 } 145 146 public Set getBrandedBundleKeys() { 147 return brandedBundleKeys; 148 } 149 150 public Set getBrandedFiles() { 151 return brandedFiles; 152 } 153 154 public Set getLocalizingBundleKeys(final String moduleCodeNameBase, final Set keys) { 155 ModuleEntry foundEntry = getModuleEntry(moduleCodeNameBase); 156 return (foundEntry != null) ? getLocalizingBundleKeys(foundEntry, keys) : null; 157 } 158 159 public Set getLocalizingBundleKeys(final ModuleEntry moduleEntry, final Set keys) { 160 Set retval = new HashSet (); 161 for (Iterator it = getBrandedBundleKeys().iterator(); 162 it.hasNext() && retval.size() != keys.size();) { 163 BundleKey bKey = (BundleKey)it.next(); 164 if (keys.contains(bKey.getKey())) { 165 retval.add(bKey); 166 } 167 } 168 169 if (retval.size() != keys.size()) { 170 loadLocalizedBundlesFromPlatform(moduleEntry, keys, retval); 171 } 172 return (retval.size() != keys.size()) ? null : retval; 173 } 174 175 public BrandedFile getBrandedFile(final String moduleCodeNameBase, final String entryPath) { 176 ModuleEntry foundEntry = getModuleEntry(moduleCodeNameBase); 177 return (foundEntry != null) ? getBrandedFile(foundEntry,entryPath) : null; 178 } 179 180 public BrandedFile getBrandedFile(final ModuleEntry moduleEntry, final String entryPath) { 181 BrandedFile retval = null; 182 try { 183 retval = new BrandedFile(moduleEntry, entryPath); 184 for (Iterator it = getBrandedFiles().iterator();it.hasNext() ;) { 185 BrandedFile bFile = (BrandedFile)it.next(); 186 187 if (retval.equals(bFile)) { 188 retval = bFile; 189 190 } 191 } 192 } catch (MalformedURLException ex) { 193 retval = null; 194 } 195 return retval; 196 } 197 198 public BundleKey getBundleKey(final String moduleCodeNameBase, 199 final String bundleEntry,final String key) { 200 Set keys = new HashSet (); 201 keys.add(key); 202 keys = getBundleKeys(moduleCodeNameBase,bundleEntry, keys); 203 return (keys == null) ? null : (BrandingSupport.BundleKey) keys.toArray()[0]; 204 } 205 206 public Set getBundleKeys(final String moduleCodeNameBase, final String bundleEntry,final Set keys) { 207 ModuleEntry foundEntry = getModuleEntry(moduleCodeNameBase); 208 return (foundEntry != null) ? getBundleKeys(foundEntry,bundleEntry, keys) : null; 209 } 210 211 public Set getBundleKeys(final ModuleEntry moduleEntry, final String bundleEntry, final Set keys) { 212 Set retval = new HashSet (); 213 for (Iterator it = getBrandedBundleKeys().iterator(); 214 it.hasNext() && retval.size() != keys.size();) { 215 BundleKey bKey = (BundleKey)it.next(); 216 if (keys.contains(bKey.getKey())) { 217 retval.add(bKey); 218 } 219 } 220 221 if (retval.size() != keys.size()) { 222 try { 223 loadLocalizedBundlesFromPlatform(moduleEntry, bundleEntry, keys, retval); 224 } catch (IOException ex) { 225 throw new IllegalStateException (); 227 } 228 } 229 230 return (retval.size() != keys.size()) ? null : retval; 231 } 232 233 private ModuleEntry getModuleEntry(final String moduleCodeNameBase) { 234 NbPlatform platform; 235 platform = getActivePlatform(); 236 for (Iterator it = Arrays.asList(platform.getModules()).iterator(); it.hasNext();) { 237 ModuleEntry entry = (ModuleEntry)it.next(); 238 if (entry.getCodeNameBase().equals(moduleCodeNameBase)) { 239 return entry; 240 } 241 } 242 243 return null; 244 } 245 246 private NbPlatform getActivePlatform() { 247 NbPlatform retval = suiteProperties.getActivePlatform(); 248 if (retval != null) { 249 return retval; 250 } else { 251 return NbPlatform.getDefaultPlatform(); 252 } 253 } 254 255 public void brandFile(final BrandedFile bFile) throws IOException { 256 if (!bFile.isModified()) return; 257 258 File target = bFile.getFileLocation(); 259 if (!target.exists()) { 260 target.getParentFile().mkdirs(); 261 target.createNewFile(); 262 } 263 264 assert target.exists(); 265 266 InputStream is = null; 267 OutputStream os = null; 268 try { 269 is = bFile.getBrandingSource().openStream(); 270 os = new FileOutputStream (target); 271 FileUtil.copy(is, os); 272 } finally { 273 if (is != null) { 274 is.close(); 275 } 276 277 if (os != null) { 278 os.close(); 279 } 280 281 brandedFiles.add(bFile); 282 bFile.modified = false; 283 } 284 } 285 286 public void brandFile(final BrandedFile bFile, final Runnable saveTask) throws IOException { 287 if (!bFile.isModified()) return; 288 289 saveTask.run(); 290 brandedFiles.add(bFile); 291 bFile.modified = false; 292 } 293 294 public void brandBundleKey(final BundleKey bundleKey) throws IOException { 295 if (bundleKey == null) { 296 return; 297 } 298 Set keys = new HashSet (); 299 keys.add(bundleKey); 300 brandBundleKeys(keys); 301 } 302 303 public void brandBundleKeys(final Set bundleKeys) throws IOException { 304 init(); 305 Map mentryToEditProp = new HashMap (); 306 for (Iterator it = bundleKeys.iterator();it.hasNext();) { 307 BundleKey bKey = (BundleKey)it.next(); 308 if (bKey.isModified()) { 309 EditableProperties ep = (EditableProperties)mentryToEditProp.get(bKey.getBrandingBundle()); 310 if (ep == null) { 311 File bundle = bKey.getBrandingBundle(); 312 if (!bundle.exists()) { 313 bundle.getParentFile().mkdirs(); 314 bundle.createNewFile(); 315 } 316 ep = getEditableProperties(bundle); 317 mentryToEditProp.put(bKey.getBrandingBundle(), ep); 318 } 319 ep.setProperty(bKey.getKey(), bKey.getValue()); 320 } 321 } 322 323 for (Iterator it = mentryToEditProp.entrySet().iterator();it.hasNext();) { 324 Map.Entry entry = (Map.Entry ) it.next(); 325 File bundle = (File ) entry.getKey(); 326 assert bundle.exists(); 327 storeEditableProperties((EditableProperties) entry.getValue(), bundle); 328 for (Iterator it2 = bundleKeys.iterator();it2.hasNext();) { 329 BundleKey bKey = (BundleKey)it2.next(); 330 File bundle2 = bKey.getBrandingBundle(); 331 if (bundle2.equals(bundle)) { 332 brandedBundleKeys.add(bKey); 333 bKey.modified = false; 334 brandedModules.add(bKey.getModuleEntry()); 335 } 336 } 337 } 338 } 339 340 private void init() throws IOException { 341 NbPlatform newPlatform = getActivePlatform(); 342 343 if (brandedModules == null || !newPlatform.equals(platform)) { 344 brandedModules = new HashSet (); 345 brandedBundleKeys = new HashSet (); 346 brandedFiles = new HashSet (); 347 platform = newPlatform; 348 349 if (brandingDir.exists()) { 350 assert brandingDir.isDirectory(); 351 scanModulesInBrandingDir(brandingDir, platform.getModules()); 352 } 353 } 354 } 355 356 private void scanModulesInBrandingDir(final File srcDir, final ModuleEntry[] platformModules) throws IOException { 357 if (srcDir.getName().endsWith(".jar")) { ModuleEntry foundEntry = null; 359 for (int i = 0; i < platformModules.length; i++){ 360 if (isBrandingForModuleEntry(srcDir, platformModules[i])) { 361 scanBrandedFiles(srcDir, platformModules[i]); 362 363 foundEntry = platformModules[i]; 364 break; 365 } 366 } 367 if (foundEntry != null) { 368 brandedModules.add(foundEntry); 369 } 370 } else { 371 String [] kids = srcDir.list(); 372 assert (kids != null); 373 374 for (int i = 0; i < kids.length; i++) { 375 File kid = new File (srcDir, kids[i]); 376 if (!kid.isDirectory()) { 377 continue; 378 } 379 scanModulesInBrandingDir(kid, platformModules); 380 } 381 } 382 } 383 384 private void scanBrandedFiles(final File srcDir, final ModuleEntry mEntry) throws IOException { 385 String [] kids = srcDir.list(); 386 assert (kids != null); 387 388 for (int i = 0; i < kids.length; i++) { 389 File kid = new File (srcDir, kids[i]); 390 if (!kid.isDirectory()) { 391 if (kid.getName().endsWith(BUNDLE_NAME)) { 392 loadBundleKeys(mEntry, kid); 393 } else { 394 loadBrandedFiles(mEntry, kid); 395 } 396 397 continue; 398 } 399 scanBrandedFiles(kid, mEntry); 400 } 401 } 402 403 private void loadBundleKeys(final ModuleEntry mEntry, 404 final File bundle) throws IOException { 405 406 EditableProperties p = getEditableProperties(bundle); 407 408 for (Iterator it = p.entrySet().iterator(); it.hasNext();) { 409 Map.Entry entry = (Map.Entry )it.next(); 410 brandedBundleKeys.add(new BundleKey(mEntry, bundle,(String )entry.getKey(), (String )entry.getValue())); 411 } 412 } 413 414 private void loadBrandedFiles(final ModuleEntry mEntry, 415 final File file) throws IOException { 416 417 String entryPath = PropertyUtils.relativizeFile(getModuleEntryDirectory(mEntry),file); 418 BrandedFile bf = new BrandedFile(mEntry, file.toURI().toURL(), entryPath); 419 brandedFiles.add(bf); 420 } 421 422 423 private static EditableProperties getEditableProperties(final File bundle) throws IOException { 424 EditableProperties p = new EditableProperties(true); 425 InputStream is; 426 is = new FileInputStream (bundle); 427 try { 428 p.load(is); 429 } finally { 430 is.close(); 431 } 432 433 434 return p; 435 } 436 437 private static void storeEditableProperties(final EditableProperties p, final File bundle) throws IOException { 438 OutputStream os; 439 os = new FileOutputStream (bundle); 440 try { 441 p.store(os); 442 } finally { 443 os.close(); 444 } 445 } 446 447 448 private void loadLocalizedBundlesFromPlatform(final ModuleEntry moduleEntry, final Set keys, final Set bundleKeys) { 449 EditableProperties p; 450 p = ModuleList.loadBundleInfo(moduleEntry.getSourceLocation()).toEditableProperties(); 451 for (Iterator it = p.keySet().iterator(); it.hasNext(); ) { 452 String key = (String )it.next(); 453 if (keys.contains(key)) { 454 String value = (String )p.getProperty(key); 455 bundleKeys.add(new BundleKey(moduleEntry, key, value)); 456 } 457 } 458 } 459 460 private void loadLocalizedBundlesFromPlatform(final ModuleEntry moduleEntry, 461 final String bundleEntry, final Set keys, final Set bundleKeys) throws IOException { 462 Properties p = new Properties (); 463 JarFile module = new JarFile (moduleEntry.getJarLocation()); 464 JarEntry je = module.getJarEntry(bundleEntry); 465 InputStream is = module.getInputStream(je); 466 File bundle = new File (getModuleEntryDirectory(moduleEntry),bundleEntry); 467 try { 468 469 p.load(is); 470 } finally { 471 is.close(); 472 } 473 for (Iterator it = p.keySet().iterator(); it.hasNext(); ) { 474 String key = (String )it.next(); 475 if (keys.contains(key)) { 476 String value = (String )p.getProperty(key); 477 bundleKeys.add(new BundleKey(moduleEntry, bundle, key, value)); 478 } 479 } 480 } 481 482 483 private boolean isBrandingForModuleEntry(final File srcDir, final ModuleEntry mEntry) { 484 boolean retval = mEntry.getJarLocation().getName().equals(srcDir.getName()); 485 if (retval) { 486 String relPath1 = PropertyUtils.relativizeFile( mEntry.getClusterDirectory(), mEntry.getJarLocation().getParentFile()); 487 String relPath2 = PropertyUtils.relativizeFile(brandingDir, srcDir.getParentFile()); 488 489 retval = relPath1.equals(relPath2); 490 } 491 return retval; 492 } 493 494 public final class BundleKey { 495 private final File brandingBundle; 496 private final ModuleEntry moduleEntry; 497 private final String key; 498 private String value; 499 private boolean modified = false; 500 501 private BundleKey(final ModuleEntry moduleEntry, final File brandingBundle, final String key, final String value) { 502 this.moduleEntry = moduleEntry; 503 this.key = key; 504 this.value = value; 505 this.brandingBundle = brandingBundle; 506 } 507 508 private BundleKey(final ModuleEntry mEntry, final String key, final String value) { 509 this(mEntry, getLocalizingBundle(mEntry), key,value); 510 } 511 512 public ModuleEntry getModuleEntry() { 513 return moduleEntry; 514 } 515 516 public String getKey() { 517 return key; 518 } 519 520 public String getValue() { 521 return value; 522 } 523 524 public void setValue(final String value) { 525 if (!this.value.equals(value)) { 526 modified = true; 527 } 528 this.value = value; 529 } 530 531 public boolean equals(Object obj) { 532 boolean retval = false; 533 534 if (obj instanceof BundleKey) { 535 BundleKey bKey = (BundleKey)obj; 536 retval = getKey().equals(bKey.getKey()) 537 && getModuleEntry().equals(bKey.getModuleEntry()) 538 && getBrandingBundle().equals(bKey.getBrandingBundle()); 539 } 540 541 return retval; 542 } 543 544 public int hashCode() { 545 return 0; 546 } 547 548 boolean isModified() { 549 return modified; 550 } 551 552 public File getBrandingBundle() { 553 return brandingBundle; 554 } 555 556 } 557 558 public class BrandedFile { 559 private final ModuleEntry moduleEntry; 560 private final String entryPath; 561 private URL brandingSource; 562 private boolean modified = false; 563 564 private BrandedFile(final ModuleEntry moduleEntry, final String entry) throws MalformedURLException { 565 this(moduleEntry, null, entry); 566 } 567 568 private BrandedFile(final ModuleEntry moduleEntry, final URL source, final String entry) throws MalformedURLException { 569 this.moduleEntry = moduleEntry; 570 this.entryPath = entry; 571 if (source == null) { 572 brandingSource = moduleEntry.getJarLocation().toURI().toURL(); 573 brandingSource = new URL ("jar:" + brandingSource + "!/" + entryPath); } else { 575 brandingSource = source; 576 } 577 578 } 579 580 public ModuleEntry getModuleEntry() { 581 return moduleEntry; 582 } 583 584 public String getEntryPath() { 585 return entryPath; 586 } 587 588 public File getFileLocation() { 589 return new File (getModuleEntryDirectory(getModuleEntry()), getEntryPath()); 590 } 591 592 public URL getBrandingSource() { 593 return brandingSource; 594 } 595 596 public void setBrandingSource(URL brandingSource) { 597 if (!Utilities.compareObjects(brandingSource, this.brandingSource)) { 598 modified = true; 599 } 600 this.brandingSource = brandingSource; 601 } 602 603 public void setBrandingSource(File brandingFile) throws MalformedURLException { 604 setBrandingSource(brandingFile.toURI().toURL()); 605 } 606 607 public boolean isModified() { 608 return modified; 609 } 610 611 public boolean equals(Object obj) { 612 boolean retval = false; 613 614 if (obj instanceof BrandedFile) { 615 BrandedFile bFile = (BrandedFile)obj; 616 retval = getModuleEntry().equals(bFile.getModuleEntry()) 617 && getFileLocation().equals(bFile.getFileLocation()); 618 } 619 620 return retval; 622 } 623 624 public int hashCode() { 625 return 0; 626 } 627 628 } 629 630 public String getNameOfBrandingFolder() { 631 return suiteProject.getEvaluator().getProperty(BRANDING_DIR_PROPERTY); 632 } 633 634 } 635 | Popular Tags |