diff --git a/java.j2seplatform/nbproject/project.xml b/java.j2seplatform/nbproject/project.xml --- a/java.j2seplatform/nbproject/project.xml +++ b/java.j2seplatform/nbproject/project.xml @@ -124,7 +124,7 @@ 1 - 1.15 + 1.31 diff --git a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibraryTypeProvider.java b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibraryTypeProvider.java --- a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibraryTypeProvider.java +++ b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibraryTypeProvider.java @@ -71,6 +71,7 @@ import java.net.URI; import java.util.HashSet; import java.util.logging.Logger; +import org.netbeans.spi.project.libraries.NamedLibraryImplementation; import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; @@ -101,27 +102,33 @@ VOLUME_TYPE_JAVADOC, })); + @Override public String getLibraryType() { return LIBRARY_TYPE; } + @Override public String getDisplayName () { return NbBundle.getMessage (J2SELibraryTypeProvider.class,"TXT_J2SELibraryType"); } + @Override public String[] getSupportedVolumeTypes () { return VOLUME_TYPES; } + @Override public LibraryImplementation createLibrary() { return new J2SELibraryImpl (); } + @Override public void libraryCreated(final LibraryImplementation libraryImpl) { assert libraryImpl != null; ProjectManager.mutex().postWriteRequest( new Runnable () { + @Override public void run () { try { EditableProperties props = PropertyUtils.getGlobalProperties(); @@ -137,9 +144,11 @@ ); } + @Override public void libraryDeleted(final LibraryImplementation libraryImpl) { assert libraryImpl != null; ProjectManager.mutex().postWriteRequest(new Runnable () { + @Override public void run() { try { EditableProperties props = PropertyUtils.getGlobalProperties(); @@ -155,6 +164,7 @@ }); } + @Override public Customizer getCustomizer(String volumeType) { if (VOLUME_TYPES[0].equals(volumeType)|| VOLUME_TYPES[1].equals(volumeType)|| @@ -167,6 +177,7 @@ } + @Override public Lookup getLookup() { return Lookup.EMPTY; } @@ -228,7 +239,7 @@ } //Like DefaultLibraryTypeProvider but in addition checks '/' on the end of folder URLs. - private static class J2SELibraryImpl implements LibraryImplementation { + private static class J2SELibraryImpl implements NamedLibraryImplementation { private String description; private Map> contents; @@ -236,6 +247,8 @@ // library 'binding name' as given by user private String name; + private String displayName; + private String localizingBundle; private List listeners; @@ -251,20 +264,34 @@ } + @Override public String getType() { return LIBRARY_TYPE; } + @Override public void setName(final String name) throws UnsupportedOperationException { String oldName = this.name; this.name = name; this.firePropertyChange (PROP_NAME, oldName, this.name); } + @Override public String getName() { return name; } + @Override + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + @Override + public String getDisplayName() { + return this.displayName; + } + + @Override public List getContent(String contentType) throws IllegalArgumentException { List content = contents.get(contentType); if (content == null) @@ -272,6 +299,7 @@ return Collections.unmodifiableList (content); } + @Override public void setContent(final String contentType, List path) throws IllegalArgumentException { if (path == null) { throw new IllegalArgumentException (); @@ -311,37 +339,44 @@ return checkedResources; } + @Override public String getDescription () { return this.description; } + @Override public void setDescription (String text) { String oldDesc = this.description; this.description = text; this.firePropertyChange (PROP_DESCRIPTION, oldDesc, this.description); } + @Override public String getLocalizingBundle() { return this.localizingBundle; } + @Override public void setLocalizingBundle(String resourceName) { this.localizingBundle = resourceName; } + @Override public synchronized void addPropertyChangeListener (PropertyChangeListener l) { if (this.listeners == null) this.listeners = new ArrayList(); this.listeners.add (l); } + @Override public synchronized void removePropertyChangeListener (PropertyChangeListener l) { if (this.listeners == null) return; this.listeners.remove (l); } - public @Override String toString() { + @Override + public String toString() { return this.getClass().getName()+"[" + name + "]"; // NOI18N } diff --git a/java.project/nbproject/project.xml b/java.project/nbproject/project.xml --- a/java.project/nbproject/project.xml +++ b/java.project/nbproject/project.xml @@ -125,6 +125,7 @@ 1 + 1.31 diff --git a/java.project/src/org/netbeans/spi/java/project/support/ui/SharableLibrariesUtils.java b/java.project/src/org/netbeans/spi/java/project/support/ui/SharableLibrariesUtils.java --- a/java.project/src/org/netbeans/spi/java/project/support/ui/SharableLibrariesUtils.java +++ b/java.project/src/org/netbeans/spi/java/project/support/ui/SharableLibrariesUtils.java @@ -512,7 +512,18 @@ NbBundle.getMessage(SharableLibrariesUtils.class, "ERR_LibraryExists", library.getDisplayName()), NotifyDescriptor.WARNING_MESSAGE)); } else { - man.createURILibrary(library.getType(), library.getName(), volumes); + final String name = library.getName(); + String displayName = library.getDisplayName(); + if (name.equals(displayName)) { + //No need to set displayName when it's same as name + displayName = null; + } + man.createURILibrary( + library.getType(), + name, + displayName, + library.getDescription(), + volumes); } } catch (IOException ex) { Exceptions.printStackTrace(ex); diff --git a/project.ant/nbproject/project.xml b/project.ant/nbproject/project.xml --- a/project.ant/nbproject/project.xml +++ b/project.ant/nbproject/project.xml @@ -72,7 +72,7 @@ 1 - 1.15 + 1.31 diff --git a/project.ant/src/org/netbeans/modules/project/ant/ProjectLibraryProvider.java b/project.ant/src/org/netbeans/modules/project/ant/ProjectLibraryProvider.java --- a/project.ant/src/org/netbeans/modules/project/ant/ProjectLibraryProvider.java +++ b/project.ant/src/org/netbeans/modules/project/ant/ProjectLibraryProvider.java @@ -76,6 +76,7 @@ import javax.swing.JFileChooser; import javax.swing.event.ChangeListener; import javax.swing.filechooser.FileFilter; +import org.netbeans.api.annotations.common.NullAllowed; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectManager; import org.netbeans.api.project.libraries.Library; @@ -91,6 +92,7 @@ import org.netbeans.spi.project.libraries.LibraryImplementation2; import org.netbeans.spi.project.libraries.LibraryProvider; import org.netbeans.spi.project.libraries.LibraryStorageArea; +import org.netbeans.spi.project.libraries.NamedLibraryImplementation; import org.netbeans.spi.project.libraries.support.LibrariesSupport; import org.netbeans.spi.project.support.ant.AntProjectEvent; import org.netbeans.spi.project.support.ant.AntProjectHelper; @@ -130,6 +132,7 @@ private static final String NAMESPACE = "http://www.netbeans.org/ns/ant-project-libraries/1"; // NOI18N private static final String EL_LIBRARIES = "libraries"; // NOI18N private static final String EL_DEFINITIONS = "definitions"; // NOI18N + private static final String SFX_DISPLAY_NAME = "displayName"; //NOI18N private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); private AntProjectListener apl; @@ -496,6 +499,7 @@ String name = entry.getKey(); String type = "j2se"; // NOI18N String description = null; + String displayName = null; Map> contents = new HashMap>(); for (Map.Entry subentry : entry.getValue().entrySet()) { String k = subentry.getKey(); @@ -505,6 +509,8 @@ // XXX currently overriding display name is not supported } else if (k.equals("description")) { // NOI18N description = subentry.getValue(); + } else if (k.equals(SFX_DISPLAY_NAME)) { //NOI18N + displayName = subentry.getValue(); } else { final String[] path = sanitizeHttp(subentry.getKey(), PropertyUtils.tokenizePath(subentry.getValue())); List volume = new ArrayList(path.length); @@ -535,7 +541,16 @@ contents.put(k, volume); } } - libs.put(name, new ProjectLibraryImplementation(def.mainPropertiesFile, def.privatePropertiesFile, type, name, description, contents)); + libs.put( + name, + new ProjectLibraryImplementation( + def.mainPropertiesFile, + def.privatePropertiesFile, + type, + name, + description, + displayName, + contents)); } return libs; } @@ -642,12 +657,13 @@ return result.toArray(new String[result.size()]); } - static final class ProjectLibraryImplementation implements LibraryImplementation2 { + static final class ProjectLibraryImplementation implements LibraryImplementation2, NamedLibraryImplementation { final File mainPropertiesFile, privatePropertiesFile; final String type; String name; String description; + String displayName; Map> contents; final PropertyChangeSupport pcs = new PropertyChangeSupport(this); @@ -675,12 +691,20 @@ return null; } - ProjectLibraryImplementation(File mainPropertiesFile, File privatePropertiesFile, String type, String name, String description, Map> contents) { + ProjectLibraryImplementation( + File mainPropertiesFile, + File privatePropertiesFile, + String type, + String name, + final @NullAllowed String description, + final @NullAllowed String displayName, + Map> contents) { this.mainPropertiesFile = mainPropertiesFile; this.privatePropertiesFile = privatePropertiesFile; this.type = type; this.name = name; this.description = description; + this.displayName = displayName; this.contents = contents; } @@ -704,6 +728,11 @@ return null; } + @Override + public String getDisplayName() { + return displayName; + } + public List getContent(String volumeType) throws IllegalArgumentException { List uris = getURIContent(volumeType); List resolvedUrls = new ArrayList(uris.size()); @@ -807,6 +836,26 @@ throw new UnsupportedOperationException(); } + @Override + public void setDisplayName(final @NullAllowed String displayName) { + if (Utilities.compareObjects(this.displayName, displayName)) { + return; + } + final String oldDisplayName = this.displayName; + this.displayName = displayName; + try { + final String key = String.format("libs.%s.%s",name, SFX_DISPLAY_NAME); //NOI18N + replaceProperty( + mainPropertiesFile, + false, + key, + displayName == null ? new String[0] : new String[]{displayName}); + } catch (IOException x) { + throw new IllegalArgumentException(x); + } + pcs.firePropertyChange(LibraryImplementation.PROP_CONTENT, oldDisplayName, displayName); + } + public void addPropertyChangeListener(PropertyChangeListener l) { pcs.addPropertyChangeListener(l); } @@ -1169,7 +1218,12 @@ index++; } } - return man.createURILibrary(lib.getType(), name, content); + String displayName = lib.getDisplayName(); + if (name.equals(displayName)) { + //No need to set displayName when it's same as name + displayName = null; + } + return man.createURILibrary(lib.getType(), name, displayName, lib.getDescription(), content); } }); } catch (MutexException ex) { diff --git a/project.libraries/apichanges.xml b/project.libraries/apichanges.xml --- a/project.libraries/apichanges.xml +++ b/project.libraries/apichanges.xml @@ -107,6 +107,22 @@ + + + Allow user created library to provide display name + + + + + + Added displayName property into the Library's SPI + allowing an implementor to provide the a display name of the Library + which differs from the system (identifying) name. + + + + + URI used for relative library entries instead of URL diff --git a/project.libraries/manifest.mf b/project.libraries/manifest.mf --- a/project.libraries/manifest.mf +++ b/project.libraries/manifest.mf @@ -2,7 +2,7 @@ OpenIDE-Module: org.netbeans.modules.project.libraries/1 OpenIDE-Module-Install: org/netbeans/modules/project/libraries/LibrariesModule.class OpenIDE-Module-Layer: org/netbeans/modules/project/libraries/resources/mf-layer.xml -OpenIDE-Module-Specification-Version: 1.30 +OpenIDE-Module-Specification-Version: 1.31 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/project/libraries/resources/Bundle.properties AutoUpdate-Show-In-Client: false diff --git a/project.libraries/src/org/netbeans/api/project/libraries/LibrariesCustomizer.java b/project.libraries/src/org/netbeans/api/project/libraries/LibrariesCustomizer.java --- a/project.libraries/src/org/netbeans/api/project/libraries/LibrariesCustomizer.java +++ b/project.libraries/src/org/netbeans/api/project/libraries/LibrariesCustomizer.java @@ -50,6 +50,7 @@ import java.awt.Dialog; import javax.swing.border.EmptyBorder; import org.netbeans.modules.project.libraries.LibraryTypeRegistry; +import org.netbeans.modules.project.libraries.Util; import org.netbeans.modules.project.libraries.ui.LibrariesModel; import org.netbeans.modules.project.libraries.ui.NewLibraryPanel; import org.netbeans.spi.project.libraries.LibraryImplementation; @@ -125,9 +126,15 @@ setAccessibleDescription(dlg, customizer.getAccessibleContext().getAccessibleDescription()); dlg.setVisible(true); if (dd.getValue() == DialogDescriptor.OK_OPTION) { + final String currentLibraryName = p.getLibraryName(); + final String antLibraryName = + org.netbeans.modules.project.libraries.ui.LibrariesCustomizer.createFreeAntLibraryName( + currentLibraryName, + customizer.getModel(), + area); LibraryImplementation impl; if (area != LibrariesModel.GLOBAL_AREA) { - impl = customizer.getModel().createArealLibrary(p.getLibraryType(), p.getLibraryName(), manager.getArea()); + impl = customizer.getModel().createArealLibrary(p.getLibraryType(), antLibraryName, manager.getArea()); } else { LibraryTypeProvider provider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider(p.getLibraryType()); if (provider == null) { @@ -136,6 +143,7 @@ impl = provider.createLibrary(); impl.setName(p.getLibraryName()); } + Util.setDisplayName(impl, currentLibraryName); customizer.getModel().addLibrary(impl); customizer.forceTreeRecreation(); if (customizeLibrary(customizer, impl)) { diff --git a/project.libraries/src/org/netbeans/api/project/libraries/Library.java b/project.libraries/src/org/netbeans/api/project/libraries/Library.java --- a/project.libraries/src/org/netbeans/api/project/libraries/Library.java +++ b/project.libraries/src/org/netbeans/api/project/libraries/Library.java @@ -54,6 +54,7 @@ import java.util.ResourceBundle; import java.util.logging.Logger; import org.netbeans.modules.project.libraries.LibraryAccessor; +import org.netbeans.modules.project.libraries.Util; import org.netbeans.modules.project.libraries.ui.LibrariesModel; import org.netbeans.spi.project.libraries.LibraryImplementation; import org.netbeans.spi.project.libraries.LibraryImplementation2; @@ -176,7 +177,7 @@ * @return String the display name, never returns null. */ public String getDisplayName () { - return org.netbeans.modules.project.libraries.ui.LibrariesCustomizer.getLocalizedName(this.impl); + return Util.getLocalizedName(this.impl); } diff --git a/project.libraries/src/org/netbeans/api/project/libraries/LibraryManager.java b/project.libraries/src/org/netbeans/api/project/libraries/LibraryManager.java --- a/project.libraries/src/org/netbeans/api/project/libraries/LibraryManager.java +++ b/project.libraries/src/org/netbeans/api/project/libraries/LibraryManager.java @@ -58,7 +58,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; import org.netbeans.modules.project.libraries.LibraryAccessor; +import org.netbeans.modules.project.libraries.Util; import org.netbeans.modules.project.libraries.WritableLibraryProvider; import org.netbeans.modules.project.libraries.ui.LibrariesModel; import org.netbeans.spi.project.libraries.ArealLibraryProvider; @@ -286,6 +289,29 @@ * @since org.netbeans.modules.project.libraries/1 1.15 */ public Library createLibrary(String type, String name, Map> contents) throws IOException { + return createLibrary(type, name, null, null, contents); + } + + /** + * Creates a new library definition and adds it to the list. + * @param type the type of library, as in {@link LibraryTypeProvider#getLibraryType} or {@link LibraryImplementation#getType} + * @param name the identifying name of the new library (must not duplicate a name already in use by a library in this manager) + * @param displayName the display name of the library. If null the identifying name is used + * @param description the library description + * @param contents the initial contents of the library's volumes, as a map from volume type to volume content + * @return a newly created library + * @throws IOException if the new definition could not be stored + * @throws IllegalArgumentException if the library type or one of the content volume types is not supported, + * or if a library of the same name already exists in this manager + * @see ArealLibraryProvider#createLibrary + * @since org.netbeans.modules.project.libraries/1 1.31 + */ + public Library createLibrary( + @NonNull final String type, + @NonNull final String name, + @NullAllowed final String displayName, + @NullAllowed final String description, + @NonNull final Map> contents) throws IOException { if (getLibrary(name) != null) { throw new IllegalArgumentException("Name already in use: " + name); // NOI18N } @@ -297,6 +323,7 @@ } impl = ltp.createLibrary(); impl.setName(name); + Util.setDisplayName(impl, displayName); for (Map.Entry> entry : contents.entrySet()) { impl.setContent(entry.getKey(), entry.getValue()); } @@ -307,6 +334,7 @@ cont.put(entry.getKey(), LibrariesModel.convertURLsToURIs(entry.getValue())); } impl = LibraryAccessor.createLibrary(alp, type, name, area, cont); + Util.setDisplayName(impl, displayName); } return new Library(impl, this); } @@ -321,9 +349,32 @@ * @throws IllegalArgumentException if the library type or one of the content volume types is not supported, * or if a library of the same name already exists in this manager * @see ArealLibraryProvider#createLibrary + * @since org.netbeans.modules.project.libraries/1 1.31 + */ + public Library createURILibrary(String type, String name, Map> contents) throws IOException { + return createURILibrary(type, name, null, null, contents); + } + + /** + * Creates a new library definition and adds it to the list. + * @param type the type of library, as in {@link LibraryTypeProvider#getLibraryType} or {@link LibraryImplementation#getType} + * @param name the identifying name of the new library (must not duplicate a name already in use by a library in this manager) + * @param displayName the display name of the library. If null the identifying name is used + * @param description the library description + * @param contents the initial contents of the library's volumes, as a map from volume type to volume content + * @return a newly created library + * @throws IOException if the new definition could not be stored + * @throws IllegalArgumentException if the library type or one of the content volume types is not supported, + * or if a library of the same name already exists in this manager + * @see ArealLibraryProvider#createLibrary * @since org.netbeans.modules.project.libraries/1 1.18 */ - public Library createURILibrary(String type, String name, Map> contents) throws IOException { + public Library createURILibrary( + @NonNull final String type, + @NonNull final String name, + @NullAllowed final String displayName, + @NullAllowed final String description, + @NonNull final Map> contents) throws IOException { if (getLibrary(name) != null) { throw new IllegalArgumentException("Name already in use: " + name); // NOI18N } @@ -335,13 +386,15 @@ } impl = ltp.createLibrary(); impl.setName(name); + Util.setDisplayName(impl, displayName); for (Map.Entry> entry : contents.entrySet()) { impl.setContent(entry.getKey(), LibrariesModel.convertURIsToURLs(entry.getValue())); } Lookup.getDefault().lookup(WritableLibraryProvider.class).addLibrary(impl); } else { impl = LibraryAccessor.createLibrary(alp, type, name, area, contents); - } + Util.setDisplayName(impl, displayName); + } return new Library(impl, this); } diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/DefaultLibraryImplementation.java b/project.libraries/src/org/netbeans/modules/project/libraries/DefaultLibraryImplementation.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/DefaultLibraryImplementation.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/DefaultLibraryImplementation.java @@ -45,12 +45,14 @@ package org.netbeans.modules.project.libraries; import java.net.URL; -import org.netbeans.spi.project.libraries.LibraryImplementation; import java.util.*; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; +import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.annotations.common.NullAllowed; +import org.netbeans.spi.project.libraries.NamedLibraryImplementation; -public final class DefaultLibraryImplementation implements LibraryImplementation { +public final class DefaultLibraryImplementation implements NamedLibraryImplementation { private String description; @@ -63,6 +65,8 @@ private String localizingBundle; + private String displayName; + private List listeners; /** @@ -78,20 +82,24 @@ } + @Override public String getType() { return libraryType; } + @Override public void setName(final String name) throws UnsupportedOperationException { String oldName = this.name; this.name = name; this.firePropertyChange (PROP_NAME, oldName, this.name); } + @Override public String getName() { return name; } + @Override public List getContent(String contentType) throws IllegalArgumentException { List content = contents.get(contentType); if (content == null) @@ -99,6 +107,7 @@ return Collections.unmodifiableList (content); } + @Override public void setContent(String contentType, List path) throws IllegalArgumentException { if (path == null) { throw new IllegalArgumentException (); @@ -112,37 +121,53 @@ } } + @Override public String getDescription () { return this.description; } + @Override public void setDescription (String text) { String oldDesc = this.description; this.description = text; this.firePropertyChange (PROP_DESCRIPTION, oldDesc, this.description); } + @Override public String getLocalizingBundle() { return this.localizingBundle; } + @Override public void setLocalizingBundle(String resourceName) { this.localizingBundle = resourceName; } + @Override + public @CheckForNull String getDisplayName() { + return this.displayName; + } + + public void setDisplayName(final @NullAllowed String displayName) { + this.displayName = displayName; + } + + @Override public synchronized void addPropertyChangeListener (PropertyChangeListener l) { if (this.listeners == null) this.listeners = new ArrayList(); this.listeners.add (l); } + @Override public synchronized void removePropertyChangeListener (PropertyChangeListener l) { if (this.listeners == null) return; this.listeners.remove (l); } - public @Override String toString() { + @Override + public String toString() { return "DefaultLibraryImplementation[" + name + "]"; // NOI18N } diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/LibrariesStorage.java b/project.libraries/src/org/netbeans/modules/project/libraries/LibrariesStorage.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/LibrariesStorage.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/LibrariesStorage.java @@ -53,7 +53,6 @@ import java.net.URL; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ResourceBundle; @@ -64,7 +63,6 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.xml.parsers.ParserConfigurationException; -import org.netbeans.modules.project.libraries.ui.LibrariesCustomizer; import org.netbeans.spi.project.libraries.LibraryImplementation; import org.netbeans.spi.project.libraries.LibraryTypeProvider; import org.openide.filesystems.FileChangeAdapter; @@ -75,9 +73,6 @@ import org.openide.filesystems.FileUtil; import org.openide.util.Exceptions; import org.openide.util.NbBundle; -import org.openide.xml.XMLUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -177,7 +172,7 @@ } librariesByFileNames.put(descriptorFile.getPath(),impl); libraries.put (impl.getName(),impl); - LibrariesCustomizer.registerSource(impl, descriptorFile); + Util.registerSource(impl, descriptorFile); } } } catch (SAXException e) { @@ -235,7 +230,7 @@ final LibraryDeclarationParser parser = new LibraryDeclarationParser(handler,convertor); handler.setLibrary (impl); readLibrary (descriptorFile, parser); - LibrariesCustomizer.registerSource(impl, descriptorFile); + Util.registerSource(impl, descriptorFile); return handler.getLibrary(); } @@ -261,58 +256,24 @@ return; } FileObject fo = storage.createData (library.getName(),"xml"); //NOI18N - writeLibraryDefinition (fo, library, libraryTypeProvider); + LibraryDeclarationParser.writeLibraryDefinition (fo, library, libraryTypeProvider); } } ); } - - private static void writeLibraryDefinition (final FileObject definitionFile, final LibraryImplementation library, final LibraryTypeProvider libraryTypeProvider) throws IOException { - Document doc = XMLUtil.createDocument("library", null, - "-//NetBeans//DTD Library Declaration 1.0//EN", - "http://www.netbeans.org/dtds/library-declaration-1_0.dtd"); // NOI18N - Element libraryE = doc.getDocumentElement(); - libraryE.setAttribute("version", "1.0"); // NOI18N - libraryE.appendChild(doc.createElement("name")).appendChild(doc.createTextNode(library.getName())); // NOI18N - libraryE.appendChild(doc.createElement("type")).appendChild(doc.createTextNode(library.getType())); // NOI18N - String description = library.getDescription(); - if (description != null && description.length() > 0) { - libraryE.appendChild(doc.createElement("description")).appendChild(doc.createTextNode(description)); // NOI18N - } - String localizingBundle = library.getLocalizingBundle(); - if (localizingBundle != null && localizingBundle.length() > 0) { - libraryE.appendChild(doc.createElement("localizing-bundle")).appendChild(doc.createTextNode(localizingBundle)); // NOI18N - } - for (String vtype : libraryTypeProvider.getSupportedVolumeTypes()) { - Element volumeE = (Element) libraryE.appendChild(doc.createElement("volume")); // NOI18N - volumeE.appendChild(doc.createElement("type")).appendChild(doc.createTextNode(vtype)); // NOI18N - List volume = library.getContent(vtype); - if (volume != null) { - //If null -> broken library, repair it. - for (URL url : volume) { - volumeE.appendChild(doc.createElement("resource")).appendChild(doc.createTextNode(url.toString())); // NOI18N - } - } - } - OutputStream os = definitionFile.getOutputStream(); - try { - XMLUtil.write(doc, os, "UTF-8"); // NOI18N - } finally { - os.close(); - } - } - - + private void fireLibrariesChanged () { this.support.firePropertyChange(PROP_LIBRARIES,null,null); } + @Override public final void addPropertyChangeListener (PropertyChangeListener listener) { this.support.addPropertyChangeListener(listener); } + @Override public final void removePropertyChangeListener (PropertyChangeListener listener) { this.support.removePropertyChangeListener(listener); } @@ -320,6 +281,7 @@ /** * Return all libraries in memory. */ + @Override public final LibraryImplementation[] getLibraries() { final Libs res = initStorage(); assert res != null; @@ -327,12 +289,14 @@ } // end getLibraries + @Override public void addLibrary (LibraryImplementation library) throws IOException { this.initStorage(); assert this.storage != null : "Storage is not initialized"; writeLibrary(this.storage,library); } + @Override public void removeLibrary (LibraryImplementation library) throws IOException { final Libs data = this.initStorage(); assert this.storage != null : "Storage is not initialized"; @@ -345,6 +309,7 @@ } } + @Override public void updateLibrary(final LibraryImplementation oldLibrary, final LibraryImplementation newLibrary) throws IOException { final Libs data = this.initStorage(); assert this.storage != null : "Storage is not initialized"; @@ -361,7 +326,7 @@ this.storage.getFileSystem().runAtomicAction( new FileSystem.AtomicAction() { public void run() throws IOException { - writeLibraryDefinition (fo, newLibrary, libraryTypeProvider); + LibraryDeclarationParser.writeLibraryDefinition (fo, newLibrary, libraryTypeProvider); } } ); diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandler.java b/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandler.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandler.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandler.java @@ -91,7 +91,7 @@ * @param meta attributes * */ - public void start_library(final Attributes meta) throws SAXException; + public String start_library(final String nameSpace, final Attributes meta) throws SAXException; /** * A container element end event handling method. @@ -117,5 +117,7 @@ public void handle_localizingBundle (final String data, final Attributes meta) throws SAXException; + public void handle_displayName (String data, Attributes meta) throws SAXException; + } diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandlerImpl.java b/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandlerImpl.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandlerImpl.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationHandlerImpl.java @@ -53,8 +53,10 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; +import java.util.regex.Pattern; import org.netbeans.spi.project.libraries.LibraryImplementation; import org.netbeans.spi.project.libraries.LibraryTypeProvider; +import org.openide.util.Utilities; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -68,11 +70,11 @@ private LibraryImplementation library; - private String libraryType; private String libraryDescription; private String libraryName; private String localizingBundle; + private String displayName; private Map> contentTypes = new HashMap>(); // last volume @@ -122,8 +124,13 @@ } @Override - public void start_library(final Attributes meta) throws SAXException { - if ("1.0".equals(meta.getValue("version")) == false) { // NOI18N + public String start_library(final String nameSpace, final Attributes meta) throws SAXException { + final String version = meta.getValue("version"); + if (LibraryDeclarationParser.VER_1.equals(version)) { + return ""; //NOI18N + } else if (LibraryDeclarationParser.VER_2.equals(version)) { + return LibraryDeclarationParser.LIBRARY_NS; + } else { throw new SAXException("Invalid librray descriptor version"); // NOI18N } } @@ -137,8 +144,7 @@ library.getType()+" to: " + libraryType, null); //NOI18N } update = true; - } - else { + } else { if (this.libraryType == null) { throw new SAXParseException("Unspecified library type for: "+this.libraryName, null); //NOI18N } @@ -150,15 +156,18 @@ update = false; LibrariesStorage.LOG.log(Level.FINE, "LibraryDeclarationHandlerImpl library {0} type {1} found", new Object[] { this.libraryName, this.libraryType }); } - if (!update || !safeEquals(this.library.getLocalizingBundle(), localizingBundle)) { + if (!update || !Utilities.compareObjects(this.library.getLocalizingBundle(), localizingBundle)) { this.library.setLocalizingBundle (this.localizingBundle); } - if (!update || !safeEquals(this.library.getName(), libraryName)) { + if (!update || !Utilities.compareObjects(this.library.getName(), libraryName)) { this.library.setName (this.libraryName); } - if (!update || !safeEquals(this.library.getDescription(), libraryDescription)) { + if (!update || !Utilities.compareObjects(this.library.getDescription(), libraryDescription)) { this.library.setDescription (this.libraryDescription); } + if (!update || !Utilities.compareObjects(this.library.getLocalizingBundle(), displayName)) { + Util.setDisplayName(this.library,displayName); + } for (Map.Entry> entry : contentTypes.entrySet()) { String contentType = entry.getKey(); List cp = entry.getValue(); @@ -194,6 +203,11 @@ this.localizingBundle = data; } + @Override + public void handle_displayName (String data, Attributes meta) throws SAXException { + this.displayName = data; + } + public void setLibrary (LibraryImplementation library) { this.library = library; } @@ -203,10 +217,6 @@ } - private static boolean safeEquals (Object o1, Object o2) { - return o1 == null ? o2 == null : o1.equals (o2); - } - private static boolean urlsEqual (final Collection first, final Collection second) { assert first != null; assert second != null; diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationParser.java b/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationParser.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationParser.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/LibraryDeclarationParser.java @@ -47,10 +47,20 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.List; import java.util.Stack; import java.util.concurrent.atomic.AtomicBoolean; import javax.xml.parsers.ParserConfigurationException; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.spi.project.libraries.LibraryImplementation; +import org.netbeans.spi.project.libraries.LibraryTypeProvider; +import org.netbeans.spi.project.libraries.NamedLibraryImplementation; +import org.openide.filesystems.FileObject; import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.EntityResolver; @@ -75,10 +85,26 @@ */ public class LibraryDeclarationParser implements ContentHandler, EntityResolver { + private static final String LIBRARY_DEF_1 = "-//NetBeans//DTD Library Declaration 1.0//EN"; //NOI18N + private static final String LIBRARY_DTD_1 = "http://www.netbeans.org/dtds/library-declaration-1_0.dtd"; //NOI18N + static final String LIBRARY_NS = "http://www.netbeans.org/ns/library-declaration/2"; //NOI18N + static final String VER_1 = "1.0"; //NOI18N + static final String VER_2 = "2.0"; //NOI18N + private static final String LIBRARY = "library"; //NOI18N + private static final String VERSION = "version"; //NOI18N + private static final String VOLUME = "volume"; //NOI18N + private static final String DESCRIPTION = "description"; //NOI18N + private static final String TYPE = "type"; //NOI18N + private static final String RESOURCE = "resource"; //NOI18N + private static final String NAME = "name"; //NOI18N + private static final String BUNDLE = "localizing-bundle"; //NOI18N + private static final String DISPLAY_NAME = "display-name"; //NOI18N + private StringBuffer buffer; private final LibraryDeclarationConvertor parslet; private final LibraryDeclarationHandler handler; private Stack context; + private String expectedNS; private final AtomicBoolean used = new AtomicBoolean(); /** @@ -98,6 +124,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void setDocumentLocator(Locator locator) { } @@ -105,6 +132,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void startDocument() throws SAXException { handler.startDocument(); } @@ -113,6 +141,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void endDocument() throws SAXException { handler.endDocument(); } @@ -121,13 +150,14 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void startElement(String ns, String name, String qname, Attributes attrs) throws SAXException { dispatch(true); - context.push(new Object[] {qname, new AttributesImpl(attrs)}); - if ("volume".equals(qname)) { + context.push(new Object[] {qname, ns, new AttributesImpl(attrs)}); + if (VOLUME.equals(qname)) { handler.start_volume(attrs); - } else if ("library".equals(qname)) { - handler.start_library(attrs); + } else if (LIBRARY.equals(qname)) { + expectedNS = handler.start_library(ns, attrs); } } @@ -135,12 +165,13 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void endElement(String ns, String name, String qname) throws SAXException { dispatch(false); context.pop(); - if ("volume".equals(qname)) { + if (VOLUME.equals(qname)) { handler.end_volume(); - } else if ("library".equals(qname)) { + } else if (LIBRARY.equals(qname)) { handler.end_library(); } } @@ -149,6 +180,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void characters(char[] chars, int start, int len) throws SAXException { buffer.append(chars, start, len); } @@ -157,6 +189,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void ignorableWhitespace(char[] chars, int start, int len) throws SAXException { } @@ -164,6 +197,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void processingInstruction(String target, String data) throws SAXException { } @@ -171,6 +205,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void startPrefixMapping(final String prefix, final String uri) throws SAXException { } @@ -178,6 +213,7 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void endPrefixMapping(final String prefix) throws SAXException { } @@ -185,30 +221,38 @@ * This SAX interface method is implemented by the parser. * */ + @Override public final void skippedEntity(String name) throws SAXException { } private void dispatch(final boolean fireOnlyIfMixed) throws SAXException { if (fireOnlyIfMixed && buffer.length() == 0) return; //skip it - Object[] ctx = context.peek(); - String here = (String) ctx[0]; - Attributes attrs = (Attributes) ctx[1]; - if ("description".equals(here)) { + final Object[] ctx = context.peek(); + final String here = (String) ctx[0]; + final String ns = (String) ctx[1]; + Attributes attrs = (Attributes) ctx[2]; + if (!expectedNS.equals(ns)) { + throw new SAXException("Invalid librray descriptor namespace"); // NOI18N + } + if (DESCRIPTION.equals(here)) { if (fireOnlyIfMixed) throw new IllegalStateException("Unexpected characters() event! (Missing DTD?)"); handler.handle_description (buffer.length() == 0 ? null : buffer.toString(), attrs); - } else if ("type".equals(here)) { + } else if (TYPE.equals(here)) { if (fireOnlyIfMixed) throw new IllegalStateException("Unexpected characters() event! (Missing DTD?)"); handler.handle_type(buffer.length() == 0 ? null : buffer.toString(), attrs); - } else if ("resource".equals(here)) { + } else if (RESOURCE.equals(here)) { if (fireOnlyIfMixed) throw new IllegalStateException("Unexpected characters() event! (Missing DTD?)"); handler.handle_resource(parslet.parseResource(buffer.length() == 0 ? null : buffer.toString()), attrs); - } else if ("name".equals(here)) { + } else if (NAME.equals(here)) { if (fireOnlyIfMixed) throw new IllegalStateException("Unexpected characters() event! (Missing DTD?)"); handler.handle_name(buffer.length() == 0 ? null : buffer.toString(), attrs); - } else if ("localizing-bundle".equals(here)) { + } else if (BUNDLE.equals(here)) { if (fireOnlyIfMixed) throw new IllegalStateException("Unexpected characters() event! (Missing DTD?)"); handler.handle_localizingBundle(buffer.length() == 0 ? null : buffer.toString(), attrs); + } else if (DISPLAY_NAME.equals(here) && LIBRARY_NS.equals(ns)) { + if (fireOnlyIfMixed) throw new IllegalStateException("Unexpected characters() event! (Missing DTD?)"); + handler.handle_displayName(buffer.length() == 0 ? null : buffer.toString(), attrs); } else { //do not care } @@ -225,27 +269,24 @@ * */ public void parse(final InputSource input) throws SAXException, ParserConfigurationException, IOException { - parse(input, this); - } - - private void parse(final InputSource input, final LibraryDeclarationParser recognizer) throws SAXException, ParserConfigurationException, IOException { if (used.getAndSet(true)) { throw new IllegalStateException("The LibraryDeclarationParser was already used, create a new instance"); //NOI18N } try { - XMLReader parser = XMLUtil.createXMLReader(false, false); - parser.setContentHandler(recognizer); - parser.setErrorHandler(recognizer.getDefaultErrorHandler()); - parser.setEntityResolver(recognizer); + final XMLReader parser = XMLUtil.createXMLReader(false, true); + parser.setContentHandler(this); + parser.setErrorHandler(getDefaultErrorHandler()); + parser.setEntityResolver(this); parser.parse(input); } finally { //Recover recognizer internal state from exceptions to be reusable - if (!recognizer.context.empty()) { - recognizer.context.clear(); + if (!context.empty()) { + context.clear(); } - if (recognizer.buffer.length() > 0) { - recognizer.buffer.delete(0, recognizer.buffer.length()); + if (buffer.length() > 0) { + buffer.delete(0, buffer.length()); } + expectedNS = null; } } @@ -256,14 +297,17 @@ */ protected ErrorHandler getDefaultErrorHandler() { return new ErrorHandler() { + @Override public void error(SAXParseException ex) throws SAXException { throw ex; } + @Override public void fatalError(SAXParseException ex) throws SAXException { throw ex; } + @Override public void warning(SAXParseException ex) throws SAXException { // ignore } @@ -273,13 +317,98 @@ /** Implementation of entity resolver. Points to the local DTD * for our public ID */ + @Override public InputSource resolveEntity (String publicId, String systemId) throws SAXException { - if ("-//NetBeans//DTD Library Declaration 1.0//EN".equals(publicId)) { + if (LIBRARY_DEF_1.equals(publicId)) { InputStream is = new ByteArrayInputStream(new byte[0]); return new InputSource(is); } return null; // i.e. follow advice of systemID } + + static void writeLibraryDefinition ( + final @NonNull FileObject definitionFile, + final @NonNull LibraryImplementation library, + final @NonNull LibraryTypeProvider libraryTypeProvider) throws IOException { + final Document doc = Util.supportsDisplayName(library) ? + createLibraryDefinition2(library, libraryTypeProvider) : + createLibraryDefinition1(library, libraryTypeProvider); + final OutputStream os = definitionFile.getOutputStream(); + try { + XMLUtil.write(doc, os, "UTF-8"); // NOI18N + } finally { + os.close(); + } + } + + private static Document createLibraryDefinition1( + final @NonNull LibraryImplementation library, + final @NonNull LibraryTypeProvider libraryTypeProvider) { + final Document doc = XMLUtil.createDocument(LIBRARY, null, + LIBRARY_DEF_1, + LIBRARY_DTD_1); + final Element libraryE = doc.getDocumentElement(); + libraryE.setAttribute(VERSION, VER_1); // NOI18N + libraryE.appendChild(doc.createElement(NAME)).appendChild(doc.createTextNode(library.getName())); // NOI18N + libraryE.appendChild(doc.createElement(TYPE)).appendChild(doc.createTextNode(library.getType())); // NOI18N + String description = library.getDescription(); + if (description != null && description.length() > 0) { + libraryE.appendChild(doc.createElement(DESCRIPTION)).appendChild(doc.createTextNode(description)); // NOI18N + } + String localizingBundle = library.getLocalizingBundle(); + if (localizingBundle != null && localizingBundle.length() > 0) { + libraryE.appendChild(doc.createElement(BUNDLE)).appendChild(doc.createTextNode(localizingBundle)); // NOI18N + } + String displayname = Util.getDisplayName(library); + if (displayname != null) { + libraryE.appendChild(doc.createElement(DISPLAY_NAME)).appendChild(doc.createTextNode(displayname)); // NOI18N + } + for (String vtype : libraryTypeProvider.getSupportedVolumeTypes()) { + Element volumeE = (Element) libraryE.appendChild(doc.createElement(VOLUME)); // NOI18N + volumeE.appendChild(doc.createElement(TYPE)).appendChild(doc.createTextNode(vtype)); // NOI18N + List volume = library.getContent(vtype); + if (volume != null) { + //If null -> broken library, repair it. + for (URL url : volume) { + volumeE.appendChild(doc.createElement(RESOURCE)).appendChild(doc.createTextNode(url.toString())); // NOI18N + } + } + } + return doc; + } + + private static Document createLibraryDefinition2( + final @NonNull LibraryImplementation library, + final @NonNull LibraryTypeProvider libraryTypeProvider) { + final Document doc = XMLUtil.createDocument(LIBRARY, LIBRARY_NS, null, null); + final Element libraryE = doc.getDocumentElement(); + libraryE.setAttribute(VERSION, VER_2); // NOI18N + libraryE.appendChild(doc.createElementNS(LIBRARY_NS, NAME)).appendChild(doc.createTextNode(library.getName())); // NOI18N + libraryE.appendChild(doc.createElementNS(LIBRARY_NS, TYPE)).appendChild(doc.createTextNode(library.getType())); // NOI18N + String description = library.getDescription(); + if (description != null && description.length() > 0) { + libraryE.appendChild(doc.createElementNS(LIBRARY_NS, DESCRIPTION)).appendChild(doc.createTextNode(description)); // NOI18N + } + String localizingBundle = library.getLocalizingBundle(); + if (localizingBundle != null && localizingBundle.length() > 0) { + libraryE.appendChild(doc.createElementNS(LIBRARY_NS, BUNDLE)).appendChild(doc.createTextNode(localizingBundle)); // NOI18N + } + String displayname = Util.getDisplayName(library); + if (displayname != null) { + libraryE.appendChild(doc.createElementNS(LIBRARY_NS, DISPLAY_NAME)).appendChild(doc.createTextNode(displayname)); // NOI18N + } + for (String vtype : libraryTypeProvider.getSupportedVolumeTypes()) { + Element volumeE = (Element) libraryE.appendChild(doc.createElementNS(LIBRARY_NS,VOLUME)); // NOI18N + volumeE.appendChild(doc.createElementNS(LIBRARY_NS, TYPE)).appendChild(doc.createTextNode(vtype)); // NOI18N + List volume = library.getContent(vtype); + if (volume != null) { + for (URL url : volume) { + volumeE.appendChild(doc.createElementNS(LIBRARY_NS, RESOURCE)).appendChild(doc.createTextNode(url.toString())); // NOI18N + } + } + } + return doc; + } } diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/Util.java b/project.libraries/src/org/netbeans/modules/project/libraries/Util.java new file mode 100644 --- /dev/null +++ b/project.libraries/src/org/netbeans/modules/project/libraries/Util.java @@ -0,0 +1,148 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 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 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.project.libraries; + +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; +import org.netbeans.modules.project.libraries.ui.ProxyLibraryImplementation; +import org.netbeans.spi.project.libraries.LibraryImplementation; +import org.netbeans.spi.project.libraries.NamedLibraryImplementation; +import org.openide.filesystems.FileObject; +import org.openide.util.NbBundle; + +/** + * + * @author Tomas Zezula + */ +public class Util { + + private static final Logger LOG = Logger.getLogger(Util.class.getName()); + private static Map sources = new WeakHashMap(); + + private Util(){} + + public static @NonNull String getLocalizedName(LibraryImplementation impl) { + if (supportsDisplayName(impl) && ((NamedLibraryImplementation)impl).getDisplayName() != null) { + return ((NamedLibraryImplementation)impl).getDisplayName(); + } + final FileObject src = sources.get(impl); + if (src != null) { + Object obj = src.getAttribute("displayName"); // NOI18N + if (obj instanceof String) { + return (String)obj; + } + } + if (impl instanceof ProxyLibraryImplementation) { + String proxiedName = getLocalizedName(((ProxyLibraryImplementation)impl).getOriginal()); + if (proxiedName != null) { + return proxiedName; + } + } + + return getLocalizedString(impl.getLocalizingBundle(), impl.getName()); + } + + public static boolean supportsDisplayName(final @NonNull LibraryImplementation impl) { + assert impl != null; + if (impl instanceof ProxyLibraryImplementation) { + return supportsDisplayName(((ProxyLibraryImplementation)impl).getOriginal()); + } + return impl instanceof NamedLibraryImplementation; + } + + public static @CheckForNull String getDisplayName (final @NonNull LibraryImplementation impl) { + return supportsDisplayName(impl) ? + ((NamedLibraryImplementation)impl).getDisplayName() : + null; + } + + public static boolean setDisplayName( + final @NonNull LibraryImplementation impl, + final @NullAllowed String name) { + if (supportsDisplayName(impl)) { + ((NamedLibraryImplementation)impl).setDisplayName(name); + return true; + + } else { + return false; + } + } + + public static void registerSource( + final @NonNull LibraryImplementation impl, + final @NonNull FileObject descriptorFile) { + sources.put(impl, descriptorFile); + } + + + private static String getLocalizedString ( + final @NullAllowed String bundleResourceName, + final @NullAllowed String key) { + if (key == null) { + return null; + } + if (bundleResourceName == null) { + return key; + } + final ResourceBundle bundle; + try { + bundle = NbBundle.getBundle(bundleResourceName); + } catch (MissingResourceException mre) { + // Bundle should have existed. + LOG.log(Level.INFO, "Wrong resource bundle", mre); //NOI18N + return key; + } + try { + return bundle.getString (key); + } catch (MissingResourceException mre) { + // No problem, not specified. + return key; + } + } +} diff --git a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/resources/j2se-project.xsd b/project.libraries/src/org/netbeans/modules/project/libraries/resources/library-declaration-2_0.xsd copy from java.j2seproject/src/org/netbeans/modules/java/j2seproject/resources/j2se-project.xsd copy to project.libraries/src/org/netbeans/modules/project/libraries/resources/library-declaration-2_0.xsd --- a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/resources/j2se-project.xsd +++ b/project.libraries/src/org/netbeans/modules/project/libraries/resources/library-declaration-2_0.xsd @@ -44,33 +44,33 @@ made subject to such option by the copyright holder. --> - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/resources/mf-layer.xml b/project.libraries/src/org/netbeans/modules/project/libraries/resources/mf-layer.xml --- a/project.libraries/src/org/netbeans/modules/project/libraries/resources/mf-layer.xml +++ b/project.libraries/src/org/netbeans/modules/project/libraries/resources/mf-layer.xml @@ -56,6 +56,12 @@ + + + + + + diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/ui/Bundle.properties b/project.libraries/src/org/netbeans/modules/project/libraries/ui/Bundle.properties --- a/project.libraries/src/org/netbeans/modules/project/libraries/ui/Bundle.properties +++ b/project.libraries/src/org/netbeans/modules/project/libraries/ui/Bundle.properties @@ -51,7 +51,6 @@ ERR_ExistingName=Library {0} already exists. ERR_InvalidName=The library name is not valid. -ERR_InvalidCharacters=The library name contains invalid characters CTL_LibrariesManager=&Libraries diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibrariesCustomizer.java b/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibrariesCustomizer.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibrariesCustomizer.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibrariesCustomizer.java @@ -66,17 +66,15 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.ResourceBundle; -import java.util.WeakHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.regex.Pattern; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; import org.netbeans.modules.project.libraries.LibraryTypeRegistry; +import org.netbeans.modules.project.libraries.Util; import org.netbeans.spi.project.libraries.LibraryCustomizerContext; import org.netbeans.spi.project.libraries.LibraryImplementation; import org.netbeans.spi.project.libraries.LibraryStorageArea; @@ -86,7 +84,6 @@ import org.openide.NotifyDescriptor; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.BeanTreeView; -import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataFolder; import org.openide.nodes.AbstractNode; @@ -102,8 +99,7 @@ public final class LibrariesCustomizer extends JPanel implements ExplorerManager.Provider, HelpCtx.Provider { - private static final Logger LOG = Logger.getLogger(LibrariesCustomizer.class.getName()); - + private static final Pattern VALID_LIBRARY_NAME = Pattern.compile("[-._a-zA-Z0-9]+"); // NOI18N private ExplorerManager manager; private LibrariesModel model; private BeanTreeView libraries; @@ -196,6 +192,7 @@ } } + @Override public HelpCtx getHelpCtx() { return new HelpCtx( LibrariesCustomizer.class ); } @@ -210,16 +207,19 @@ } } + @Override public void addNotify() { super.addNotify(); expandTree(); this.libraries.requestFocus(); } + @Override public ExplorerManager getExplorerManager () { if (this.manager == null) { this.manager = new ExplorerManager (); this.manager.addPropertyChangeListener (new PropertyChangeListener() { + @Override public void propertyChange (PropertyChangeEvent event) { if (ExplorerManager.PROP_SELECTED_NODES.equals(event.getPropertyName())) { Node[] nodes = (Node[]) event.getNewValue (); @@ -229,6 +229,7 @@ } }); this.manager.addVetoableChangeListener(new VetoableChangeListener() { + @Override public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException { if (ExplorerManager.PROP_SELECTED_NODES.equals(event.getPropertyName())) { Node[] nodes = (Node[]) event.getNewValue(); @@ -255,6 +256,7 @@ this.libraryName.setEnabled(false); this.libraryName.addActionListener( new ActionListener () { + @Override public void actionPerformed(ActionEvent e) { nameChanged(); } @@ -314,7 +316,7 @@ boolean editable = model.isLibraryEditable (impl); this.libraryName.setEnabled(editable); this.deleteButton.setEnabled(editable); - this.libraryName.setText (getLocalizedName(impl)); + this.libraryName.setText (Util.getLocalizedName(impl)); LibraryTypeProvider provider = nodes[0].getLookup().lookup(LibraryTypeProvider.class); if (provider == null) return; @@ -523,8 +525,9 @@ dlg = DialogDisplayer.getDefault().createDialog (dd); dlg.setVisible(true); if (dd.getValue() == DialogDescriptor.OK_OPTION) { - String libraryType = p.getLibraryType(); - String currentLibraryName = p.getLibraryName(); + final String libraryType = p.getLibraryType(); + final String currentLibraryName = p.getLibraryName(); + final String antLibraryName = createFreeAntLibraryName(currentLibraryName, model, area); LibraryImplementation impl; if (area != LibrariesModel.GLOBAL_AREA) { impl = model.createArealLibrary(libraryType, currentLibraryName, area); @@ -534,8 +537,9 @@ return; } impl = provider.createLibrary(); - impl.setName(currentLibraryName); + impl.setName(antLibraryName); } + Util.setDisplayName(impl, currentLibraryName); model.addLibrary (impl); forceTreeRecreation(); String[] path = {impl.getType(), impl.getName()}; @@ -564,7 +568,22 @@ } }//GEN-LAST:event_createLibrary - static boolean isValidName(LibrariesModel model, String name, LibraryStorageArea area) { + static boolean isExistingDisplayName( + final @NonNull LibrariesModel model, + final @NonNull String name, + final @NullAllowed LibraryStorageArea area) { + for (LibraryImplementation lib : model.getLibraries()) { + if (Util.getLocalizedName(lib).equals(name) && Utilities.compareObjects(model.getArea(lib), area)) { + return true; + } + } + return false; + } + + private static boolean isValidName( + final @NonNull LibrariesModel model, + final @NonNull String name, + final @NullAllowed LibraryStorageArea area) { for (LibraryImplementation lib : model.getLibraries()) { if (lib.getName().equals(name) && Utilities.compareObjects(model.getArea(lib), area)) { return false; @@ -573,53 +592,31 @@ return true; } - private static Map sources = new WeakHashMap(); - public static void registerSource(LibraryImplementation impl, FileObject descriptorFile) { - sources.put(impl, descriptorFile); + + public static String createFreeAntLibraryName( + @NonNull String name, + final @NonNull LibrariesModel model, + final @NullAllowed LibraryStorageArea area) { + // XXX: there is method in PropertyUtils + // which should be used here but that would create dependency + // on ant/project modules which is not desirable. + if (!VALID_LIBRARY_NAME.matcher(name).matches()) { + final StringBuilder sb = new StringBuilder(name); + for (int i=0; i { public int compare(LibraryImplementation lib1, LibraryImplementation lib2) { - String name1 = LibrariesCustomizer.getLocalizedName(lib1); - String name2 = LibrariesCustomizer.getLocalizedName(lib2); + String name1 = Util.getLocalizedName(lib1); + String name2 = Util.getLocalizedName(lib2); int r = name1.compareToIgnoreCase(name2); return r != 0 ? r : System.identityHashCode(lib1) - System.identityHashCode(lib2); } } - private static final class DummyArealLibrary implements LibraryImplementation2 { + private static final class DummyArealLibrary implements LibraryImplementation2, NamedLibraryImplementation { private final String type, name; final Map> contents = new HashMap>(); private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private String displayName; public DummyArealLibrary(String type, String name) { this.type = type; this.name = name; } + @Override public String getType() { return type; } + @Override public String getName() { return name; } + @Override + public String getDisplayName() { + return displayName; + } + + @Override public String getDescription() { return null; } + @Override public String getLocalizingBundle() { return null; } + @Override public List getContent(String volumeType) throws IllegalArgumentException { return convertURIsToURLs(getURIContent(volumeType)); } + @Override public List getURIContent(String volumeType) throws IllegalArgumentException { List content = contents.get(volumeType); if (content != null) { @@ -405,30 +421,42 @@ } } + @Override public void setName(String name) { throw new UnsupportedOperationException(); } + @Override + public void setDisplayName(final @NullAllowed String displayName) { + this.displayName = displayName; + } + + @Override public void setDescription(String text) { throw new UnsupportedOperationException(); } + @Override public void setLocalizingBundle(String resourceName) { throw new UnsupportedOperationException(); } + @Override public void addPropertyChangeListener(PropertyChangeListener l) { pcs.addPropertyChangeListener(l); } + @Override public void removePropertyChangeListener(PropertyChangeListener l) { pcs.removePropertyChangeListener(l); } + @Override public void setContent(String volumeType, List path) throws IllegalArgumentException { setURIContent(volumeType, convertURLsToURIs(path)); } + @Override public void setURIContent(String volumeType, List path) throws IllegalArgumentException { contents.put(volumeType, path); pcs.firePropertyChange(LibraryImplementation.PROP_CONTENT, null, null); diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibraryRenderer.java b/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibraryRenderer.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibraryRenderer.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/ui/LibraryRenderer.java @@ -48,13 +48,14 @@ import java.awt.Component; import javax.swing.DefaultListCellRenderer; import javax.swing.JList; +import org.netbeans.modules.project.libraries.Util; class LibraryRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { LibraryImplementation impl = (LibraryImplementation) value; return super.getListCellRendererComponent(list, - LibrariesCustomizer.getLocalizedName(impl), + Util.getLocalizedName(impl), index, isSelected, cellHasFocus); } diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/ui/NewLibraryPanel.java b/project.libraries/src/org/netbeans/modules/project/libraries/ui/NewLibraryPanel.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/ui/NewLibraryPanel.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/ui/NewLibraryPanel.java @@ -45,13 +45,8 @@ package org.netbeans.modules.project.libraries.ui; import java.awt.Color; -import java.awt.Component; import java.util.HashMap; import java.util.Map; -import java.util.regex.Pattern; -import javax.swing.DefaultComboBoxModel; -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; import org.openide.DialogDescriptor; import org.openide.util.NbBundle; import org.netbeans.modules.project.libraries.LibraryTypeRegistry; @@ -65,8 +60,7 @@ private LibraryStorageArea area; private DialogDescriptor dd; - - private static final Pattern VALID_LIBRARY_NAME = Pattern.compile("[-._a-zA-Z0-9]+"); // NOI18N + public NewLibraryPanel (LibrariesModel model, String preselectedLibraryType, LibraryStorageArea area) { this.model = model; @@ -142,37 +136,20 @@ private void nameChanged () { String name = this.name.getText(); boolean valid = false; - String message; + String message = ""; //NOI18N if (name.length() == 0) { message = NbBundle.getMessage(NewLibraryPanel.class,"ERR_InvalidName"); - } - else { - valid = LibrariesCustomizer.isValidName(model, name, area); - if (valid) { - if (isReasonableAntProperty(name)) { - message = " "; //NOI18N - } else { - valid = false; - message = NbBundle.getMessage(NewLibraryPanel.class,"ERR_InvalidCharacters"); - } - } - else { - message = NbBundle.getMessage(NewLibraryPanel.class, "ERR_ExistingName", name); - } + } else if (LibrariesCustomizer.isExistingDisplayName(model, name, area)){ + message = NbBundle.getMessage(NewLibraryPanel.class, "ERR_ExistingName", name); + } else { + valid = true; } if (dd != null) { dd.setValid(valid); } this.status.setText(message); } - - private boolean isReasonableAntProperty(String name) { - // XXX: there is method in PropertyUtils.isUsablePropertyName() - // which should be used here but that would create dependency - // on ant/project modules which is not desirable. - // XXX: The restriction of display name should be fixed in promo F - return VALID_LIBRARY_NAME.matcher(name).matches(); - } + /** This method is called from within the constructor to * initialize the form. diff --git a/project.libraries/src/org/netbeans/modules/project/libraries/ui/ProxyLibraryImplementation.java b/project.libraries/src/org/netbeans/modules/project/libraries/ui/ProxyLibraryImplementation.java --- a/project.libraries/src/org/netbeans/modules/project/libraries/ui/ProxyLibraryImplementation.java +++ b/project.libraries/src/org/netbeans/modules/project/libraries/ui/ProxyLibraryImplementation.java @@ -52,24 +52,29 @@ import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; +import org.netbeans.api.annotations.common.NullAllowed; +import org.netbeans.modules.project.libraries.Util; import org.netbeans.spi.project.libraries.LibraryImplementation; import org.netbeans.spi.project.libraries.LibraryImplementation2; +import org.netbeans.spi.project.libraries.NamedLibraryImplementation; import org.openide.util.WeakListeners; /** * * @author tom */ -public class ProxyLibraryImplementation implements LibraryImplementation, PropertyChangeListener { +public class ProxyLibraryImplementation implements NamedLibraryImplementation, PropertyChangeListener { private final LibraryImplementation original; private final LibrariesModel model; Map> newContents; private String newName; + private String newDisplayName; private String newDescription; private PropertyChangeSupport support; + @SuppressWarnings("LeakingThisInConstructor") private ProxyLibraryImplementation (LibraryImplementation original, LibrariesModel model) { assert original != null && model != null; this.original = original; @@ -98,19 +103,23 @@ return this.original; } + @Override public void addPropertyChangeListener(PropertyChangeListener l) { this.support.addPropertyChangeListener(l); } + @Override public void removePropertyChangeListener(PropertyChangeListener l) { this.support.removePropertyChangeListener(l); } + @Override public String getType() { return this.original.getType (); } + @Override public synchronized List getContent(String volumeType) throws IllegalArgumentException { List result = null; if (newContents == null || (result = newContents.get(volumeType)) == null) { @@ -121,6 +130,7 @@ } } + @Override public synchronized String getDescription() { if (this.newDescription != null) { return this.newDescription; @@ -130,6 +140,7 @@ } } + @Override public synchronized String getName() { if (this.newName != null) { return this.newName; @@ -138,7 +149,18 @@ return this.original.getName (); } } + + @Override + public String getDisplayName() { + if (!Util.supportsDisplayName(original)) { + throw new IllegalStateException("Original does not support displayName"); //NOI18N + } + synchronized (this) { + return newDisplayName != null ? newDisplayName : Util.getDisplayName(original); + } + } + @Override public synchronized void setContent(String volumeType, List path) throws IllegalArgumentException { if (this.newContents == null) { this.newContents = new HashMap>(); @@ -148,6 +170,7 @@ this.support.firePropertyChange(PROP_CONTENT,null,null); //NOI18N } + @Override public synchronized void setDescription(String text) { String oldDescription = this.newDescription == null ? this.original.getDescription() : this.newDescription; this.newDescription = text; @@ -155,6 +178,7 @@ this.support.firePropertyChange(PROP_DESCRIPTION,oldDescription,this.newDescription); //NOI18N } + @Override public synchronized void setName(String name) { String oldName = this.newName == null ? this.original.getName() : this.newName; this.newName = name; @@ -162,24 +186,40 @@ this.support.firePropertyChange(PROP_NAME,oldName,this.newName); //NOI18N } + @Override + public void setDisplayName(final @NullAllowed String displayName) { + final String oldName; + synchronized (this) { + oldName = this.newDisplayName != null ? this.newDisplayName : Util.getDisplayName(original); + this.newName = displayName; + this.model.modifyLibrary(this); + } + this.support.firePropertyChange(PROP_DISPLAY_NAME, oldName, displayName); + } + + @Override public String getLocalizingBundle() { return this.original.getLocalizingBundle(); } + @Override public void setLocalizingBundle(String resourceName) { throw new UnsupportedOperationException(); } + @Override public void propertyChange(PropertyChangeEvent evt) { this.support.firePropertyChange(evt.getPropertyName(),evt.getOldValue(),evt.getNewValue()); } + @Override public int hashCode() { return this.original.hashCode(); } + @Override public boolean equals(Object obj) { if (obj instanceof ProxyLibraryImplementation) { return this.original.equals(((ProxyLibraryImplementation)obj).getOriginal()); @@ -188,11 +228,12 @@ return false; } - public @Override String toString() { + @Override + public String toString() { return "Proxy[" + original + "]"; // NOI18N } - static class ProxyLibraryImplementation2 extends ProxyLibraryImplementation implements LibraryImplementation2 { + static class ProxyLibraryImplementation2 extends ProxyLibraryImplementation implements LibraryImplementation2, NamedLibraryImplementation { Map> newURIContents; @@ -204,6 +245,7 @@ return (LibraryImplementation2)getOriginal(); } + @Override public List getURIContent(String volumeType) throws IllegalArgumentException { List result = null; if (newURIContents == null || (result = newURIContents.get(volumeType)) == null) { @@ -213,6 +255,7 @@ } } + @Override public void setURIContent(String volumeType, List path) throws IllegalArgumentException { if (newURIContents == null) { newURIContents = new HashMap>(); @@ -222,10 +265,12 @@ getSupport().firePropertyChange(PROP_CONTENT,null,null); } + @Override public final int hashCode() { return getOriginal().hashCode(); } + @Override public final boolean equals(Object obj) { if (obj instanceof ProxyLibraryImplementation2) { return getOriginal().equals(((ProxyLibraryImplementation2)obj).getOriginal()); @@ -234,7 +279,8 @@ return false; } - public @Override String toString() { + @Override + public String toString() { return "Proxy2[" + getOriginal() + "]"; // NOI18N } } diff --git a/project.libraries/src/org/netbeans/spi/project/libraries/NamedLibraryImplementation.java b/project.libraries/src/org/netbeans/spi/project/libraries/NamedLibraryImplementation.java new file mode 100644 --- /dev/null +++ b/project.libraries/src/org/netbeans/spi/project/libraries/NamedLibraryImplementation.java @@ -0,0 +1,72 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 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 2011 Sun Microsystems, Inc. + */ +package org.netbeans.spi.project.libraries; + +import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.annotations.common.NullAllowed; + +/** + * LibraryImplementation extension allowing setting/getting display name. + * @author Tomas Zezula + * @since org.netbeans.modules.project.libraries/1 1.31 + */ +public interface NamedLibraryImplementation extends LibraryImplementation { + + /** + * Name of displayName property. + */ + String PROP_DISPLAY_NAME = "displayName"; //NOI18N + + /** + * Sets the display name. + * @param displayName the new value of the displayName. + * If null resets the display name to the value provided + * by the localizing bundle or the identifying name. + */ + void setDisplayName(@NullAllowed String displayName); + + /** + * Returns the display name if available or null. + * @return the display name + */ + @CheckForNull String getDisplayName(); +} diff --git a/project.libraries/test/unit/src/org/netbeans/modules/project/libraries/LibrariesStorageTest.java b/project.libraries/test/unit/src/org/netbeans/modules/project/libraries/LibrariesStorageTest.java --- a/project.libraries/test/unit/src/org/netbeans/modules/project/libraries/LibrariesStorageTest.java +++ b/project.libraries/test/unit/src/org/netbeans/modules/project/libraries/LibrariesStorageTest.java @@ -138,12 +138,12 @@ assertEquals("Libraries count",2,libs.length); LibraryImplementation impl = libs[0].getName().equals("Library2") ? libs[0] : libs[1]; - assertEquals("MyName", LibrariesCustomizer.getLocalizedName(impl)); + assertEquals("MyName", Util.getLocalizedName(impl)); LibrariesModel model = new LibrariesModel(); ProxyLibraryImplementation proxy = ProxyLibraryImplementation.createProxy(impl, model); - assertEquals("MyName", LibrariesCustomizer.getLocalizedName(proxy)); + assertEquals("MyName", Util.getLocalizedName(proxy)); } public void testAddLibrary() throws Exception {