Index: apichanges.xml
===================================================================
RCS file: /cvs/ant/project/apichanges.xml,v
retrieving revision 1.1
diff -u -r1.1 apichanges.xml
--- apichanges.xml 14 Oct 2004 17:26:47 -0000 1.1
+++ apichanges.xml 9 Dec 2004 13:42:22 -0000
@@ -76,7 +76,21 @@
-
+
+
+ Make ReferencesHelper.createForeignFileReference produce relative links based on properties
+
+
+
+
+
+ ReferenceHelper should reuse external project folders as base
+ directories for references it creates where appropriate. The
+ new API allows to add/remove these base folders.
+
+
+
+
Index: manifest.mf
===================================================================
RCS file: /cvs/ant/project/manifest.mf,v
retrieving revision 1.5
diff -u -r1.5 manifest.mf
--- manifest.mf 9 Nov 2004 21:01:15 -0000 1.5
+++ manifest.mf 9 Dec 2004 13:42:22 -0000
@@ -1,5 +1,5 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.project.ant/0
-OpenIDE-Module-Specification-Version: 1.2
+OpenIDE-Module-Specification-Version: 1.3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/project/ant/Bundle.properties
Index: src/org/netbeans/spi/project/support/ant/ReferenceHelper.java
===================================================================
RCS file: /cvs/ant/project/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java,v
retrieving revision 1.20
diff -u -r1.20 ReferenceHelper.java
--- src/org/netbeans/spi/project/support/ant/ReferenceHelper.java 26 Oct 2004 18:44:30 -0000 1.20
+++ src/org/netbeans/spi/project/support/ant/ReferenceHelper.java 9 Dec 2004 13:42:22 -0000
@@ -19,9 +19,11 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.netbeans.api.project.Project;
@@ -84,6 +86,10 @@
*/
static final String REFS_NS = "http://www.netbeans.org/ns/ant-project-references/1"; // NOI18N
+ /** Set of property names which values can be used as additional base
+ * directories. */
+ private Set/**/ extraBaseDirectories = new HashSet();
+
private final AntProjectHelper h;
final PropertyEvaluator eval;
private final AuxiliaryConfiguration aux;
@@ -218,9 +224,14 @@
assert forProjPath != null : "These dirs are not really collocated: " + myProjDir + " & " + forProjDir;
propertiesFile = AntProjectHelper.PROJECT_PROPERTIES_PATH;
} else {
- // Use an absolute path.
- forProjPath = forProjDir.getAbsolutePath();
- propertiesFile = AntProjectHelper.PRIVATE_PROPERTIES_PATH;
+ forProjPath = relativizeFileToExtraBaseFolders(forProjDir);
+ if (forProjPath != null) {
+ propertiesFile = AntProjectHelper.PROJECT_PROPERTIES_PATH;
+ } else {
+ // Use an absolute path.
+ forProjPath = forProjDir.getAbsolutePath();
+ propertiesFile = AntProjectHelper.PRIVATE_PROPERTIES_PATH;
+ }
}
EditableProperties props = h.getProperties(propertiesFile);
String forProjPathProp = "project." + forProjName; // NOI18N
@@ -643,8 +654,13 @@
path = PropertyUtils.relativizeFile(myProjDir, file);
assert path != null : "expected relative path from " + myProjDir + " to " + file;
} else {
- propertiesFile = AntProjectHelper.PRIVATE_PROPERTIES_PATH;
- path = file.getAbsolutePath();
+ path = relativizeFileToExtraBaseFolders(file);
+ if (path != null) {
+ propertiesFile = AntProjectHelper.PROJECT_PROPERTIES_PATH;
+ } else {
+ propertiesFile = AntProjectHelper.PRIVATE_PROPERTIES_PATH;
+ path = file.getAbsolutePath();
+ }
}
EditableProperties props = h.getProperties(propertiesFile);
String fileID = file.getName();
@@ -669,7 +685,105 @@
}
});
}
+
+ /**
+ * Test whether file does not lie under an extra base folder and if it does
+ * then return string in form of "${extra.base}/remaining/path"; or null.
+ */
+ private String relativizeFileToExtraBaseFolders(File f) {
+ File base = FileUtil.toFile(h.getProjectDirectory());
+ String fileToRelativize = f.getAbsolutePath();
+ synchronized (extraBaseDirectories) {
+ Iterator it = extraBaseDirectories.iterator();
+ while (it.hasNext()) {
+ String prop = (String)it.next();
+ String path = eval.getProperty(prop);
+ File extraBase = PropertyUtils.resolveFile(base, path);
+ path = extraBase.getAbsolutePath();
+ if (!path.endsWith(File.separator)) {
+ path += File.separator;
+ }
+ if (fileToRelativize.startsWith(path)) {
+ return "${"+prop+"}/"+fileToRelativize.substring(path.length()).replace('\\', '/'); // NOI18N
+ }
+ }
+ }
+ return null;
+ }
+ /**
+ * Add extra folder which can be used as base directory (in addition to
+ * project base folder) for creating references. Duplicate property names
+ * are not allowed. Any newly created reference to a file lying under an
+ * extra base directory will be based on that property and will be stored in
+ * shared project proeprties.
+ * @param propertyName property name which value is path to folder which
+ * can be used as alternative project's base directory
+ * @since 1.3
+ */
+ public void addExtraBaseDirectory(String propertyName) {
+ assert propertyName != null && eval.getProperty(propertyName) != null;
+ synchronized (extraBaseDirectories) {
+ if (!extraBaseDirectories.add(propertyName)) {
+ throw new IllegalArgumentException("Already extra base directory property: "+propertyName); // NOI18N
+ }
+ }
+ }
+
+ /**
+ * Remove extra base directory. The base directory property had to be added
+ * by {@link #addExtraBaseDirectory} method call. At the time when this
+ * method is called the property must still exist and must be valid. This
+ * method will replace all references of the extra base directory property
+ * with its current value and if needed it may move such a property from
+ * shared project properties into the private properties.
+ * @param propertyName property name which was added by
+ * {@link #addExtraBaseDirectory} method.
+ * @since 1.3
+ */
+ public void removeExtraBaseDirectory(String propertyName) {
+ synchronized (extraBaseDirectories) {
+ if (!extraBaseDirectories.remove(propertyName)) {
+ throw new IllegalArgumentException("Non-existing extra base directory property: "+propertyName); // NOI18N
+ }
+ // substitute all references of removed extra base folder property with its value
+ String tag = "${"+propertyName+"}"; // NOI18N
+ // was extra base property defined in shared file or not:
+ boolean shared = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).containsKey(propertyName);
+ String value = eval.getProperty(propertyName);
+ EditableProperties propProj = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
+ EditableProperties propPriv = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
+ boolean modifiedProj = false;
+ boolean modifiedPriv = false;
+ Iterator it = propProj.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry)it.next();
+ String val = (String)entry.getValue();
+ int index;
+ if ((index = val.indexOf(tag)) != -1) {
+ val = val.substring(0, index) +value + val.substring(index+tag.length());
+ if (shared) {
+ // substitute extra base folder property with its value
+ entry.setValue(val);
+ modifiedProj = true;
+ } else {
+ // move property to private properties file
+ it.remove();
+ propPriv.put(entry.getKey(), val);
+ modifiedPriv = true;
+ modifiedProj = true;
+ }
+ }
+ }
+ if (modifiedProj) {
+ h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, propProj);
+ }
+ if (modifiedPriv) {
+ h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, propPriv);
+ }
+ }
+ }
+
/**
* Find reference ID (e.g. something you can then pass to RawReference
* as foreignProjectName) for the given property base name, prefix and path.
Index: test/unit/src/org/netbeans/spi/project/support/ant/ReferenceHelperTest.java
===================================================================
RCS file: /cvs/ant/project/test/unit/src/org/netbeans/spi/project/support/ant/ReferenceHelperTest.java,v
retrieving revision 1.13
diff -u -r1.13 ReferenceHelperTest.java
--- test/unit/src/org/netbeans/spi/project/support/ant/ReferenceHelperTest.java 26 Aug 2004 21:16:02 -0000 1.13
+++ test/unit/src/org/netbeans/spi/project/support/ant/ReferenceHelperTest.java 9 Dec 2004 13:42:22 -0000
@@ -702,4 +702,45 @@
assertNull("wrong target name, will not be found", art);
}
+ public void testAddRemoveExtraBaseDirectory() throws Exception {
+ // test foreign file reference for non-collocated jar under extra base folder
+ FileObject nonCollocatedLib = scratch.getFileObject("separate").createFolder("jars").createData("mylib.jar");
+ File f = FileUtil.toFile(nonCollocatedLib);
+ EditableProperties props = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
+ props.setProperty("externalSourceRoot", "../separate");
+ h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
+ r.addExtraBaseDirectory("externalSourceRoot");
+ String ref = r.createForeignFileReference(f, "jar");
+ assertEquals("foreign file reference created", "${file.reference.mylib.jar}", ref);
+ String refval = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(ref.substring(2, ref.length()-1));
+ assertEquals("reference is using extra base folder", "${externalSourceRoot}/jars/mylib.jar", refval);
+ assertEquals("reference is correctly evaluated", f, h.resolveFile(h.getStandardPropertyEvaluator().evaluate(refval)));
+ // test removal of extra base folder
+ r.removeExtraBaseDirectory("externalSourceRoot");
+ refval = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(ref.substring(2, ref.length()-1));
+ assertEquals("reference does not contain extra base folder", "../separate/jars/mylib.jar", refval);
+ assertEquals("reference is correctly evaluated", f, h.resolveFile(refval));
+
+ // the same test as above but with extra base folder defined in PRIVATE props
+ nonCollocatedLib = scratch.createFolder("separate2").createFolder("jars").createData("mylib2.jar");
+ f = FileUtil.toFile(nonCollocatedLib);
+ props = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
+ String absolutePath = FileUtil.toFile(scratch.getFileObject("separate2")).getAbsolutePath();
+ props.setProperty("externalSourceRootAbsolute", absolutePath);
+ h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, props);
+ r.addExtraBaseDirectory("externalSourceRootAbsolute");
+ ref = r.createForeignFileReference(f, "jar");
+ assertEquals("foreign file reference created", "${file.reference.mylib2.jar}", ref);
+ refval = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(ref.substring(2, ref.length()-1));
+ assertEquals("reference is using extra base folder", "${externalSourceRootAbsolute}/jars/mylib2.jar", refval);
+ assertEquals("reference is correctly evaluated", f, h.resolveFile(h.getStandardPropertyEvaluator().evaluate(refval)));
+ r.removeExtraBaseDirectory("externalSourceRootAbsolute");
+ refval = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(ref.substring(2, ref.length()-1));
+ assertNull("reference was removed from PROJECT_PROPERTIES_PATH", refval);
+ refval = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH).getProperty(ref.substring(2, ref.length()-1));
+ assertNotNull("reference was moved to PRIVATE_PROPERTIES_PATH", refval);
+ assertEquals("reference does not contain extra base folder", absolutePath+"/jars/mylib2.jar", refval);
+ assertEquals("reference is correctly evaluated", f, h.resolveFile(h.getStandardPropertyEvaluator().evaluate(refval)));
+ }
+
}