[hg] main-silver: #184845: The branding suite edit bundles opti...

  • From: Martin Kozeny < >
  • To: , ,
  • Subject: [hg] main-silver: #184845: The branding suite edit bundles opti...
  • Date: Fri, 03 May 2013 03:48:00 -0700

changeset 284e8c0964f5 in main-silver ((none))
details: http://hg.netbeans.org/main-silver/rev/284e8c0964f5
description:
        #184845:  The branding suite edit bundles option now includes 
internationalization options.

diffstat:

 
apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingModel.java
                                        |    4 +-
 
apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingSupport.java
                                      |    4 +-
 apisupport.harness/release/suite.xml                                         
                                                   |    5 +-
 apisupport.project/apichanges.xml                                            
                                                   |   14 +
 apisupport.project/manifest.mf                                               
                                                   |    2 +-
 
apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingModel.java
                                           |  164 +-
 
apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingSupport.java
                                         |  122 +-
 
apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/BrandingEditorPanel.java
                             |    3 +-
 
apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties
                                    |    5 +
 
apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.form
 |  106 +
 
apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.java
 |  929 ++++++++++
 nbbuild/antsrc/org/netbeans/nbbuild/Branding.java                            
                                                   |   38 +-
 12 files changed, 1357 insertions(+), 39 deletions(-)

diffs (1778 lines):

diff --git 
a/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingModel.java
 
b/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingModel.java
--- 
a/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingModel.java
+++ 
b/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingModel.java
@@ -46,6 +46,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
+import java.util.Locale;
 import org.netbeans.api.annotations.common.NonNull;
 import org.netbeans.api.project.Project;
 import org.netbeans.api.project.ProjectManager;
