diff -r ffef4cca2ff4 project.ant/apichanges.xml --- a/project.ant/apichanges.xml Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/apichanges.xml Thu Feb 21 14:37:31 2008 +0100 @@ -40,8 +40,8 @@ Version 2 license, then the option applies only if the new code is made subject to such option by the copyright holder. --> - - + + - + + + + Support for project-specific libraries + + + + + +

+ A new XML schema + (http://www.netbeans.org/ns/ant-project-libraries/1), + several new API methods + (AntProjectHelper.getProjectLibrariesPropertyProvider, + AntProjectHelper.isSharableProject, + AntProjectHelper.getLibrariesLocation, + AntProjectHelper.setLibrariesLocation, + ProjectGenerator.createProject(FileObject, String, String), + ReferenceHelper.createForeignFileReferenceAsIs, + ReferenceHelper.createExtraForeignFileReferenceAsIs, + ReferenceHelper.copyLibrary, + ReferenceHelper.getLibraryChooserImportHandler, + ReferenceHelper.createLibraryReference, + ReferenceHelper.getProjectLibraryManager, + ReferenceHelper.findLibrary) and + custom file chooser (FileChooser) + provide support for collocated library definitions + referred to from Ant-based projects. +

+
+ + + + + +
+ Support for adding external files owned by project diff -r ffef4cca2ff4 project.ant/src/org/netbeans/api/project/ant/FileChooser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project.ant/src/org/netbeans/api/project/ant/FileChooser.java Thu Feb 21 14:37:31 2008 +0100 @@ -0,0 +1,162 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * 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. + */ + +package org.netbeans.api.project.ant; + +import java.awt.Dialog; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import javax.swing.JFileChooser; +import org.netbeans.api.project.FileOwnerQuery; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.libraries.LibraryManager; +import org.netbeans.modules.project.ant.FileChooserAccessory; +import org.netbeans.modules.project.ant.RelativizeFilePathCustomizer; +import org.netbeans.modules.project.ant.ProjectLibraryProvider; +import org.netbeans.spi.project.AuxiliaryConfiguration; +import org.netbeans.spi.project.support.ant.AntProjectHelper; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.NbBundle; + + +/** + * Custom file chooser allowing user to choose how a file will be referenced + * from a project - via absolute path, or relative path. Make sure you call + * {@link #getSelectedPaths} instead of {@link #getSelectedFiles} as it returns relative + * files and performs file copying if necessary. + * + * @author David Konecny + * @since org.netbeans.modules.project.ant/1 1.19 + */ +public final class FileChooser extends JFileChooser { + + private FileChooserAccessory accessory; + + /** + * Create chooser for given AntProjectHelper. Standard file chooser is shown + * if project is not sharable. + * + * @param helper ant project helper; cannot be null + * @param copyAllowed is file copying allowed + */ + public FileChooser(AntProjectHelper helper, boolean copyAllowed) { + super(); + LibraryManager lm = ProjectLibraryProvider.getProjectLibraryManager(helper); + if (lm != null) { + URL u = lm.getLocation(); + if (u != null) { + File libBase = new File(URI.create(u.toExternalForm())).getParentFile(); + accessory = new FileChooserAccessory(this, FileUtil.toFile(helper.getProjectDirectory()), + libBase, copyAllowed); + setAccessory(accessory); + } + } + } + + /** + * Create chooser for given base folder and shared libraries folder. + * + * @param baseFolder base folder to which all selected files will be relativized; + * can be null in which case regular file chooser is shown + * @param sharedLibrariesFolder providing shared libraries folder enables option + * of copying selected files there; can be null in which case copying option + * is disabled + */ + public FileChooser(File baseFolder, File sharedLibrariesFolder) { + super(); + if (baseFolder != null) { + accessory = new FileChooserAccessory(this, baseFolder, sharedLibrariesFolder, sharedLibrariesFolder != null); + setAccessory(accessory); + } + } + + /** + * Returns array of paths selected. The difference from + * {@link #getSelectedFiles} is that depends on user's choice the files + * may be relative and they may have been copied to different location. + * + * @return array of files which may be relative to base folder this chooser + * was created for; e.g. project folder in case of AntProjectHelper + * constructor; never null; can be empty array + * @throws java.io.IOException any IO problem; for example during + * file copying + */ + public String[] getSelectedPaths() throws IOException { + if (accessory != null) { + accessory.copyFilesIfNecessary(); + if (accessory.isRelative()) { + return accessory.getFiles(); + } + } + if (isMultiSelectionEnabled()) { + File[] sels = getSelectedFiles(); + String[] toRet = new String[sels.length]; + int index = 0; + for (File fil : sels) { + toRet[index] = fil.getAbsolutePath(); + index++; + } + return toRet; + } else { + if (getSelectedFile() != null) { + return new String[]{ getSelectedFile().getAbsolutePath() }; + } else { + return new String[0]; + } + } + } + + @Override + public void approveSelection() { + if (accessory != null && !accessory.canApprove()) { + return; + } + super.approveSelection(); + } + + + +} diff -r ffef4cca2ff4 project.ant/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java --- a/project.ant/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java Thu Feb 21 14:37:31 2008 +0100 @@ -60,6 +60,7 @@ import org.netbeans.modules.project.ant.FileChangeSupport; import org.netbeans.modules.project.ant.FileChangeSupportEvent; import org.netbeans.modules.project.ant.FileChangeSupportListener; +import org.netbeans.modules.project.ant.ProjectLibraryProvider; import org.netbeans.modules.project.ant.UserQuestionHandler; import org.netbeans.modules.project.ant.Util; import org.netbeans.spi.project.AuxiliaryConfiguration; @@ -429,7 +430,7 @@ return null; } }; - if (ProjectManager.mutex().isWriteAccess()) { + if (ProjectManager.mutex().isWriteAccess() || ProjectLibraryProvider.FIRE_CHANGES_SYNCH) { // Run it right now. postReadRequest would be too late. ProjectManager.mutex().readAccess(action); } else if (ProjectManager.mutex().isReadAccess()) { @@ -542,6 +543,10 @@ */ private void save() throws IOException { assert ProjectManager.mutex().isWriteAccess(); + if (!getProjectDirectory().isValid()) { + //ProjectManager.saveProject() is called when project is deleted externally.. + return; + } Set locks = new HashSet(); try { synchronized (modifiedMetadataPaths) { @@ -1019,6 +1024,11 @@ * It is permitted, and harmless, to include items that overlap others. For example, * you can have both a directory and one of its children in the include list. *

+ *

+ * Whether or not you use this method, all files named *-private.properties + * outside the project are marked unsharable, as are such files inside the project if currently referenced + * as project libraries. (See {@link #getProjectLibrariesPropertyProvider}.) + *

*
*

* Typical usage would be: @@ -1072,12 +1082,59 @@ public PropertyProvider getStockPropertyPreprovider() { return properties.getStockPropertyPreprovider(); } + + /** + * Creates a property provider which can load definitions of project libraries. + * If this project refers to any project library definition files, they will + * be included, with ${base} replaced by the appropriate value. + * @return a property provider + * @since org.netbeans.modules.project.ant/1 1.19 + * @see Schema for project library references + */ + public PropertyProvider getProjectLibrariesPropertyProvider() { + return ProjectLibraryProvider.createPropertyProvider(this); + } + + /** + * Is this project shared with other or not, that is is it using shrared + * libraries or not. + * @return true for shared project + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public boolean isSharableProject() + { + return getLibrariesLocation() != null; + } + + /** + * Returns location of shared libraries associated with this project or null. + * @return relative or absolute OS path or null + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public String getLibrariesLocation() + { + return ProjectLibraryProvider.getLibrariesLocationText(this.createAuxiliaryConfiguration()); + } + + /** + * Change project's associated shared libraries location. If location is + * null then project will not have shared libraries and will + * be considered as not being shared. + * + * @param location project relative or absolute OS path or null + * @since org.netbeans.modules.project.ant/1 1.18 + */ + public void setLibrariesLocation(String location) + { + ProjectLibraryProvider.setLibrariesLocation(this, location); + } /** * Get a property evaluator that can evaluate properties according to the default * file layout for Ant-based projects. * First, {@link #getStockPropertyPreprovider stock properties} are predefined. * Then {@link #PRIVATE_PROPERTIES_PATH} is loaded via {@link #getPropertyProvider}, + * then {@link #getProjectLibrariesPropertyProvider}, * then global definitions from {@link PropertyUtils#globalPropertyProvider} * (though these may be overridden using the property user.properties.file * in private.properties), then {@link #PROJECT_PROPERTIES_PATH}. @@ -1127,6 +1184,7 @@ return PropertyUtils.resolvePath(FileUtil.toFile(dir), path); } + @Override public String toString() { return "AntProjectHelper[" + getProjectDirectory() + "]"; // NOI18N } diff -r ffef4cca2ff4 project.ant/src/org/netbeans/spi/project/support/ant/ProjectGenerator.java --- a/project.ant/src/org/netbeans/spi/project/support/ant/ProjectGenerator.java Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/src/org/netbeans/spi/project/support/ant/ProjectGenerator.java Thu Feb 21 14:37:31 2008 +0100 @@ -41,12 +41,14 @@ package org.netbeans.spi.project.support.ant; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectManager; import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton; +import org.netbeans.modules.project.ant.ProjectLibraryProvider; import org.openide.filesystems.FileLock; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; @@ -90,10 +92,24 @@ * new project on disk is recognized by some other factory */ public static AntProjectHelper createProject(final FileObject directory, final String type) throws IOException, IllegalArgumentException { - return createProject0(directory, type, null); + return createProject0(directory, type, null, null); } - private static AntProjectHelper createProject0(final FileObject directory, final String type, final String name) throws IOException, IllegalArgumentException { + /** + * See {@link #createProject(FileObject, String)} for more datails. This + * method in addition allows to setup shared libraries location + * @param directory the main project directory to create it in + * (see {@link AntProjectHelper#getProjectDirectory}) + * @param type a unique project type identifier (see {@link AntBasedProjectType#getType}) + * @param librariesDefinition relative or absolute OS path; can be null + */ + public static AntProjectHelper createProject(final FileObject directory, final String type, + final String librariesDefinition) throws IOException, IllegalArgumentException { + return createProject0(directory, type, null, librariesDefinition); + } + + private static AntProjectHelper createProject0(final FileObject directory, final String type, + final String name, final String librariesDefinition) throws IOException, IllegalArgumentException { try { return ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { public AntProjectHelper run() throws IOException { @@ -116,6 +132,18 @@ } el = doc.createElementNS(AntProjectHelper.PROJECT_NS, "configuration"); // NOI18N doc.getDocumentElement().appendChild(el); + if (librariesDefinition != null) { + el.appendChild(ProjectLibraryProvider.createLibrariesElement(doc, librariesDefinition)); + // create libraries property file if it does not exist: + File f = new File(librariesDefinition); + if (!f.isAbsolute()) { + f = new File(FileUtil.toFile(directory), librariesDefinition); + } + f = FileUtil.normalizeFile(f); + if (!f.exists()) { + FileUtil.createData(f); + } + } FileLock lock = projectXml.lock(); try { OutputStream os = projectXml.getOutputStream(lock); diff -r ffef4cca2ff4 project.ant/src/org/netbeans/spi/project/support/ant/ProjectProperties.java --- a/project.ant/src/org/netbeans/spi/project/support/ant/ProjectProperties.java Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/src/org/netbeans/spi/project/support/ant/ProjectProperties.java Thu Feb 21 14:37:31 2008 +0100 @@ -409,6 +409,7 @@ standardPropertyEvaluator = PropertyUtils.sequentialPropertyEvaluator( getStockPropertyPreprovider(), getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH), + helper.getProjectLibrariesPropertyProvider(), globalProperties, getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH)); } diff -r ffef4cca2ff4 project.ant/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java --- a/project.ant/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java Thu Feb 21 14:37:31 2008 +0100 @@ -43,6 +43,7 @@ import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -55,6 +56,7 @@ import java.util.Properties; import java.util.Set; import java.util.TreeSet; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.netbeans.api.project.Project; @@ -62,8 +64,12 @@ import org.netbeans.api.project.ProjectUtils; import org.netbeans.api.project.ant.AntArtifact; import org.netbeans.api.project.ant.AntArtifactQuery; +import org.netbeans.api.project.libraries.Library; +import org.netbeans.api.project.libraries.LibraryChooser; +import org.netbeans.api.project.libraries.LibraryManager; import org.netbeans.api.queries.CollocationQuery; import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton; +import org.netbeans.modules.project.ant.ProjectLibraryProvider; import org.netbeans.modules.project.ant.Util; import org.netbeans.spi.project.AuxiliaryConfiguration; import org.netbeans.spi.project.SubprojectProvider; @@ -72,6 +78,7 @@ import org.openide.filesystems.FileUtil; import org.openide.util.Mutex; import org.openide.util.NbCollections; +import org.openide.util.Parameters; import org.openide.xml.XMLUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -332,7 +339,11 @@ relativePath }; } - else if (CollocationQuery.areCollocated(base, path)) { + else if (PropertyUtils.relativizeFile(base, path) != null) { + //mkleint: removed CollocationQuery.areCollocated() reference + // when AlwaysRelativeCQI gets removed the condition resolves to false more frequently. + // that might not be desirable. + // Fine, using a relative path to subproject. relativePath = PropertyUtils.relativizeFile(base, path); assert relativePath != null : "These dirs are not really collocated: " + base + " & " + path; @@ -352,6 +363,25 @@ }; } assert !Arrays.asList(values).contains(null) : "values=" + Arrays.toString(values) + " base=" + base + " path=" + path; // #119847 + return setPathPropertyImpl(propertyName, values, propertiesFiles); + } + + /** + * Helper method which in project properties file sets up property with + * the given name and with (possibly relative) path value. + * @return was there any change or not + */ + private boolean setPathProperty(String path, String propertyName) { + String[] propertiesFiles = new String[] { + AntProjectHelper.PROJECT_PROPERTIES_PATH + }; + String[] values = new String[] { + path + }; + return setPathPropertyImpl(propertyName, values, propertiesFiles); + } + + private boolean setPathPropertyImpl(String propertyName, String[] values, String[] propertiesFiles) { boolean metadataChanged = false; for (int i=0; i + * Acquires write access. + * @param path a file path to refer to (need not currently exist) + * @param expectedArtifactType the required {@link AntArtifact#getType} + * @return a string which can refer to that file somehow + * + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public String createForeignFileReferenceAsIs(final String filepath, final String expectedArtifactType) { + return createForeignFileReferenceImpl(filepath, expectedArtifactType, false); + } + + private String createForeignFileReferenceImpl(final String path, final String expectedArtifactType, final boolean performHeuristics) { + FileObject myProjDirFO = h.getProjectDirectory(); + File myProjDir = FileUtil.toFile(myProjDirFO); + final File normalizedFile = FileUtil.normalizeFile(PropertyUtils.resolveFile(myProjDir, path)); return ProjectManager.mutex().writeAccess(new Mutex.Action() { public String run() { - AntArtifact art = AntArtifactQuery.findArtifactFromFile(file); + AntArtifact art = AntArtifactQuery.findArtifactFromFile(normalizedFile); if (art != null && art.getType().equals(expectedArtifactType) && art.getProject() != null) { try { return createForeignFileReference(art); @@ -927,26 +986,51 @@ throw new AssertionError(iae); } } else { - String propertiesFile; - String path; File myProjDir = FileUtil.toFile(AntBasedProjectFactorySingleton.getProjectFor(h).getProjectDirectory()); - String fileID = file.getName(); + String fileID = normalizedFile.getName(); // if the file is folder then add to ID string also parent folder name, // i.e. if external source folder name is "src" the ID will // be a bit more selfdescribing, e.g. project-src in case // of ID for ant/project/src directory. - if (file.isDirectory() && file.getParentFile() != null) { - fileID = file.getParentFile().getName()+"-"+file.getName(); + if (normalizedFile.isDirectory() && normalizedFile.getParentFile() != null) { + fileID = normalizedFile.getParentFile().getName()+"-"+normalizedFile.getName(); } fileID = PropertyUtils.getUsablePropertyName(fileID); - String prop = findReferenceID(fileID, "file.reference.", file.getAbsolutePath()); // NOI18N + String prop = findReferenceID(fileID, "file.reference.", normalizedFile.getAbsolutePath()); // NOI18N if (prop == null) { - prop = generateUniqueID(fileID, "file.reference.", file.getAbsolutePath()); // NOI18N + prop = generateUniqueID(fileID, "file.reference.", normalizedFile.getAbsolutePath()); // NOI18N } - setPathProperty(myProjDir, file, "file.reference." + prop); + if (performHeuristics) { + setPathProperty(myProjDir, normalizedFile, "file.reference." + prop); + } else { + setPathProperty(path, "file.reference." + prop); + } return "${file.reference." + prop + '}'; // NOI18N } } + }); + } + + /** + * Create an Ant-interpretable string referring to a file on disk. Compared + * to {@link #createForeignFileReference} the file path does not have to be + * normalized (ie. it can be relative path to project base folder), no + * relativization or absolutization of path is done and + * reference to file is always stored in project properties. + *

+ * Acquires write access. + * @param path a file path to refer to (need not currently exist) + * @param property name of the property + * @return a string which can refer to that file somehow + * + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public String createExtraForeignFileReferenceAsIs(final String path, final String property) { + return ProjectManager.mutex().writeAccess(new Mutex.Action() { + public String run() { + setPathProperty(path, property); + return "${" + property + '}'; // NOI18N + } }); } @@ -1127,6 +1211,7 @@ private static final Pattern FOREIGN_FILE_REFERENCE = Pattern.compile("\\$\\{reference\\.([^.${}]+)\\.([^.${}]+)\\.([\\d&&[^.${}]]+)\\}"); // NOI18N private static final Pattern FOREIGN_FILE_REFERENCE_OLD = Pattern.compile("\\$\\{reference\\.([^.${}]+)\\.([^.${}]+)\\}"); // NOI18N private static final Pattern FOREIGN_PLAIN_FILE_REFERENCE = Pattern.compile("\\$\\{file\\.reference\\.([^${}]+)\\}"); // NOI18N + private static final Pattern LIBRARY_REFERENCE = Pattern.compile("\\$\\{libs\\.([^${}]+)\\.[^${}]+\\}"); // NOI18N /** * Try to find an AntArtifact object corresponding to a given @@ -1304,7 +1389,12 @@ File absolutePath = FileUtil.normalizeFile(PropertyUtils.resolveFile(originalPath, value)); //TODO: extra base dir relativization: - if (!CollocationQuery.areCollocated(absolutePath, projectDir)) { + + //mkleint: removed CollocationQuery.areCollocated() reference + // when AlwaysRelativeCQI gets removed the condition resolves to false more frequently. + // that might not be desirable. + String rel = PropertyUtils.relativizeFile(projectDir, absolutePath); + if (rel == null) { pubRemove.add(key); privAdd.put(key, absolutePath.getAbsolutePath()); } @@ -1338,8 +1428,13 @@ } //TODO: extra base dir relativization: - if (CollocationQuery.areCollocated(absolutePath, projectDir)) { - pubAdd.put(key, PropertyUtils.relativizeFile(projectDir, absolutePath)); + + //mkleint: removed CollocationQuery.areCollocated() reference + // when AlwaysRelativeCQI gets removed the condition resolves to false more frequently. + // that might not be desirable. + String rel = PropertyUtils.relativizeFile(projectDir, absolutePath); + if (rel != null) { + pubAdd.put(key, rel); } } @@ -1357,7 +1452,136 @@ h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, pub); h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, priv); } + + /** + * Create a reference to one volume of a library. + * @param library a library + * @param volumeType a legal volume type for that library + * @return substitutable Ant text suitable for inclusion in a properties file when also loading {@link AntProjectHelper#getProjectLibrariesPropertyProvider} + * @see #findLibrary + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public String createLibraryReference(Library library, String volumeType) { + if (library.getManager() == LibraryManager.getDefault()) { + if (h.isSharableProject()) { + throw new IllegalArgumentException("Project ["+ // NOI18N + h.getProjectDirectory()+ + "] is sharable and cannot reference global library "+library.getName()); // NOI18N + } + } else { + if (!ProjectLibraryProvider.isReachableLibrary(library, h)) { + throw new IllegalArgumentException("Project ["+ // NOI18N + h.getProjectDirectory()+ + "] cannot reference a library from "+library.getManager().getLocation()); // NOI18N + } + } + return "${libs." + library.getName() + "." + volumeType + "}"; // NOI18N + } + + /** + * Gets a library manager corresponding to library definition file referred to from this project. + * There is no guarantee that the manager is the same object from call to call + * even if the location remain the same; in particular, it is not guaranteed that + * the manager match that returned from {@link Library#getManager} for libraries added + * from {@link #createLibraryReference}. + * @return a library manager associated with project's libraries or null if project is + * not shared (will not include {@link LibraryManager#getDefault}) + * @see #createLibraryReference + * @see #findLibrary + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public LibraryManager getProjectLibraryManager() { + return ProjectLibraryProvider.getProjectLibraryManager(h); + } + + /** + * Gets a library manager of the given project. + * There is no guarantee that the manager is the same object from call to call + * even if the project is the same; in particular, it is not guaranteed that + * the manager match that returned from {@link Library#getManager} for libraries added + * from {@link #createLibraryReference}. + * @return a library manager associated with project's libraries or null if project is + * not shared (will not include {@link LibraryManager#getDefault}) + * {@link LibraryManager#getDefault}) + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public static LibraryManager getProjectLibraryManager(Project p) { + AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class); + if (aux != null) { + File libFile = ProjectLibraryProvider.getLibrariesLocation(aux, + FileUtil.toFile(p.getProjectDirectory())); + if (libFile != null) { + try { + return LibraryManager.forLocation(libFile.toURI().toURL()); + } catch (MalformedURLException e) { + // ok, no project manager + Logger.getLogger(ReferenceHelper.class.getName()).info( + "library manager cannot be found for "+libFile+". "+e.toString()); //NOI18N + } + } + } + return null; + } + + /** + * Copy global IDE library to sharable libraries definition associated with + * this project. Does nothing if project is not sharable. + * When a library with same name already exists in sharable location, the new one + * is copied with generated unique name. + * + *

Library creation is done under write access of ProjectManager.mutex(). + * + * @param lib global library; cannot be null + * @return newly created sharable version of library in case of sharable + * project or given global library in case of non-sharable project + * @throws java.io.IOException if there was problem copying files + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public Library copyLibrary(Library lib) throws IOException { + Parameters.notNull("lib", lib); + if (lib.getManager() != LibraryManager.getDefault()) { + throw new IllegalArgumentException("cannot copy non-global library "+lib.getManager().getLocation()); // NOI18N + } + if (!h.isSharableProject()) { + return lib; + } + File mainPropertiesFile = h.resolveFile(h.getLibrariesLocation()); + return ProjectLibraryProvider.copyLibrary(lib, mainPropertiesFile.toURI().toURL(), true); + } + /** + * Returns library import handler which imports global library to sharable + * one. See {@link LibraryChooser#showDialog} for usage of this handler. + * @return copy handler + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public LibraryChooser.LibraryImportHandler getLibraryChooserImportHandler() { + return new LibraryChooser.LibraryImportHandler() { + public Library importLibrary(Library library) throws IOException { + return copyLibrary(library); + } + }; + } + /** + * Tries to find a library by name in library manager associated with the project. + * It is not guaranteed that any returned library is an identical object to one which passed in to {@link #createLibraryReference}. + * @param name either a bare {@link Library#getName}, or a reference as created by {@link #createLibraryReference} + * @return the first library to be found matching that name, or null if not found + * @since org.netbeans.modules.project.ant/1 1.19 + */ + public Library findLibrary(String name) { + Matcher m = LIBRARY_REFERENCE.matcher(name); + if (m.matches()) { + name = m.group(1); + } + LibraryManager mgr = getProjectLibraryManager(); + if (mgr == null) { + return LibraryManager.getDefault().getLibrary(name); + } else { + return mgr.getLibrary(name); + } + } + /** * A raw reference descriptor representing a link to a foreign project * and some build artifact used from it. @@ -1638,7 +1862,11 @@ public String getID() { return artifactID; } - + + /** + * Get an extra properties used for target execution. + * @return a set of properties (may be empty but not null) + */ public Properties getProperties() { return props; } diff -r ffef4cca2ff4 project.ant/src/org/netbeans/spi/project/support/ant/SharabilityQueryImpl.java --- a/project.ant/src/org/netbeans/spi/project/support/ant/SharabilityQueryImpl.java Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/src/org/netbeans/spi/project/support/ant/SharabilityQueryImpl.java Thu Feb 21 14:37:31 2008 +0100 @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.List; import org.netbeans.api.queries.SharabilityQuery; +import org.netbeans.modules.project.ant.ProjectLibraryProvider; import org.netbeans.spi.queries.SharabilityQueryImplementation; import org.openide.util.WeakListeners; @@ -54,7 +55,7 @@ * Standard impl of {@link SharabilityQueryImplementation}. * @author Jesse Glick */ -final class SharabilityQueryImpl implements SharabilityQueryImplementation, PropertyChangeListener { +final class SharabilityQueryImpl implements SharabilityQueryImplementation, PropertyChangeListener, AntProjectListener { private final AntProjectHelper h; private final PropertyEvaluator eval; @@ -72,12 +73,13 @@ this.excludes = excludes; computeFiles(); eval.addPropertyChangeListener(WeakListeners.propertyChange(this, eval)); + h.addAntProjectListener(this); } /** Compute the absolute paths which are and are not sharable. */ private void computeFiles() { - String[] _includePaths = computeFrom(includes); - String[] _excludePaths = computeFrom(excludes); + String[] _includePaths = computeFrom(includes, false); + String[] _excludePaths = computeFrom(excludes, true); synchronized (this) { includePaths = _includePaths; excludePaths = _excludePaths; @@ -85,7 +87,7 @@ } /** Compute a list of absolute paths based on some abstract names. */ - private String[] computeFrom(String[] list) { + private String[] computeFrom(String[] list, boolean excludeProjectLibraryPrivate) { List result = new ArrayList(list.length); for (String s : list) { String val = eval.evaluate(s); @@ -93,6 +95,9 @@ File f = h.resolveFile(val); result.add(f.getAbsolutePath()); } + } + if (excludeProjectLibraryPrivate) { + result.addAll(ProjectLibraryProvider.getUnsharablePathsWithinProject(h)); } // XXX should remove overlaps somehow return result.toArray(new String[result.size()]); @@ -132,5 +137,11 @@ public void propertyChange(PropertyChangeEvent evt) { computeFiles(); } + + public void configurationXmlChanged(AntProjectEvent ev) { + computeFiles(); + } + + public void propertiesChanged(AntProjectEvent ev) {} } diff -r ffef4cca2ff4 project.ant/src/org/netbeans/spi/project/support/ant/SourcesHelper.java --- a/project.ant/src/org/netbeans/spi/project/support/ant/SourcesHelper.java Tue Jan 22 05:32:07 2008 +0000 +++ b/project.ant/src/org/netbeans/spi/project/support/ant/SourcesHelper.java Thu Feb 21 14:37:31 2008 +0100 @@ -193,11 +193,11 @@ if (owner != null && owner != p) { return false; } + File f = FileUtil.toFile(file); + if (f != null && SharabilityQuery.getSharability(f) == SharabilityQuery.NOT_SHARABLE) { + return false; + } // else MIXED, UNKNOWN, or SHARABLE; or not a disk file } - File f = FileUtil.toFile(file); - if (f != null && SharabilityQuery.getSharability(f) == SharabilityQuery.NOT_SHARABLE) { - return false; - } // else MIXED, UNKNOWN, or SHARABLE; or not a disk file return true; }