@@ -72,6 +73,7 @@
     public SuiteBrandingModel(@NonNull SuiteProperties suiteProps) {
         assert null != suiteProps;
         this.suiteProps = suiteProps;
+        this.locale = Locale.getDefault();
     }
 
     @Override public void init() {
@@ -167,7 +169,7 @@
         if (brandingPath == null) { // #125160
             brandingPath = "branding"; // NOI18N
         }
-        return new SuiteBrandingSupport(suiteProject, brandingPath);
+        return new SuiteBrandingSupport(suiteProject, brandingPath, 
this.locale);
     }
 
     @Override public void reloadProperties() {
diff --git 
a/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingSupport.java
 
b/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingSupport.java
--- 
a/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingSupport.java
+++ 
b/apisupport.ant/src/org/netbeans/modules/apisupport/project/suite/SuiteBrandingSupport.java
@@ -45,6 +45,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.HashSet;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import org.netbeans.modules.apisupport.project.spi.BrandingSupport;
@@ -58,9 +59,10 @@
     private final SuiteProject project;
     private NbPlatform platform;
 
-    SuiteBrandingSupport(SuiteProject project, String brandingPath) throws 
IOException {
+    SuiteBrandingSupport(SuiteProject project, String brandingPath, Locale 
locale) throws IOException {
         super(project, brandingPath);
         this.project = project;
+        this.locale = locale;
     }
 
     private NbPlatform getActivePlatform() {
diff --git a/apisupport.harness/release/suite.xml 
b/apisupport.harness/release/suite.xml
--- a/apisupport.harness/release/suite.xml
+++ b/apisupport.harness/release/suite.xml
@@ -146,6 +146,9 @@
                 <isset property="branding.token"/>
             </and>
         </condition>
+        <condition property="branding.locales.impl" 
value="${branding.locales}" else="">
+            <isset property="branding.locales"/>
+        </condition>
     </target>
 
     <target name="-release.dir">
@@ -495,7 +498,7 @@
 
     <target name="branding" depends="-init" if="run.branding">
         <mkdir dir="${cluster}"/>
-        <branding cluster="${cluster}" overrides="${branding.dir}" 
token="${branding.token}"/>
+        <branding cluster="${cluster}" overrides="${branding.dir}" 
token="${branding.token}"  locales="${branding.locales.impl}"/>
     </target>
 
     <target name="run" depends="build,-jdk-init" description="Runs this 
suite in place.">
diff --git a/apisupport.project/apichanges.xml 
b/apisupport.project/apichanges.xml
--- a/apisupport.project/apichanges.xml
+++ b/apisupport.project/apichanges.xml
@@ -110,6 +110,20 @@
     <changes>
         <change>
             <api name="apisupport_spi"/>
+            <summary>Modified branding for internationalization</summary>
+            <version major="1" minor="63"/>
+            <date day="1" month="5" year="2013"/>
+            <author login="mkozeny"/>
+            <compatibility addition="yes"/>
+            <description>
+                <code>BrandingModel</code> and <code>BrandingSupport</code> 
now contains branding methods
+                internationalization.
+            </description>
+            <class package="org.netbeans.modules.apisupport.project.spi" 
name="BrandingModel"/>
+            <class package="org.netbeans.modules.apisupport.project.spi" 
name="BrandingSupport"/>
+        </change>
+        <change>
+            <api name="apisupport_spi"/>
             <summary>Added explicitLayer method</summary>
             <version major="1" minor="62"/>
             <date day="26" month="3" year="2013"/>
diff --git a/apisupport.project/manifest.mf b/apisupport.project/manifest.mf
--- a/apisupport.project/manifest.mf
+++ b/apisupport.project/manifest.mf
@@ -4,5 +4,5 @@
 OpenIDE-Module-Requires: javax.script.ScriptEngine.freemarker
 OpenIDE-Module-Layer: 
org/netbeans/modules/apisupport/project/ui/resources/layer.xml
 AutoUpdate-Show-In-Client: false
-OpenIDE-Module-Specification-Version: 1.62
+OpenIDE-Module-Specification-Version: 1.63
 
diff --git 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingModel.java
 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingModel.java
--- 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingModel.java
+++ 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingModel.java
@@ -141,8 +141,13 @@
     /**all BundleKeys the user may have modified through Resource Bundle 
editor panel */
     private final Set<BrandingSupport.BundleKey> generalResourceBundleKeys = 
new HashSet<BrandingSupport.BundleKey>();
     
+    /**Internationalized BundleKeys the user may have modified through 
Internationalized Resource Bundle editor panel */
+    private final Set<BrandingSupport.BundleKey> 
internationalizedResourceBundleKeys = new 
HashSet<BrandingSupport.BundleKey>();
+    
     private final ChangeSupport changeSupport = new ChangeSupport(this);
     
+    protected Locale locale;
+    
     protected BrandingModel() {}
     
     public final boolean isBrandingEnabled() {
@@ -287,6 +292,8 @@
 
             getBranding().brandBundleKeys(generalResourceBundleKeys);
 
+            
getBranding().brandBundleKeys(internationalizedResourceBundleKeys);
+
             FileObject root = 
FileUtil.toFileObject(getBranding().getBrandingRoot());
             if( null != root ) {
                 root.refresh();
@@ -327,6 +334,17 @@
         };
     }
     
+    public void refreshLocalizedBundles(Locale locale) {
+        this.locale = locale;
+        try {
+            branding.refreshLocalizedBundles(locale);
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+         
+        
+    }
+    
     private BrandingSupport getBranding() {
         if (branding == null) {
             try {
@@ -662,6 +680,8 @@
         winsysKeys.remove(null);
 
         generalResourceBundleKeys.clear();
+        
+        internationalizedResourceBundleKeys.clear();
 }
 
     private String backslashesToSlashes (String text) {
@@ -678,10 +698,39 @@
         return null;
     }
 
+    private BrandingSupport.BundleKey 
findInModifiedInternationalizedBundleKeys (String codenamebase, String 
bundlepath, String key) {
+        for (BundleKey bundleKey : internationalizedResourceBundleKeys) {
+            String localizedBundlepath = bundlepath;
+            if(!localizedBundlepath.endsWith("_" + 
this.locale.toString().toLowerCase() + ".properties"))
+                localizedBundlepath = bundlepath.replaceAll(".properties", 
"_" + this.locale.toString().toLowerCase() + ".properties");
+            if (key.equals(bundleKey.getKey()) &&
+                
backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(localizedBundlepath)
 &&
+                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+                return bundleKey;
+        }
+        return null;
+    }
+
     public final void addModifiedGeneralBundleKey (BrandingSupport.BundleKey 
key) {
         generalResourceBundleKeys.add (key);
     }
 
+    public final void addModifiedInternationalizedBundleKey 
(BrandingSupport.BundleKey key) {
+        Set<BrandingSupport.BundleKey> brandedBundleKeys = 
branding.getBrandedBundleKeys();
+        String localizedBundlepath = key.getBundleFilePath();
+        if(!localizedBundlepath.endsWith("_" + 
this.locale.toString().toLowerCase() + ".properties"))
+                localizedBundlepath = 
localizedBundlepath.replaceAll(".properties", "_" + 
this.locale.toString().toLowerCase() + ".properties");
+        File bundleFile = new File(localizedBundlepath);
+        if(!bundleFile.exists()) {
+            for(BrandingSupport.BundleKey keyIter:brandedBundleKeys) {
+                
if(keyIter.getBundleFilePath().equals(key.getBundleFilePath()) && 
!key.getKey().equals(keyIter.getKey())) {
+                    
internationalizedResourceBundleKeys.add(branding.createModifiedBundleKey(keyIter.getModuleEntry(),
 bundleFile, keyIter.getKey(), keyIter.getValue()));
+                }
+            }
+        }
+        internationalizedResourceBundleKeys.add 
(branding.createModifiedBundleKey(key.getModuleEntry(), bundleFile, 
key.getKey(), key.getValue()));
+    }
+
     public final BrandingSupport.BundleKey 
getGeneralBundleKeyForModification(String codenamebase, String bundlepath, 
String key) {
         BrandingSupport.BundleKey bKey = 
findInModifiedGeneralBundleKeys(codenamebase, bundlepath, key);
         return null != bKey ? bKey : 
getBranding().getBundleKey(codenamebase, bundlepath, key);
@@ -693,14 +742,21 @@
                 : getBranding().getBundleKey(codenamebase, bundlepath, 
key).getValue();
     }
 
+    public final BrandingSupport.BundleKey 
getGeneralLocalizedBundleKeyForModification(String codenamebase, String 
bundlepath, String key) {
+        BrandingSupport.BundleKey bKey = 
findInModifiedInternationalizedBundleKeys(codenamebase, bundlepath, key);
+        return null != bKey ? bKey : 
getBranding().getLocalizedBundleKey(codenamebase, bundlepath, key);
+    }
+
+    public final String getLocalizedKeyValue(String bundlepath, String 
codenamebase, String key) {
+        BrandingSupport.BundleKey bKey = 
findInModifiedInternationalizedBundleKeys(codenamebase, bundlepath, key);
+        return null != bKey ? bKey.getValue()
+                : getBranding().getLocalizedBundleKey(codenamebase, 
bundlepath, key).getValue();
+    }
+
     public final boolean isKeyBranded(String bundlepath, String 
codenamebase, String key) {
         // in modified keys?
-        for (BundleKey bundleKey : generalResourceBundleKeys) {
-            if (key.equals(bundleKey.getKey()) &&
-                
backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(bundlepath) &&
-                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+        if(inModifiedKeys(bundlepath, codenamebase, key))
                 return true;
-        }
         // in branded but not modified keys?
         Set<BundleKey> bundleKeys = getBranding().getBrandedBundleKeys();
         for (BundleKey bundleKey : bundleKeys) {
@@ -712,17 +768,103 @@
         return false;
     }
 
+    public final boolean isKeyLocallyBranded(String bundlepath, String 
codenamebase, String key) {
+        // in modified keys?
+        if(inModifiedLocalizedKeys(bundlepath, codenamebase, key))
+            return true;
+        // in branded but not modified keys?
+        Set<BundleKey> bundleKeys = 
getBranding().getLocalizedBrandedBundleKeys();
+        for (BundleKey bundleKey : bundleKeys) {
+            String bundleFilePath = bundleKey.getBundleFilePath();
+            String localizedBundlepath = bundlepath;
+            if(bundleFilePath.endsWith("_" + 
this.locale.toString().toLowerCase() + ".properties"))
+                localizedBundlepath = bundlepath.replaceAll(".properties", 
"_" + this.locale.toString().toLowerCase() + ".properties");
+            if (key.equals(bundleKey.getKey()) &&
+                
backslashesToSlashes(bundleFilePath).endsWith(localizedBundlepath) &&
+                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+                return true;
+        }
+        return false;
+    }
+    
+    private boolean inModifiedKeys(String bundlepath, String codenamebase, 
String key)
+    {
+        // in modified keys?
+        for (BundleKey bundleKey : generalResourceBundleKeys) {
+            if (key.equals(bundleKey.getKey()) &&
+                
backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(bundlepath) &&
+                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+                return true;
+        }
+        return false;
+    }
+
+    private boolean inModifiedLocalizedKeys(String bundlepath, String 
codenamebase, String key)
+    {
+        // in modified keys?
+        for (BundleKey bundleKey : internationalizedResourceBundleKeys) {
+            String localizedBundlepath = bundlepath;
+            if(!localizedBundlepath.endsWith("_" + 
this.locale.toString().toLowerCase() + ".properties"))
+                localizedBundlepath = bundlepath.replaceAll(".properties", 
"_" + this.locale.toString().toLowerCase() + ".properties");
+            if (key.equals(bundleKey.getKey()) &&
+                
backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(localizedBundlepath)
 &&
+                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+                return true;
+        }
+        return false;
+    }
+
     public final boolean isBundleBranded(String bundlepath, String 
codenamebase) {
         // in modified keys?
+        if(inModifiedKeysBundle(bundlepath, codenamebase))
+            return true;
+        // in branded but not modified keys?
+        Set<BundleKey> bundleKeys = getBranding().getBrandedBundleKeys();
+        for (BundleKey bundleKey : bundleKeys) {
+            if 
(backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(bundlepath) &&
+                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+                return true;
+        }
+        return false;
+    }
+    
+    public final boolean isBundleLocallyBranded(String bundlepath, String 
codenamebase) {
+        // in modified keys?
+        if(inModifiedLocalizedKeysBundle(bundlepath, codenamebase))
+            return true;
+        // in branded but not modified keys?
+        Set<BundleKey> bundleKeys = 
getBranding().getLocalizedBrandedBundleKeys();
+        for (BundleKey bundleKey : bundleKeys) {
+            String bundleFilePath = bundleKey.getBundleFilePath();
+            String localizedBundlepath = bundlepath;
+            if(bundleFilePath.endsWith("_" + 
this.locale.toString().toLowerCase() + ".properties"))
+                localizedBundlepath = bundlepath.replaceAll(".properties", 
"_" + this.locale.toString().toLowerCase() + ".properties");
+            if 
(backslashesToSlashes(bundleFilePath).endsWith(localizedBundlepath) &&
+                
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
+                return true;
+        }
+        return false;
+    }
+    
+    private boolean inModifiedKeysBundle(String bundlepath, String 
codenamebase)
+    {
+        // in modified keys?
         for (BundleKey bundleKey : generalResourceBundleKeys) {
             if 
(backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(bundlepath) &&
                 
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
                 return true;
         }
-        // in branded but not modified keys?
-        Set<BundleKey> bundleKeys = getBranding().getBrandedBundleKeys();
-        for (BundleKey bundleKey : bundleKeys) {
-            if 
(backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(bundlepath) &&
+        return false;
+    }
+
+    private boolean inModifiedLocalizedKeysBundle(String bundlepath, String 
codenamebase)
+    {
+        // in modified keys?
+        for (BundleKey bundleKey : internationalizedResourceBundleKeys) {
+            String localizedBundlepath = bundlepath;
+            if(!localizedBundlepath.endsWith("_" + 
this.locale.toString().toLowerCase() + ".properties"))
+                localizedBundlepath = bundlepath.replaceAll(".properties", 
"_" + this.locale.toString().toLowerCase() + ".properties");
+            if 
(backslashesToSlashes(bundleKey.getBundleFilePath()).endsWith(localizedBundlepath)
 &&
                 
codenamebase.equals(bundleKey.getModuleEntry().getCodeNameBase()))
                 return true;
         }
@@ -843,4 +985,8 @@
 
     public void reloadProperties() {}
 
+    public Locale getLocale() {
+        return locale;
 }
+    
+}
diff --git 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingSupport.java
 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingSupport.java
--- 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingSupport.java
+++ 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/spi/BrandingSupport.java
@@ -50,12 +50,14 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.ref.SoftReference;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -90,12 +92,19 @@
     private final Project project;
     private Set<BrandableModule> brandedModules;
     private Set<BundleKey> brandedBundleKeys;
+    private Set<BundleKey> localizedBrandedBundleKeys;
     private Set<BrandedFile> brandedFiles;
 
     private final String brandingPath;
     private final File brandingDir;
     
-    private static final String BUNDLE_NAME = "Bundle.properties"; //NOI18N
+    private static final String BUNDLE_NAME_PREFIX = "Bundle"; //NOI18N
+    private static final String BUNDLE_NAME_SUFFIX = ".properties"; //NOI18N
+
+    protected Locale locale;
+    private final Object LOCK = new Object();
+    private SoftReference<Set<BrandableModule>> cacheLoaded;
+    private boolean isCached;
 
     /**
      * @param p Project to be branded.
@@ -155,6 +164,12 @@
         
     }
     
+    boolean isLocalizedBranded(final BundleKey key) {
+        boolean retval = getLocalizedBrandedBundleKeys().contains(key);
+        return retval;
+        
+    }
+    
     boolean isBranded(final BrandedFile bFile) {
         return getBrandedFiles().contains(bFile);
     }
@@ -176,6 +191,10 @@
         return brandedBundleKeys;
     }
     
+    Set<BundleKey> getLocalizedBrandedBundleKeys() {
+        return localizedBrandedBundleKeys;
+    }
+    
     Set<BrandedFile> getBrandedFiles() {
         return brandedFiles;
     }
@@ -185,9 +204,14 @@
         return (foundEntry != null) ? getLocalizingBundleKeys(foundEntry, 
keys) : null;
     }
     
+    Set<BundleKey> getLocalizedLocalizingBundleKeys(final String 
moduleCodeNameBase, final Set<String> keys) {
+        BrandableModule foundEntry = findBrandableModule(moduleCodeNameBase);
+        return (foundEntry != null) ? getLocalizingBundleKeys(foundEntry, 
keys) : null;
+    }
+    
     private Set<BundleKey> getLocalizingBundleKeys(final BrandableModule 
moduleEntry, final Set<String> keys) {
         Set<BundleKey> retval = new HashSet<BundleKey>();
-        for (Iterator<BundleKey> it = getBrandedBundleKeys().iterator();
+        for (Iterator<BundleKey> it = 
getLocalizedBrandedBundleKeys().iterator();
         it.hasNext() && retval.size() != keys.size();) {
             BundleKey bKey = it.next();
             if (keys.contains(bKey.getKey())) {
@@ -226,18 +250,24 @@
     
     BundleKey getBundleKey(final String moduleCodeNameBase,
             final String bundleEntry,final String key) {
-        Set<BundleKey> keys = getBundleKeys(moduleCodeNameBase, bundleEntry, 
Collections.singleton(key));
+        Set<BundleKey> keys = getBundleKeys(moduleCodeNameBase, bundleEntry, 
Collections.singleton(key), getBrandedBundleKeys());
         return (keys == null) ? null : (BrandingSupport.BundleKey) 
keys.toArray()[0];
     }
     
-    Set<BundleKey> getBundleKeys(final String moduleCodeNameBase, final 
String bundleEntry, final Set<String> keys) {
-        BrandableModule foundEntry = findBrandableModule(moduleCodeNameBase);
-        return (foundEntry != null) ? getBundleKeys(foundEntry, bundleEntry, 
keys) : null;
+    BundleKey getLocalizedBundleKey(final String moduleCodeNameBase,
+            final String bundleEntry,final String key) {
+        Set<BundleKey> keys = getBundleKeys(moduleCodeNameBase, bundleEntry, 
Collections.singleton(key), getLocalizedBrandedBundleKeys());
+        return (keys == null) ? null : (BrandingSupport.BundleKey) 
keys.toArray()[0];
     }
     
-    private Set<BundleKey> getBundleKeys(final BrandableModule moduleEntry, 
final String bundleEntry, final Set<String> keys) {
+    Set<BundleKey> getBundleKeys(final String moduleCodeNameBase, final 
String bundleEntry, final Set<String> keys, Set<BundleKey> bundleKeys) {
+        BrandableModule foundEntry = findBrandableModule(moduleCodeNameBase);
+        return (foundEntry != null) ? getBundleKeys(foundEntry, bundleEntry, 
keys, bundleKeys) : null;
+    }
+    
+    private Set<BundleKey> getBundleKeys(final BrandableModule moduleEntry, 
final String bundleEntry, final Set<String> keys, Set<BundleKey> bundleKeys) {
         Set<BundleKey> retval = new HashSet<BundleKey>();
-        for (Iterator<BundleKey> it = getBrandedBundleKeys().iterator();
+        for (Iterator<BundleKey> it = bundleKeys.iterator();
         it.hasNext() && retval.size() != keys.size();) {
             BundleKey bKey = it.next();
             if (keys.contains(bKey.getKey())) {
@@ -345,10 +375,36 @@
     protected abstract @CheckForNull Set<BrandableModule> loadModules() 
throws IOException;
     
     void init() throws IOException {
-        Set<BrandableModule> loaded = loadModules();
+        Set<BrandableModule> loaded = null;
+        synchronized(LOCK) {
+            isCached = false;
+            loaded = cacheOrLoadModules();
+        }
         if (brandedModules == null || loaded != null) {
             brandedModules = new HashSet<BrandableModule>();
             brandedBundleKeys = new HashSet<BundleKey>();
+            localizedBrandedBundleKeys = new HashSet<BundleKey>();
+            brandedFiles = new HashSet<BrandedFile>();
+            
+            if (brandingDir.exists()) {
+                if(this.locale == null)
+                    this.locale = Locale.getDefault();
+                assert brandingDir.isDirectory();
+                scanModulesInBrandingDir(brandingDir, loaded);
+            }
+        }
+    }
+    
+    void refreshLocalizedBundles(Locale locale) throws IOException {
+        this.locale = locale;
+        Set<BrandableModule> loaded = null;
+        synchronized(LOCK) {
+            loaded = cacheOrLoadModules();
+        }
+        if (brandedModules == null || loaded != null) {
+            brandedModules = new HashSet<BrandableModule>();
+            brandedBundleKeys = new HashSet<BundleKey>();
+            localizedBrandedBundleKeys = new HashSet<BundleKey>();
             brandedFiles = new HashSet<BrandedFile>();
             
             if (brandingDir.exists()) {
@@ -356,6 +412,19 @@
                 scanModulesInBrandingDir(brandingDir, loaded);
             }
         }
+        
+    }
+    
+    private Set<BrandableModule> cacheOrLoadModules() throws IOException {
+        Set<BrandableModule> loaded = null;
+        if(isCached) {
+           loaded = cacheLoaded != null? cacheLoaded.get():null;
+        }
+        if(loaded == null) {
+            cacheLoaded = new SoftReference<Set<BrandableModule>>(loaded = 
loadModules());
+            isCached = true;
+        }
+        return loaded;
     }
     
     private  void scanModulesInBrandingDir(final File srcDir, final 
Set<BrandableModule> platformModules) throws IOException  {
@@ -389,19 +458,28 @@
     private void scanBrandedFiles(final File srcDir, final BrandableModule 
mEntry) throws IOException {
         String[] kids = srcDir.list();
         assert (kids != null);
-        
+        boolean foundLocale = false;
+        File kid = null;
         for (String kidName : kids) {
-            File kid = new File(srcDir, kidName);
+            kid = new File(srcDir, kidName);
             if (!kid.isDirectory()) {
-                if (kid.getName().endsWith(BUNDLE_NAME)) {
+                if (kid.getName().endsWith(BUNDLE_NAME_PREFIX + 
BUNDLE_NAME_SUFFIX)) {
                     loadBundleKeys(mEntry, kid);
+                } else if (kid.getName().endsWith(BUNDLE_NAME_PREFIX + "_" + 
this.locale.toString().toLowerCase() + BUNDLE_NAME_SUFFIX)) {
+                    loadLocalizedBundleKeys(mEntry, kid);
+                    foundLocale = true;
                 } else {
                     loadBrandedFiles(mEntry, kid);
                 }
-                
-                continue;
+            } else {
+                scanBrandedFiles(kid, mEntry);
             }
-            scanBrandedFiles(kid, mEntry);
+        }
+        if(!foundLocale) {
+            File defaultBundle = new File(srcDir, BUNDLE_NAME_PREFIX + 
BUNDLE_NAME_SUFFIX);
+            if(defaultBundle.exists()) {
+                loadLocalizedBundleKeys(mEntry, defaultBundle);
+            }
         }
     }
     
@@ -413,6 +491,14 @@
         }
     }
     
+    private void loadLocalizedBundleKeys(final BrandableModule mEntry,
+            final File bundle) throws IOException {
+        EditableProperties p = getEditableProperties(bundle);
+        for (Map.Entry<String,String> entry : p.entrySet()) {
+            localizedBrandedBundleKeys.add(new BundleKey(mEntry, bundle, 
entry.getKey(), entry.getValue()));
+        }
+    }
+    
     private void loadBrandedFiles(final BrandableModule mEntry,
             final File file) throws IOException {
         String entryPath = 
PropertyUtils.relativizeFile(getModuleEntryDirectory(mEntry),file);
@@ -420,7 +506,6 @@
         brandedFiles.add(bf);
     }
     
-    
     private static EditableProperties getEditableProperties(final File 
bundle) throws IOException {
         EditableProperties p = new EditableProperties(true);
         InputStream is = new FileInputStream(bundle);
@@ -475,6 +560,11 @@
         }
     }
     
+    BundleKey createModifiedBundleKey(final BrandableModule moduleEntry, 
final File brandingBundle, final String key, final String value) {
+        BundleKey bundleKey = new BundleKey(moduleEntry, brandingBundle, 
key, "");
+        bundleKey.setValue(value);
+        return bundleKey;
+    }
     
     private boolean isBrandingForModuleEntry(final File srcDir, final 
BrandableModule mEntry) {
         return 
mEntry.getRelativePath().equals(PropertyUtils.relativizeFile(brandingDir, 
srcDir));
diff --git 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/BrandingEditorPanel.java
 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/BrandingEditorPanel.java
--- 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/BrandingEditorPanel.java
+++ 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/BrandingEditorPanel.java
@@ -75,7 +75,8 @@
             new BasicBrandingPanel(model),
             new SplashBrandingPanel(model),
             new WindowSystemBrandingPanel(model),
-            new ResourceBundleBrandingPanel(model)
+            new ResourceBundleBrandingPanel(model),
+            new InternationalizationResourceBundleBrandingPanel(model)
         };
         for( AbstractBrandingPanel panel : panels ) {
             panel.init(this);
diff --git 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties
 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties
--- 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties
+++ 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties
@@ -119,6 +119,7 @@
 LBL_SplashTab=Splash Screen
 LBL_WindowSystemTab=Window System
 LBL_ResourceBundleTab=Resource Bundles
+LBL_InternationalizationResourceBundleTab=Internationalization Resource 
Bundles
 LBL_ResourceBundlesList=Resource Bundles
 LBL_ResourceBundlesDesc=Resource bundles and their keys that can be branded 
in this project
 LBL_ResourceBundlesExpand=Show all bundle keys
@@ -134,3 +135,7 @@
 WindowSystemBrandingPanel.cbEnableModeSliding.text=Sliding Window Groups
 WindowSystemBrandingPanel.cbEnableModeClosing.text=Closing of Window Groups
 WindowSystemBrandingPanel.cbEnableAutoSlideInMinimizedMode.text=Auto-slide 
Windows in Minimized Window Groups
+InternationalizationResourceBundleBrandingPanel.searchField.text=
+InternationalizationResourceBundleBrandingPanel.searchLabel.AccessibleContext.accessibleDescription=Search
 bundle keys
+InternationalizationResourceBundleBrandingPanel.searchLabel.text=&Search:
+InternationalizationResourceBundleBrandingPanel.localeLabel.text=Locale:
diff --git 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.form
 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.form
new file mode 100644
--- /dev/null
+++ 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.form
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.4" maxVersion="1.7" 
type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <Events>
+    <EventHandler event="componentShown" 
listener="java.awt.event.ComponentListener" 
parameters="java.awt.event.ComponentEvent" handler="formComponentShown"/>
+  </Events>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" 
value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" 
type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" 
value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" 
type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" 
value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" 
value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" 
type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" 
value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" 
value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="1" attributes="0">
+                  <Component id="view" alignment="1" max="32767" 
attributes="0"/>
+                  <Group type="102" alignment="1" attributes="0">
+                      <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                      <Component id="localeLabel" min="-2" max="-2" 
attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="localeComboBox" min="-2" max="-2" 
attributes="0"/>
+                      <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                      <Component id="searchLabel" pref="94" max="32767" 
attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="searchField" min="-2" pref="209" 
max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="searchField" alignment="3" min="-2" 
max="-2" attributes="0"/>
+                  <Component id="searchLabel" alignment="3" min="-2" 
max="-2" attributes="0"/>
+                  <Component id="localeComboBox" alignment="3" min="-2" 
max="-2" attributes="0"/>
+                  <Component id="localeLabel" alignment="3" min="-2" 
max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
+              <Component id="view" pref="258" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="org.openide.explorer.view.BeanTreeView" name="view">
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" 
type="java.lang.String" value="new MyTree();"/>
+      </AuxValues>
+    </Component>
+    <Component class="javax.swing.JLabel" name="searchLabel">
+      <Properties>
+        <Property name="horizontalAlignment" type="int" value="11"/>
+        <Property name="labelFor" type="java.awt.Component" 
editor="org.netbeans.modules.form.ComponentChooserEditor">
+          <ComponentRef name="searchField"/>
+        </Property>
+        <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties"
 key="InternationalizationResourceBundleBrandingPanel.searchLabel.text" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <AccessibilityProperties>
+        <Property name="AccessibleContext.accessibleDescription" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties"
 
key="InternationalizationResourceBundleBrandingPanel.searchLabel.AccessibleContext.accessibleDescription"
 replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </Property>
+      </AccessibilityProperties>
+    </Component>
+    <Component class="javax.swing.JTextField" name="searchField">
+      <Properties>
+        <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties"
 key="InternationalizationResourceBundleBrandingPanel.searchField.text" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="localeLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="org/netbeans/modules/apisupport/project/ui/branding/Bundle.properties"
 key="InternationalizationResourceBundleBrandingPanel.localeLabel.text" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="localeComboBox">
+      <Properties>
+        <Property name="model" type="javax.swing.ComboBoxModel" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+          <Connection code="new javax.swing.DefaultComboBoxModel(locales)" 
type="code"/>
+        </Property>
+      </Properties>
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_InitCodePost" 
type="java.lang.String" 
value="localeComboBox.setSelectedItem(java.util.Locale.getDefault());"/>
+        <AuxValue name="JavaCodeGenerator_InitCodePre" 
type="java.lang.String" value="java.util.Locale [] locales = 
java.util.Locale.getAvailableLocales();&#xa;Comparator&lt;Locale&gt; 
localeComparator = new Comparator&lt;Locale&gt;() {&#xa;&#xa;    
@Override&#xa;    public int compare(Locale o1, Locale o2) {&#xa;        
return o1.toString().compareTo(o2.toString());&#xa;    
}&#xa;};&#xa;java.util.Arrays.sort(locales, localeComparator);"/>
+      </AuxValues>
+    </Component>
+  </SubComponents>
+</Form>
diff --git 
a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.java
 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.java
new file mode 100644
--- /dev/null
+++ 
b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/branding/InternationalizationResourceBundleBrandingPanel.java
@@ -0,0 +1,929 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2010 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.apisupport.project.ui.branding;
+
+import org.netbeans.modules.apisupport.project.spi.BrandingSupport;
+import org.netbeans.modules.apisupport.project.spi.BrandingModel;
+import java.awt.Component;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.ZipException;
+import javax.swing.Action;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.apisupport.project.api.ManifestManager;
+import org.netbeans.modules.apisupport.project.api.UIUtil;
+import org.netbeans.modules.apisupport.project.api.Util;
+import org.netbeans.modules.apisupport.project.spi.PlatformJarProvider;
+import org.netbeans.spi.project.support.ant.EditableProperties;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.actions.EditAction;
+import org.openide.actions.OpenAction;
+import org.openide.cookies.EditCookie;
+import org.openide.cookies.OpenCookie;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.view.BeanTreeView;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.FilterNode;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+import org.openide.util.Utilities;
+import org.openide.util.actions.SystemAction;
+import org.openide.util.lookup.AbstractLookup;
+import org.openide.util.lookup.InstanceContent;
+
+/**
+ *
+ * @author mkozeny
+ */
+public class InternationalizationResourceBundleBrandingPanel extends 
AbstractBrandingPanel
+        implements ExplorerManager.Provider {
+
+    private static final Logger LOG = 
Logger.getLogger(InternationalizationResourceBundleBrandingPanel.class.getName());
+
+    private final ExplorerManager manager;
+    private RootNode rootNode;
+    private final AbstractNode waitRoot;
+    private static final String WAIT_ICON_PATH =
+            
"org/netbeans/modules/apisupport/project/suite/resources/wait.png"; // NOI18N
+
+    private RequestProcessor.Task refreshTask = null;
+    private RequestProcessor RPforRefresh = new 
RequestProcessor(InternationalizationResourceBundleBrandingPanel.class.getName()
 + " - refresh", 1); // NOI18N
+
+    private EditRBAction editRBAction = SystemAction.get 
(EditRBAction.class);
+    private OpenRBAction openRBAction = SystemAction.get 
(OpenRBAction.class);
+    private ExpandAllAction expandAllAction = SystemAction.get 
(ExpandAllAction.class);
+
+    private String searchString = null;
+    private SearchListener searchListener = new SearchListener();
+    private RequestProcessor.Task searchTask = null;
+    private RequestProcessor RPforSearch = new 
RequestProcessor(InternationalizationResourceBundleBrandingPanel.class.getName()
 + " - search", 1); // NOI18N
+
+    private BrandingModel branding;
+    private Project prj;
+    private Locale locale;
+
+    public InternationalizationResourceBundleBrandingPanel(BrandingModel 
model) {
+        super(getMessage("LBL_InternationalizationResourceBundleTab"), 
model); //NOI18N
+        locale = model.getLocale();
+        
+        initComponents();
+
+        searchField.getDocument().addDocumentListener(searchListener);
+        searchField.addFocusListener(searchListener);
+
+        manager = new ExplorerManager();
+        rootNode = null;
+        waitRoot = getWaitRoot();
+        waitRoot.setName(getMessage("LBL_ResourceBundlesList")); // NOI18N
+        waitRoot.setDisplayName(getMessage("LBL_ResourceBundlesList")); // 
NOI18N
+        manager.setRootContext(waitRoot);
+
+        branding = getBranding();
+        prj = branding.getProject();
+        
+        attachListeners();
+}
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated 
Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        view = new MyTree();
+        searchLabel = new javax.swing.JLabel();
+        searchField = new javax.swing.JTextField();
+        localeLabel = new javax.swing.JLabel();
+        localeComboBox = new javax.swing.JComboBox();
+
+        addComponentListener(new java.awt.event.ComponentAdapter() {
+            public void componentShown(java.awt.event.ComponentEvent evt) {
+                formComponentShown(evt);
+            }
+        });
+
+        
searchLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+        searchLabel.setLabelFor(searchField);
+        org.openide.awt.Mnemonics.setLocalizedText(searchLabel, 
org.openide.util.NbBundle.getMessage(InternationalizationResourceBundleBrandingPanel.class,
 "InternationalizationResourceBundleBrandingPanel.searchLabel.text")); // 
NOI18N
+
+        
searchField.setText(org.openide.util.NbBundle.getMessage(InternationalizationResourceBundleBrandingPanel.class,
 "InternationalizationResourceBundleBrandingPanel.searchField.text")); // 
NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(localeLabel, 
org.openide.util.NbBundle.getMessage(InternationalizationResourceBundleBrandingPanel.class,
 "InternationalizationResourceBundleBrandingPanel.localeLabel.text")); // 
NOI18N
+
+        java.util.Locale [] locales = java.util.Locale.getAvailableLocales();
+        Comparator<Locale> localeComparator = new Comparator<Locale>() {
+
+            @Override
+            public int compare(Locale o1, Locale o2) {
+                return o1.toString().compareTo(o2.toString());
+            }
+        };
+        java.util.Arrays.sort(locales, localeComparator);
+        localeComboBox.setModel(new 
javax.swing.DefaultComboBoxModel(locales));
+        localeComboBox.setSelectedItem(java.util.Locale.getDefault());
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, 
layout.createSequentialGroup()
+                .addContainerGap()
+                
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addComponent(view, 
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE)
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addComponent(localeLabel)
+                        
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(localeComboBox, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(6, 6, 6)
+                        .addComponent(searchLabel, 
javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE)
+                        
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(searchField, 
javax.swing.GroupLayout.PREFERRED_SIZE, 209, 
javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(searchField, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(searchLabel)
+                    .addComponent(localeComboBox, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(localeLabel))
+                .addGap(12, 12, 12)
+                .addComponent(view, javax.swing.GroupLayout.DEFAULT_SIZE, 
258, Short.MAX_VALUE)
+                .addContainerGap())
+        );
+
+        
searchLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(InternationalizationResourceBundleBrandingPanel.class,
 
"InternationalizationResourceBundleBrandingPanel.searchLabel.AccessibleContext.accessibleDescription"));
 // NOI18N
+    }// </editor-fold>//GEN-END:initComponents
+
+    private boolean initialized = false;
+
+    private void formComponentShown(java.awt.event.ComponentEvent evt) 
{//GEN-FIRST:event_formComponentShown
+        if (!initialized) {
+            refresh();
+            initialized = true;
+        }
+        view.requestFocusInWindow();
+    }
+
+    private void refresh() {
+        if (refreshTask == null) {
+            refreshTask = RPforRefresh.create(new Runnable() {
+                @Override
+                public void run() {
+                    prepareTree();
+                }
+            });
+        }
+        refreshTask.schedule(0);
+    }
+
+    private void prepareTree() {
+        List<BundleNode> resourcebundlenodes = new LinkedList<BundleNode>();
+
+        Set<File> jars = new HashSet<File>();
+        PlatformJarProvider pjp = 
prj.getLookup().lookup(PlatformJarProvider.class);
+        if (pjp != null) {
+            try {
+                jars.addAll(pjp.getPlatformJars());
+            } catch (IOException x) {
+                LOG.log(Level.INFO, null, x);
+            }
+        }
+        Set<File> brandableJars = branding.getBrandableJars();
+        jars.retainAll(brandableJars);
+        
+        for (File file : jars) {
+            try {
+                URI juri = Utilities.toURI(file);
+                JarFile jf = new JarFile(file);
+                String codeNameBase = 
ManifestManager.getInstance(jf.getManifest(), false).getCodeNameBase();
+                Enumeration<JarEntry> entries = jf.entries();
+                while (entries.hasMoreElements()) {
+                    JarEntry entry = entries.nextElement();
+                    if (entry.getName().endsWith("Bundle.properties")) { // 
NOI18N
+                        try {
+                            URL url = new URL("jar:" + juri + "!/" + 
entry.getName()); // NOI18N
+                            FileObject fo = URLMapper.findFileObject(url);
+                            if (fo == null) {
+                                LOG.log(Level.WARNING, "#207183: no bundle 
file found: {0}", url);
+                                continue;
+                            }
+                            DataObject dobj = DataObject.find(fo);
+                            Node dobjnode = dobj.getNodeDelegate();
+                            BundleNode filternode = new BundleNode(dobjnode, 
fo.getPath(), codeNameBase);
+                            resourcebundlenodes.add(filternode);
+                        } catch (Exception e) {
+                            Exceptions.printStackTrace(e);
+                        }
+                    }
+                }
+            } catch (ZipException ex) {
+                // accessing JAR file failed, log and ignore
+                LOG.log(Level.INFO, "Access failed for " + file.getPath()); 
// NOI18N
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+
+        rootNode = new RootNode(resourcebundlenodes);
+        rootNode.setName(getMessage("LBL_ResourceBundlesList")); // NOI18N
+        rootNode.setDisplayName(getMessage("LBL_ResourceBundlesList")); // 
NOI18N
+        rootNode.setShortDescription(getMessage("LBL_ResourceBundlesDesc")); 
// NOI18N
+        manager.setRootContext(rootNode);
+    }//GEN-LAST:event_formComponentShown
+
+    private void searchStringUpdated() {
+        if (null != rootNode) {
+            try {
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    @Override
+                    public void run() {
+                        searchString = retrieveSearchField();
+                        // replace root node with waitRoot
+                        manager.setRootContext(waitRoot);
+                    }
+                });
+
+                // refresh lists of children based on the filter
+                rootNode.refreshChildren();
+
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    @Override
+                    public void run() {
+                        // quit immediately if search field value changed
+                        if (!searchFieldEquals(searchString))
+                            return;
+                        // replace waitRoot with the real root
+                        manager.setRootContext(rootNode);
+                        // expand/collapse all bundle nodes
+                        if (null == searchString) {
+                            Node[] nodes = rootNode.getChildren().getNodes();
+                            for (Node node : nodes) {
+                                view.collapseNode(node);
+                            }
+                        } else {
+                            view.expandAll();
+                        }
+                    }
+                });
+            } catch (InterruptedException ex) {
+                Exceptions.printStackTrace(ex);
+            } catch (InvocationTargetException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+    }
+
+    private String retrieveSearchField () {
+        String value = searchField.getText().trim().toLowerCase();
+        if (value.equalsIgnoreCase("")) {
+            value = null;
+        }
+        return value;
+    }
+
+    private boolean searchFieldEquals (String value1) {
+        String value2 = retrieveSearchField();
+        if (null==value1 && null==value2)
+            return true;
+        if (null!=value1 && null!=value2 && value1.equals(value2))
+            return true;
+        return false;
+    }
+    
+    private class RootNode extends AbstractNode implements OpenCookie {
+
+        private RootChildren rootChildren;
+
+        public RootNode(List<BundleNode> resourceBundleNodes) {
+            this(resourceBundleNodes, new InstanceContent());
+        }
+
+        private RootNode(List<BundleNode> resourceBundleNodes, 
InstanceContent content) {
+            super (new RootChildren(resourceBundleNodes), new 
AbstractLookup(content));
+            content.add(this);
+            this.rootChildren = (RootChildren) getChildren();
+        }
+
+        @Override
+        public Action[] getActions(boolean context) {
+            return new Action[] { 
expandAllAction.createContextAwareInstance(getLookup()) };
+        }
+
+        @Override
+        public void open() {
+            view.expandAll();
+            view.requestFocusInWindow();
+        }
+
+        public void refreshChildren() {
+            rootChildren.refreshChildren();
+        }
+    }
+
+    static final class ExpandAllAction extends OpenAction {
+
+        @Override
+        public String getName() {
+            return getMessage("LBL_ResourceBundlesExpand"); // NOI18N
+        }
+    }
+
+    private class RootChildren extends Children.Keys<Node> {
+
+        List<BundleNode> resourceBundleNodes;
+
+        public RootChildren(List<BundleNode> resourceBundleNodes) {
+            super();
+            this.resourceBundleNodes = resourceBundleNodes;
+        }
+
+        @Override
+        protected Node[] createNodes(Node key) {
+            // filter out BundleNodes without visible KeyNodes
+            if (key.getChildren().getNodesCount()>0)
+                return new Node[] { key };
+            return null;
+        }
+
+        @Override
+        protected void addNotify() {
+            refreshList();
+        }
+
+        @Override
+        protected void removeNotify() {
+            setKeys(Collections.EMPTY_SET);
+        }
+
+        private void refreshList() {
+            List<BundleNode> keys = new ArrayList();
+            for (BundleNode node : resourceBundleNodes) {
+                keys.add(node);
+            }
+            Collections.sort(keys);
+            setKeys(keys);
+        }
+
+        private void refreshChildren() {
+            for (BundleNode node : resourceBundleNodes) {
+                node.refreshChildren();
+                refreshKey(node);
+            }
+        }
+    }
+
+    private class BundleNode extends FilterNode implements OpenCookie, 
Comparable<BundleNode> {
+
+        private String bundlepath;
+        private String codenamebase;
+        private BundleChildren bundleChildren;
+
+        public BundleNode(Node orig, String bundlepath, String codenamebase) 
{
+            this (orig, bundlepath, codenamebase, new InstanceContent());
+        }
+
+        public BundleNode(Node orig, String bundlepath, String codenamebase, 
InstanceContent content) {
+            super(orig, new BundleChildren (orig, bundlepath, codenamebase), 
new AbstractLookup(content));
+            content.add(this);
+            
+            disableDelegation(DELEGATE_GET_DISPLAY_NAME | 
DELEGATE_SET_DISPLAY_NAME
+                    | DELEGATE_GET_SHORT_DESCRIPTION | 
DELEGATE_SET_SHORT_DESCRIPTION
+                    | DELEGATE_GET_ACTIONS);
+
+            setDisplayName(bundlepath);
+            setShortDescription(codenamebase);
+
+            this.bundlepath = bundlepath;
+            this.codenamebase = codenamebase;
+            this.bundleChildren = (BundleChildren) getChildren();
+        }
+
+        @Override
+        public String getHtmlDisplayName() {
+            if (isBundleBranded(bundlepath, codenamebase))
+                return "<b>" + bundlepath + "</b>"; // NOI18N
+            else
+                return bundlepath;
+        }
+
+        public void refresh() {
+            fireDisplayNameChange(null, null);
+        }
+
+        @Override
+        public Action[] getActions(boolean context) {
+            return new Action[] { 
openRBAction.createContextAwareInstance(getLookup()) };
+        }
+
+        @Override
+        public Action getPreferredAction() {
+            return null;
+        }
+
+        @Override
+        public boolean canRename() {
+            return false;
+        }
+
+        @Override
+        public void open() {
+            EditCookie originalEC = 
getOriginal().getCookie(EditCookie.class);
+            if (null != originalEC)
+                originalEC.edit();
+        }
+
+        @Override
+        public int compareTo(BundleNode o) {
+            return getDisplayName().compareTo(o.getDisplayName());
+        }
+
+        private void refreshChildren() {
+            bundleChildren.refreshChildren();
+        }
+    }
+
+    private class BundleChildren extends Children.Keys<Node> {
+
+        Node original;
+        private String bundlepath;
+        private String codenamebase;
+
+        public BundleChildren(Node orig, String bundlepath, String 
codenamebase) {
+            super();
+            original = orig;
+            this.bundlepath = bundlepath;
+            this.codenamebase = codenamebase;
+        }
+
+        @Override
+        protected Node[] createNodes(Node key) {
+            // filter out all keys related to module metadata
+            if 
(!key.getDisplayName().toUpperCase().startsWith("OPENIDE-MODULE")) { // NOI18N
+                KeyNode keyNode = new KeyNode(key, bundlepath, codenamebase);
+                // filter out according to searchString
+                if (null == searchString || 
keyNode.getDisplayName().toLowerCase().indexOf(searchString) != -1) {
+                    return new Node[]{keyNode};
+                }
+            }
+            return null;
+        }
+
+        @Override
+        protected void addNotify() {
+            refreshList();
+        }
+
+        @Override
+        protected void removeNotify() {
+            setKeys(Collections.EMPTY_SET);
+        }
+
+        private void refreshList() {
+            List keys = new ArrayList();
+            Node[] origChildren = original.getChildren().getNodes();
+            for (Node node : origChildren) {
+                keys.add(node);
+            }
+            setKeys(keys);
+        }
+
+        private void refreshChildren() {
+            Node[] origChildren = original.getChildren().getNodes();
+            for (Node node : origChildren) {
+                refreshKey(node);
+            }
+        }
+    }
+
+    private class KeyNode extends FilterNode implements EditCookie, 
OpenCookie {
+
+        private String key;
+        private String bundlepath;
+        private String codenamebase;
+        private String cachedDisplayName;
+        private String cachedHtmlDisplayName;
+
+        public KeyNode(Node orig, String bundlepath, String codenamebase) {
+            this (orig, bundlepath, codenamebase, new InstanceContent());
+        }
+
+        public KeyNode(Node orig, String bundlepath, String codenamebase, 
InstanceContent content) {
+            super(orig, null, new AbstractLookup(content));
+            content.add(this);
+
+            disableDelegation(DELEGATE_GET_DISPLAY_NAME | 
DELEGATE_SET_DISPLAY_NAME
+                    | DELEGATE_GET_SHORT_DESCRIPTION | 
DELEGATE_SET_SHORT_DESCRIPTION
+                    | DELEGATE_GET_ACTIONS);
+
+            this.key = orig.getDisplayName();
+            this.bundlepath = bundlepath;
+            this.codenamebase = codenamebase;
+
+            cachedDisplayName = null;
+            cachedHtmlDisplayName = null;
+        }
+
+        @Override
+        public String getDisplayName() {
+            if (null == cachedDisplayName) {
+                cachedDisplayName = key + " = " + getKeyValue(bundlepath, 
codenamebase, key); // NOI18N
+            }
+            return cachedDisplayName;
+        }
+
+        @Override
+        public String getHtmlDisplayName() {
+            if (null == cachedHtmlDisplayName) {
+                if (isKeyBranded(bundlepath, codenamebase, key)) {
+                    cachedHtmlDisplayName = "<b>" + key + "</b>" + // NOI18N
+                            " = <font color=\"#ce7b00\">" + // NOI18N
+                            escapeTagDefinitions(getKeyValue(bundlepath, 
codenamebase, key)) + // NOI18N
+                            "</font>"; // NOI18N
+                } else {
+                    cachedHtmlDisplayName = key + " = <font 
color=\"#ce7b00\">" + // NOI18N
+                            escapeTagDefinitions(getKeyValue(bundlepath, 
codenamebase, key)) + // NOI18N
+                            "</font>"; // NOI18N
+                }
+            }
+            return cachedHtmlDisplayName;
+        }
+
+        private String escapeTagDefinitions (String text) {
+            return text.replaceAll("<", "&lt;").replaceAll(">", "&gt;"); // 
NOI18N
+        }
+
+        public void refresh() {
+            cachedDisplayName = null;
+            cachedHtmlDisplayName = null;
+            fireDisplayNameChange(null, null);
+        }
+
+        @Override
+        public Action[] getActions(boolean context) {
+            return new Action[] { 
editRBAction.createContextAwareInstance(getLookup()),
+                openRBAction.createContextAwareInstance(getLookup()) };
+        }
+
+        @Override
+        public Action getPreferredAction() {
+            return editRBAction.createContextAwareInstance(getLookup());
+        }
+
+        @Override
+        public boolean canRename() {
+            return false;
+        }
+
+        @Override
+        public void edit() {
+            if (addKeyToBranding(bundlepath, codenamebase, 
getOriginal().getDisplayName())) {
+                refresh();
+                Node parent = getParentNode();
+                if (parent instanceof BundleNode) {
+                    ((BundleNode) parent).refresh();
+                }
+            }
+        }
+
+        @Override
+        public void open() {
+            EditCookie originalEC = 
getOriginal().getCookie(EditCookie.class);
+            if (null != originalEC)
+                originalEC.edit();
+        }
+    }
+
+    static final class EditRBAction extends EditAction {
+
+        @Override
+        public String getName() {
+            return getMessage ("LBL_ResourceBundlesAddToBranding"); // NOI18N
+        }
+    }
+
+    static final class OpenRBAction extends OpenAction {
+
+        @Override
+        public String getName() {
+            return getMessage ("LBL_ResourceBundlesViewOriginal"); // NOI18N
+        }
+    }
+
+    private class SearchListener implements DocumentListener, FocusListener {
+
+        @Override
+        public void insertUpdate(DocumentEvent e) {
+            if (searchTask == null) {
+                searchTask = RPforSearch.create(new Runnable() {
+                    @Override
+                    public void run() {
+                        searchStringUpdated();
+                    }
+                });
+            }
+            searchTask.schedule(500);
+        }
+
+        @Override
+        public void removeUpdate(DocumentEvent e) {
+            insertUpdate(e);
+        }
+
+        @Override
+        public void changedUpdate(DocumentEvent e) {
+            insertUpdate(e);
+        }
+
+        @Override
+        public void focusGained(FocusEvent e) {
+            searchField.selectAll();
+        }
+
+        @Override
+        public void focusLost(FocusEvent e) {
+            searchField.select(0, 0);
+        }
+
+    }
+
+    private boolean addKeyToBranding (String bundlepath, String 
codenamebase, String key) {
+        BrandingSupport.BundleKey bundleKey = 
getBranding().getGeneralLocalizedBundleKeyForModification(codenamebase, 
bundlepath, key);
+        KeyInput inputLine = new KeyInput(key + ":", bundlepath); // NOI18N
+        String oldValue = bundleKey.getValue();
+        inputLine.setInputText(oldValue);
+        if 
(DialogDisplayer.getDefault().notify(inputLine)==NotifyDescriptor.OK_OPTION) {
+            String newValue = inputLine.getInputText();
+            if (newValue.compareTo(oldValue)!=0) {
+                bundleKey.setValue(newValue);
+                
getBranding().addModifiedInternationalizedBundleKey(bundleKey);
+                setModified();
+                updateProjectInternationalizationLocales();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private String getKeyValue (String bundlepath, String codenamebase, 
String key) {
+        return getBranding().getLocalizedKeyValue(bundlepath, codenamebase, 
key);
+    }
+
+    private boolean isKeyBranded (String bundlepath, String codenamebase, 
String key) {
+        return getBranding().isKeyLocallyBranded(bundlepath, codenamebase, 
key);
+    }
+
+    private boolean isBundleBranded (String bundlepath, String codenamebase) 
{
+        return getBranding().isBundleLocallyBranded(bundlepath, 
codenamebase);
+    }
+
+    @Override
+    public void store() {
+        // no-op, all modified bundle keys are stored through the model
+    }
+
+    @Override
+    public ExplorerManager getExplorerManager() {
+        return manager;
+    }
+
+    private static String getMessage(String key) {
+        return 
NbBundle.getMessage(InternationalizationResourceBundleBrandingPanel.class, 
key);
+    }
+
+    private AbstractNode getWaitRoot() {
+        return new AbstractNode(new Children.Array() {
+            @Override
+            protected Collection<Node> initCollection() {
+                return Collections.singleton((Node) new WaitNode());
+            }
+        });
+    }
+
+    private final class WaitNode extends AbstractNode {
+
+        public WaitNode() {
+            super(Children.LEAF);
+            setDisplayName(UIUtil.WAIT_VALUE);
+            setIconBaseWithExtension(WAIT_ICON_PATH);
+        }
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JComboBox localeComboBox;
+    private javax.swing.JLabel localeLabel;
+    private javax.swing.JTextField searchField;
+    private javax.swing.JLabel searchLabel;
+    private org.openide.explorer.view.BeanTreeView view;
+    // End of variables declaration//GEN-END:variables
+
+    public static class KeyInput extends NotifyDescriptor {
+
+        protected ResourceBundleKeyPanel keyPanel;
+
+        public KeyInput(final String text, final String title) {
+            this(text, title, OK_CANCEL_OPTION, PLAIN_MESSAGE);
+        }
+
+        public KeyInput(final String text, final String title, final int 
optionType, final int messageType) {
+            super(null, title, optionType, messageType, null, null);
+            super.setMessage(createDesign(text));
+        }
+
+        public String getInputText() {
+            return keyPanel.getText();
+        }
+
+        public void setInputText(final String text) {
+            keyPanel.setText(text);
+        }
+
+        protected Component createDesign(final String text) {
+            return keyPanel = new ResourceBundleKeyPanel(text);
+        }
+    }
+
+    private final JScrollPane scrollPane = new JScrollPane();
+
+    private class MyTree extends BeanTreeView {
+
+        public MyTree() {
+            setBorder(scrollPane.getBorder());
+            setViewportBorder(scrollPane.getViewportBorder());
+        }
+
+        @Override
+        public void updateUI() {
+            super.updateUI();
+            setBorder(scrollPane.getBorder());
+            setViewportBorder(scrollPane.getViewportBorder());
+        }
+    }
+    
+    private void attachListeners() {
+        localeComboBox.addItemListener(new ItemListener() {
+
+            @Override
+            public void itemStateChanged(final ItemEvent e) {
+                new Thread(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (e.getStateChange() == ItemEvent.SELECTED) {
+                            Object item = e.getItem();
+                            locale = (Locale) item;
+                            branding.refreshLocalizedBundles(locale = 
(Locale) item);
+                            SwingUtilities.invokeLater(new Runnable() {
+                                @Override
+                                public void run() {
+                                    prepareTree();
+                                }
+                            });
+                        
+                        }
+                    }
+                }).start();
+                
+            }
+        });
+    }
+    
+    private void updateProjectInternationalizationLocales() {
+        EditableProperties p = null;
+        File projectProperties = null;
+        try {
+            projectProperties = new 
File(FileUtil.toFile(prj.getProjectDirectory()), "nbproject" + 
File.separatorChar + "project.properties");
+            p = getEditableProperties(projectProperties);
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        if(p != null && projectProperties != null) {
+            if(p.getProperty("branding.locales") == null) {
+                p.setProperty("branding.locales", 
this.locale.toString().toLowerCase());
+            } else {
+                String localizationsStr = p.getProperty("branding.locales");
+                StringTokenizer tokenizer = new 
StringTokenizer(localizationsStr, ",");
+                boolean containsLocale = false;
+                while (tokenizer.hasMoreElements()) {
+                    
if(this.locale.toString().toLowerCase().equals(tokenizer.nextToken())) {
+                        containsLocale = true;
+                        break;
+                    }
+                }
+                if(!containsLocale) {
+                    p.setProperty("branding.locales", 
p.getProperty("branding.locales") + "," + 
this.locale.toString().toLowerCase());
+                }
+            }
+            try {
+                storeEditableProperties(p, projectProperties);
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+    }
+    
+    private static EditableProperties getEditableProperties(final File 
bundle) throws IOException {
+        EditableProperties p = new EditableProperties(true);
+        InputStream is = new FileInputStream(bundle);
+        try {
+            p.load(is);
+        } finally {
+            is.close();
+        }
+        return p;
+    }
+    
+    private static void storeEditableProperties(final EditableProperties p, 
final File bundle) throws IOException {
+        FileObject fo = FileUtil.toFileObject(bundle);
+        OutputStream os = null == fo ? new FileOutputStream(bundle) : 
fo.getOutputStream();
+        try {
+            p.store(os);
+        } finally {
+            os.close();
+        }
+    }
+    
+}
diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/Branding.java 
b/nbbuild/antsrc/org/netbeans/nbbuild/Branding.java
--- a/nbbuild/antsrc/org/netbeans/nbbuild/Branding.java
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/Branding.java
@@ -46,6 +46,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.StringTokenizer;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
@@ -63,6 +64,7 @@
     private File cluster;
     private File overrides;
     private String token;
+    private String locales;
     
     public Branding() {}
     
@@ -78,6 +80,10 @@
         this.token = token;
     }
     
+    public void setLocales(String locales) {
+        this.locales = locales;
+    }
+    
     public void execute() throws BuildException {
         if (cluster == null || !cluster.isDirectory()) {
             throw new BuildException("Must specify a valid cluster 
directory", getLocation());
@@ -89,7 +95,11 @@
             throw new BuildException("Must specify a valid branding token: " 
+ token, getLocation());
         }
         try {
-            lookForBrandingJars(overrides, cluster, 
overrides.getAbsolutePath() + File.separatorChar);
+            StringTokenizer tokenizer = new StringTokenizer(locales, ",");
+            while (tokenizer.hasMoreElements()) {
+                lookForBrandingJars(overrides, cluster, 
overrides.getAbsolutePath() + File.separatorChar, tokenizer.nextToken());
+            }
+            lookForBrandingJars(overrides, cluster, 
overrides.getAbsolutePath() + File.separatorChar, null);
         } catch (IOException e) {
             throw new BuildException(e, getLocation());
         }
@@ -110,9 +120,9 @@
         return false;
     }
     
-    private boolean lookForBrandingJars(File srcDir, File destDir, String 
srcPrefix) throws IOException {
+    private boolean lookForBrandingJars(File srcDir, File destDir, String 
srcPrefix, String locale) throws IOException {
         if (srcDir.getName().endsWith(".jar")) {
-            packBrandingJar(srcDir, destDir);
+            packBrandingJar(srcDir, destDir, locale);
             return true;
         } else {
             String[] kids = srcDir.list();
@@ -129,7 +139,7 @@
                     log("Warning: stray file " + kid + " encountered; 
ignoring", Project.MSG_WARN);
                     continue;
                 }
-                used |= lookForBrandingJars(kid, new File(destDir, kids[i]), 
srcPrefix);
+                used |= lookForBrandingJars(kid, new File(destDir, kids[i]), 
srcPrefix, locale);
             }
             if (!used) {
                 log("Warning: stray directory " + srcDir + " with no 
brandables encountered; ignoring", Project.MSG_WARN);
@@ -138,12 +148,22 @@
         }
     }
     
-    private void packBrandingJar(File srcDir, File destJarBase) throws 
IOException {
+    private void packBrandingJar(File srcDir, File destJarBase, String 
locale) throws IOException {
         DirectoryScanner scanner = new DirectoryScanner();
         scanner.setBasedir(srcDir);
+        String localeToken = "";
+        if(locale != null) {
+            String [] includes = {"**/*_" + locale.toString().toLowerCase() 
+ ".*"};
+            scanner.setIncludes(includes);
+            localeToken = "_" + locale.toString().toLowerCase();
+        } else {
+            String [] excludes = {"**/*_??_??.*", "**/*_??.*"};
+            scanner.setExcludes(excludes);
+        }
         scanner.addDefaultExcludes(); // #68929
         scanner.scan();
         String[] files = scanner.getIncludedFiles();
+        if(files.length > 0) {
         Zip zip = (Zip) getProject().createTask("zip");
         String name = destJarBase.getName();
         String nameBase = name.substring(0, name.length() - ".jar".length());
@@ -151,7 +171,7 @@
         if (!destFolder.isDirectory() && !destFolder.mkdirs()) {
             throw new IOException("Could not create directory " + 
destFolder);
         }
-        File destJar = new File(destFolder, nameBase + "_" + token + ".jar");
+            File destJar = new File(destFolder, nameBase + "_" + token + 
localeToken + ".jar");
         zip.setDestFile(destJar);
         zip.setCompress(true);
         for (int i = 0; i < files.length; i++) {
@@ -160,12 +180,12 @@
             String basePath = files[i].replace(File.separatorChar, '/');
             int slash = basePath.lastIndexOf('/');
             int dot = basePath.lastIndexOf('.');
-            String infix = "_" + token;
+                String infix = "_" + token + localeToken;
             String brandedPath;
             if (dot == -1 || dot < slash) {
                 brandedPath = basePath + infix;
             } else {
-                brandedPath = basePath.substring(0, dot) + infix + 
basePath.substring(dot);
+                    brandedPath = basePath.substring(0, dot - 
localeToken.length()) + infix + basePath.substring(dot);
             }
             entry.setFullpath(brandedPath);
             zip.addZipfileset(entry);
@@ -174,5 +194,5 @@
         zip.init();
         zip.execute();
     }
-    
 }
+}

[hg] main-silver: #184845: The branding suite edit bundles opti...

Martin Kozeny 05/03/2013

Project Features

About this Project

APIsupport was started in November 2009, is owned by Antonin Nebuzelsky, and has 43 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20131025.e7cbc9d). © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close