diff --git a/apisupport.harness/nbproject/project.properties b/apisupport.harness/nbproject/project.properties --- a/apisupport.harness/nbproject/project.properties +++ b/apisupport.harness/nbproject/project.properties @@ -70,6 +70,7 @@ org/netbeans/nbbuild/Branding*.class,\ org/netbeans/nbbuild/CreateModuleXML*.class,\ org/netbeans/nbbuild/CustomJavac*.class,\ + org/netbeans/nbbuild/ConvertClusterPath*.class,\ org/netbeans/nbbuild/FixDependencies*.class,\ org/netbeans/nbbuild/FixTestDependencies*.class,\ org/netbeans/nbbuild/JHIndexer*.class,\ @@ -86,6 +87,7 @@ org/netbeans/nbbuild/ModuleSelector*.class,\ org/netbeans/nbbuild/ModuleTracking*.class,\ org/netbeans/nbbuild/ParseProjectXml*.class,\ + org/netbeans/nbbuild/PathFileSet*.class,\ org/netbeans/nbbuild/ShorterPaths*.class,\ org/netbeans/nbbuild/SortSuiteModules*.class,\ org/netbeans/nbbuild/UpdateTracking*.class,\ diff --git a/apisupport.harness/release/build.xml b/apisupport.harness/release/build.xml --- a/apisupport.harness/release/build.xml +++ b/apisupport.harness/release/build.xml @@ -48,11 +48,58 @@ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -152,9 +199,9 @@ - - - + + + @@ -201,20 +248,27 @@ - + + + - + + + - + + + + diff --git a/apisupport.harness/release/jnlp.xml b/apisupport.harness/release/jnlp.xml --- a/apisupport.harness/release/jnlp.xml +++ b/apisupport.harness/release/jnlp.xml @@ -110,12 +110,13 @@ - + + - - - + + + @@ -126,7 +127,7 @@ - + @@ -171,7 +172,7 @@ permissions="${jnlp.permissions}" signjars="${jnlp.sign.jars}" > - + @@ -193,7 +194,7 @@ dir="${jnlp.master.dir}" codebase="${jnlp.platform.codebase}" > - + @@ -413,9 +414,10 @@ This target only works when run from inside the NetBeans IDE. - - - + + + + @@ -425,6 +427,7 @@ + diff --git a/apisupport.harness/release/run.xml b/apisupport.harness/release/run.xml --- a/apisupport.harness/release/run.xml +++ b/apisupport.harness/release/run.xml @@ -44,15 +44,25 @@ - + - - + + + + + + + + + + + + @@ -91,45 +101,23 @@ netbeans_extraclusters="${cluster}" - + - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - + + @@ -186,9 +174,9 @@ This target only works when run from inside the NetBeans IDE. - - - + + + @@ -198,6 +186,7 @@ + @@ -209,9 +198,9 @@ mainclass="org.netbeans.Main" > - - - + + + @@ -225,6 +214,7 @@ + diff --git a/apisupport.harness/release/suite.xml b/apisupport.harness/release/suite.xml --- a/apisupport.harness/release/suite.xml +++ b/apisupport.harness/release/suite.xml @@ -49,15 +49,61 @@ Using build harness in ${harness.dir} + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Suite in ${basedir} with target platform ${netbeans.dest.dir}, build cluster ${cluster}, and sorted modules ${modules.sorted} + Suite in ${basedir} with clusters ${cluster.path}, build cluster ${cluster}, and sorted modules ${modules.sorted} @@ -103,16 +149,20 @@ - + + + - - + + + - - + + + @@ -122,15 +172,17 @@ + + + + - - - + @@ -144,13 +196,14 @@ + - + @@ -159,38 +212,52 @@ Must have set at least an application name ('app.name') - - - - - + + + + + - - - - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - + + + + + + + + + @@ -226,22 +293,22 @@ + + + + + + + + + - - - - - - - - - - - - - + + + @@ -249,6 +316,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -269,20 +366,13 @@ - - - - - - - - - - - - - - + + + + + + + @@ -336,7 +426,9 @@ - + + + @@ -346,32 +438,46 @@ - + + + - + + + - + + + - + + + - + + + - + + + - + + + diff --git a/apisupport.harness/taskdefs.properties b/apisupport.harness/taskdefs.properties --- a/apisupport.harness/taskdefs.properties +++ b/apisupport.harness/taskdefs.properties @@ -54,3 +54,4 @@ fixtestdeps=org.netbeans.nbbuild.FixTestDependencies shorterpaths=org.netbeans.nbbuild.ShorterPaths custom-javac=org.netbeans.nbbuild.CustomJavac +convertclusterpath=org.netbeans.nbbuild.ConvertClusterPath \ No newline at end of file diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/ConvertClusterPath.java b/nbbuild/antsrc/org/netbeans/nbbuild/ConvertClusterPath.java new file mode 100644 --- /dev/null +++ b/nbbuild/antsrc/org/netbeans/nbbuild/ConvertClusterPath.java @@ -0,0 +1,165 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 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]" + * + * 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 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.nbbuild; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.util.FileUtils; + +/** + * Converts cluster.path from value specified in platform.properties + * to value usable by harness. + * + * TODO - describe actual changes + * + * @author Richard Michalsky + */ +public class ConvertClusterPath extends Task { + private String from; + private String id; + private String basedir; + private String to; + + /** + * Name of property to which stores + * @param to + */ + public void setTo(String to) { + this.to = to; + } + + public void setBasedir(String basedir) { + this.basedir = basedir; + } + + public void setFrom(String from) { + this.from = from; + } + + public void setId(String id) { + this.id = id; + } + + public ConvertClusterPath() { + + } + + @Override + public void execute() throws BuildException { + try { + if (from == null || from.length() == 0) + throw new BuildException("From parameter not specified.", getLocation()); + if ((id == null || id.length() == 0) + && (to == null && to.length() == 0)) + throw new BuildException("Either 'to' or 'id' parameter for converted path must be specified.", getLocation()); + if (basedir == null || basedir.length() == 0) + basedir = getProject().getBaseDir().getAbsolutePath(); + + log("Converting cluster.path from '" + from + "' relative to '" + basedir + "'.", Project.MSG_VERBOSE); + FileUtils fu = FileUtils.getFileUtils(); + Project fakeproj = new Project(); + fakeproj.setBasedir(basedir); + Path absPath = new Path(fakeproj, from); + log("Converted path: '" + absPath.toString() + "'.", Project.MSG_VERBOSE); + + // When cluster does not exist, try to find one with different number + final Pattern pat = Pattern.compile("(?:.*[\\\\/])?([^/\\\\]*)([0-9]+)[/\\\\]?$"); + Path convPath = new Path(fakeproj); + + for (Iterator it = absPath.iterator(); it.hasNext();) { + FileResource element = (FileResource) it.next(); + File f = element.getFile(); + String fPath = f.getAbsolutePath(); + final Matcher cm = pat.matcher(fPath); + if (f.exists()) { + if (! f.isDirectory()) + throw new BuildException("Only directories can be elements of cluster.path. Got '" + fPath + "'", getLocation()); + convPath.createPathElement().setLocation(f); + continue; + } + if (cm.matches()) { + // cluster is numbered, search for one with different number + File parent = f.getParentFile(); + + if (parent != null) { + File[] alternate = parent.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + Matcher am = pat.matcher(name); + return am.matches() && cm.group(1).equalsIgnoreCase(am.group(1)); + } + }); + if (alternate == null) { + Matcher matcher = Pattern.compile("^\\$\\{nbplatform\\.(.*)\\.netbeans\\.dest\\.dir\\}$").matcher(parent.getName()); + if (matcher.matches()) + throw new BuildException("Unknown platform name '" + matcher.group(1) + "'.", getLocation()); + else + throw new BuildException("Parent dir '" + parent.getAbsolutePath() + + "' does not exist.", getLocation()); + } + if (alternate.length > 0 && alternate[0].isDirectory()) { + log("Cluster '" + fPath + "' not found, using '" + alternate[0].getAbsolutePath() + "' instead.", Project.MSG_WARN); + convPath.createPathElement().setLocation(alternate[0]); + continue; + } + } + } + // no alternate cluster found + throw new BuildException("Cluster '" + fPath + "' not found.", getLocation()); + } + + if (id != null && id.length() > 0) + getProject().addReference(id, convPath); + if (to != null && to.length() > 0) + getProject().setProperty(to, convPath.toString()); + } catch (Exception e) { + throw new BuildException(e, getLocation()); + } + } + + +} diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/CreateModuleXML.java b/nbbuild/antsrc/org/netbeans/nbbuild/CreateModuleXML.java --- a/nbbuild/antsrc/org/netbeans/nbbuild/CreateModuleXML.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/CreateModuleXML.java @@ -105,13 +105,26 @@ private List autoloadNames = new ArrayList(10); private List eagerNames = new ArrayList(10); private List hiddenNames = new ArrayList(10); - + private String hiddenList; + + /** + * In addition to >hidden< nested fileset, list of hidden modules can + * be specified as comma-separated list in attribute 'hidden'. + * @param hiddenList + */ + public void setHidden(String hiddenList) { + // Only hidden parameters can be specified as list of absolute file paths, + // enabled, eager and autoload modules need relative path to create proper module xml + this.hiddenList = hiddenList; + } + public void execute() throws BuildException { if (xmldir == null) throw new BuildException("Must set xmldir attribute", getLocation()); if (!xmldir.exists ()) { if (!xmldir.mkdirs()) throw new BuildException("Cannot create directory " + xmldir, getLocation()); } - if (enabled.isEmpty() && disabled.isEmpty() && autoload.isEmpty() && eager.isEmpty() && hidden.isEmpty()) { + if (enabled.isEmpty() && disabled.isEmpty() && autoload.isEmpty() && eager.isEmpty() && hidden.isEmpty() + && hiddenList == null) { log("Warning: with no modules listed", Project.MSG_WARN); } for (FileSet fs : enabled) { @@ -129,6 +142,8 @@ for (FileSet fs : hidden) { scanModules(fs, false, false, false, true, hiddenNames); } + if (hiddenList != null && hiddenList.length() > 0) + scanModulesInList(hiddenList, false, false, false, true, hiddenNames); Collections.sort(enabledNames); Collections.sort(disabledNames); Collections.sort(autoloadNames); @@ -156,117 +171,136 @@ File dir = scan.getBasedir(); for (String kid : scan.getIncludedFiles()) { File module = new File(dir, kid); - if (!module.exists()) throw new BuildException("Module file does not exist: " + module, getLocation()); - if (!module.getName().endsWith(".jar")) throw new BuildException("Only *.jar may be listed, check the fileset: " + module, getLocation()); + scanOneModule(module, kid, isEnabled, isAutoload, isEager, isHidden, names); + } + } + + private void scanModulesInList(String modulesList, boolean isEnabled, boolean isAutoload, + boolean isEager, boolean isHidden, List names) throws BuildException { + String[] modules = modulesList.split(","); + for (String modulePath : modules) { + File module = new File(modulePath); + scanOneModule(module, null, isEnabled, isAutoload, isEager, isHidden, names); + } + } + + private void scanOneModule(File module, String kid, boolean isEnabled,boolean isAutoload, boolean isEager, boolean isHidden, List names) throws BuildException { + if (!module.exists()) { + throw new BuildException("Module file does not exist: " + module, getLocation()); + } + if (!module.getName().endsWith(".jar")) { + throw new BuildException("Only *.jar may be listed, check the fileset: " + module, getLocation()); + } + try { + JarFile jar = new JarFile(module); try { - JarFile jar = new JarFile(module); - try { - Manifest m = jar.getManifest(); - Attributes attr = m.getMainAttributes(); - String codename = attr.getValue("OpenIDE-Module"); - if (codename == null) { - throw new BuildException("Missing manifest tag OpenIDE-Module; " + module + " is not a module", getLocation()); + Manifest m = jar.getManifest(); + Attributes attr = m.getMainAttributes(); + String codename = attr.getValue("OpenIDE-Module"); + if (codename == null) { + throw new BuildException("Missing manifest tag OpenIDE-Module; " + module + " is not a module", getLocation()); + } + if (codename.endsWith(" ") || codename.endsWith("\t")) { + // #62887 + throw new BuildException("Illegal trailing space in OpenIDE-Module value from " + module, getLocation()); + } + int idx = codename.lastIndexOf('/'); + String codenamebase; + int rel; + if (idx == -1) { + codenamebase = codename; + rel = -1; + } else { + codenamebase = codename.substring(0, idx); + try { + rel = Integer.parseInt(codename.substring(idx + 1)); + } catch (NumberFormatException e) { + throw new BuildException("Invalid OpenIDE-Module '" + codename + "' in " + module, getLocation()); } - if (codename.endsWith(" ") || codename.endsWith("\t")) { // #62887 - throw new BuildException("Illegal trailing space in OpenIDE-Module value from " + module, getLocation()); - } - int idx = codename.lastIndexOf('/'); - String codenamebase; - int rel; - if (idx == -1) { - codenamebase = codename; - rel = -1; - } else { - codenamebase = codename.substring(0, idx); + } + File xml = new File(xmldir, codenamebase.replace('.', '-') + ".xml"); + if (xml.exists()) { + // XXX should check that the old file actually matches what we would have written + log("Will not overwrite " + xml + "; skipping...", Project.MSG_VERBOSE); + return; + } + String displayname = attr.getValue("OpenIDE-Module-Name"); + if (displayname == null) { + String bundle = attr.getValue("OpenIDE-Module-Localizing-Bundle"); + if (bundle != null) { + // Display name actually found in a bundle, not manifest. + ZipEntry entry = jar.getEntry(bundle); + InputStream is; + if (entry != null) { + is = jar.getInputStream(entry); + } else { + File moduleloc = new File(new File(module.getParentFile(), "locale"), module.getName()); + if (!moduleloc.isFile()) { + throw new BuildException("Expecting localizing bundle: " + bundle + " in: " + module); + } + JarFile jarloc = new JarFile(moduleloc); + try { + ZipEntry entry2 = jarloc.getEntry(bundle); + if (entry2 == null) { + throw new BuildException("Expecting localizing bundle: " + bundle + " in: " + module); + } + is = jarloc.getInputStream(entry2); + } finally { + jarloc.close(); + } + } try { - rel = Integer.parseInt(codename.substring(idx + 1)); - } catch (NumberFormatException e) { - throw new BuildException("Invalid OpenIDE-Module '" + codename + "' in " + module, getLocation()); + Properties p = new Properties(); + p.load(is); + displayname = p.getProperty("OpenIDE-Module-Name"); + } finally { + is.close(); } } - File xml = new File(xmldir, codenamebase.replace('.', '-') + ".xml"); - if (xml.exists()) { - // XXX should check that the old file actually matches what we would have written - log("Will not overwrite " + xml + "; skipping...", Project.MSG_VERBOSE); - continue; + } + if (displayname == null) { + displayname = codename; + } + names.add(displayname); + String spec = attr.getValue("OpenIDE-Module-Specification-Version"); + if (isHidden) { + File h = new File(xml.getParentFile(), xml.getName() + "_hidden"); + h.createNewFile(); + } else { + OutputStream os = new FileOutputStream(xml); + try { + PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8")); + // Please make sure formatting matches what the IDE actually spits + // out; it could matter. + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(" " + isAutoload + ""); + pw.println(" " + isEager + ""); + if (!isAutoload && !isEager) { + pw.println(" " + isEnabled + ""); + } + pw.println(" " + kid.replace(File.separatorChar, '/') + ""); + if (rel != -1) { + pw.println(" " + rel + ""); + } + pw.println(" false"); + if (spec != null) { + pw.println(" " + spec + ""); + } + pw.println(""); + pw.flush(); + pw.close(); + } finally { + os.close(); } - String displayname = attr.getValue("OpenIDE-Module-Name"); - if (displayname == null) { - String bundle = attr.getValue("OpenIDE-Module-Localizing-Bundle"); - if (bundle != null) { - // Display name actually found in a bundle, not manifest. - ZipEntry entry = jar.getEntry(bundle); - InputStream is; - if (entry != null) { - is = jar.getInputStream(entry); - } else { - File moduleloc = new File(new File(module.getParentFile(), "locale"), module.getName()); - if (! moduleloc.isFile()) { - throw new BuildException("Expecting localizing bundle: " + bundle + " in: " + module); - } - JarFile jarloc = new JarFile(moduleloc); - try { - ZipEntry entry2 = jarloc.getEntry(bundle); - if (entry2 == null) { - throw new BuildException("Expecting localizing bundle: " + bundle + " in: " + module); - } - is = jarloc.getInputStream(entry2); - } finally { - jarloc.close(); - } - } - try { - Properties p = new Properties(); - p.load(is); - displayname = p.getProperty("OpenIDE-Module-Name"); - } finally { - is.close(); - } - } - } - if (displayname == null) displayname = codename; - names.add(displayname); - String spec = attr.getValue("OpenIDE-Module-Specification-Version"); - - if (isHidden) { - File h = new File(xml.getParentFile(), xml.getName() + "_hidden"); - h.createNewFile(); - } else { - OutputStream os = new FileOutputStream(xml); - try { - PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8")); - // Please make sure formatting matches what the IDE actually spits - // out; it could matter. - pw.println(""); - pw.println(""); - pw.println(""); - pw.println(" " + isAutoload + ""); - pw.println(" " + isEager + ""); - if (!isAutoload && !isEager) { - pw.println(" " + isEnabled + ""); - } - pw.println(" " + kid.replace(File.separatorChar, '/') + ""); - if (rel != -1) { - pw.println(" " + rel + ""); - } - pw.println(" false"); - if (spec != null) { - pw.println(" " + spec + ""); - } - pw.println(""); - pw.flush(); - pw.close(); - } finally { - os.close(); - } - } - } finally { - jar.close(); } - } catch (IOException ioe) { - throw new BuildException("Caught while processing " + module + ": " + ioe, ioe, getLocation()); + } finally { + jar.close(); } + } catch (IOException ioe) { + throw new BuildException("Caught while processing " + module + ": " + ioe, ioe, getLocation()); } } diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/MakeJNLP.java b/nbbuild/antsrc/org/netbeans/nbbuild/MakeJNLP.java --- a/nbbuild/antsrc/org/netbeans/nbbuild/MakeJNLP.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/MakeJNLP.java @@ -73,7 +73,9 @@ import org.apache.tools.ant.taskdefs.SignJar; import org.apache.tools.ant.taskdefs.Zip; import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.ResourceCollection; import org.apache.tools.ant.types.ZipFileSet; +import org.apache.tools.ant.types.resources.FileResource; import org.xml.sax.SAXException; /** Generates JNLP files for signed versions of the module JAR files. @@ -82,16 +84,20 @@ */ public class MakeJNLP extends Task { /** the files to work on */ - private FileSet files; + private ResourceCollection files; private SignJar signTask; public FileSet createModules() throws BuildException { - if (files != null) throw new BuildException("modules can be created just once"); - files = new FileSet(); - return files; + addConfigured(new FileSet()); + return (FileSet) files; } - + + public void addConfigured(ResourceCollection rc) throws BuildException { + if (files != null) throw new BuildException("modules can be specified just once"); + files = rc; + } + private SignJar getSignTask() { if (signTask == null) { signTask = (SignJar)getProject().createTask("signjar"); @@ -226,10 +232,10 @@ } } - DirectoryScanner scan = files.getDirectoryScanner(getProject()); - for (String f : scan.getIncludedFiles()) { - File jar = new File (files.getDir(getProject()), f); - + for (Iterator fileIt = files.iterator(); fileIt.hasNext();) { + FileResource fr = (FileResource) fileIt.next(); + File jar = fr.getFile(); + if (!jar.canRead()) { throw new BuildException("Cannot read file: " + jar); } diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/MakeMasterJNLP.java b/nbbuild/antsrc/org/netbeans/nbbuild/MakeMasterJNLP.java --- a/nbbuild/antsrc/org/netbeans/nbbuild/MakeMasterJNLP.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/MakeMasterJNLP.java @@ -44,10 +44,13 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.Iterator; import java.util.jar.JarFile; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.types.resources.FileResource; /** Generates JNLP files for signed versions of the module JAR files. * @@ -55,13 +58,17 @@ */ public class MakeMasterJNLP extends Task { /** the files to work on */ - private FileSet files; + private ResourceCollection files; public FileSet createModules() throws BuildException { - if (files != null) throw new BuildException("modules can be created just once"); - files = new FileSet(); - return files; + addConfigured(new FileSet()); + return (FileSet) files; + } + + public void addConfigured(ResourceCollection rc) throws BuildException { + if (files != null) throw new BuildException("modules can be specified just once"); + files = rc; } private File target; @@ -86,9 +93,10 @@ } private void generateFiles() throws IOException, BuildException { - for (String nm : files.getDirectoryScanner(getProject()).getIncludedFiles()) { - File jar = new File (files.getDir(getProject()), nm); - + for (Iterator fileIt = files.iterator(); fileIt.hasNext();) { + FileResource fr = (FileResource) fileIt.next(); + File jar = fr.getFile(); + if (!jar.canRead()) { throw new BuildException("Cannot read file: " + jar); } diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/ModuleListParser.java b/nbbuild/antsrc/org/netbeans/nbbuild/ModuleListParser.java --- a/nbbuild/antsrc/org/netbeans/nbbuild/ModuleListParser.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/ModuleListParser.java @@ -500,20 +500,25 @@ /** * Find all modules in a binary build, possibly from cache. */ - private static Map scanBinaries(Project project, File build) throws IOException { - Map entries = BINARY_SCAN_CACHE.get(build); - if (entries == null) { - if (project != null) { - project.log("Scanning for modules in " + build); + private static Map scanBinaries(Project project, File[] clusters) throws IOException { + Map allEntries = new HashMap(); + + for (File cluster : clusters) { + Map entries = BINARY_SCAN_CACHE.get(cluster); + if (entries == null) { + if (project != null) { + project.log("Scanning for modules in " + cluster); + } + entries = new HashMap(); + doScanBinaries(cluster, entries); + if (project != null) { + project.log("Found modules: " + entries.keySet(), Project.MSG_VERBOSE); + } + BINARY_SCAN_CACHE.put(cluster, entries); } - entries = new HashMap(); - doScanBinaries(build, entries); - if (project != null) { - project.log("Found modules: " + entries.keySet(), Project.MSG_VERBOSE); - } - BINARY_SCAN_CACHE.put(build, entries); + allEntries.putAll(entries); } - return entries; + return allEntries; } private static final String[] MODULE_DIRS = { @@ -528,14 +533,9 @@ * Checks modules/{,autoload/,eager/}*.jar as well as well-known core/*.jar and lib/boot.jar in each cluster. * XXX would be slightly more precise to check config/Modules/*.xml rather than scan for module JARs. */ - private static void doScanBinaries(File build, Map entries) throws IOException { - File[] clusters = build.listFiles(); - if (clusters == null) { - throw new IOException("Cannot examine dir " + build); - } - for (int i = 0; i < clusters.length; i++) { + private static void doScanBinaries(File cluster, Map entries) throws IOException { for (int j = 0; j < MODULE_DIRS.length; j++) { - File dir = new File(clusters[i], MODULE_DIRS[j].replace('/', File.separatorChar)); + File dir = new File(cluster, MODULE_DIRS[j].replace('/', File.separatorChar)); if (!dir.isDirectory()) { continue; } @@ -577,7 +577,7 @@ String moduleDependencies = attr.getValue("OpenIDE-Module-Module-Dependencies"); - Entry entry = new Entry(codenamebase, m, exts,dir, null, null, clusters[i].getName(), + Entry entry = new Entry(codenamebase, m, exts,dir, null, null, cluster.getName(), parseRuntimeDependencies(moduleDependencies), Collections.emptyMap()); if (entries.containsKey(codenamebase)) { throw new IOException("Duplicated module " + codenamebase + ": found in " + entries.get(codenamebase) + " and " + entry); @@ -589,7 +589,6 @@ } } } - } } private static Map scanSuiteSources(Map properties, Project project) throws IOException { @@ -666,7 +665,8 @@ * Properties interpreted: *
    *
  1. ${nb_all} - location of NB sources (used only for netbeans.org modules) - *
  2. ${netbeans.dest.dir} - location of NB build + *
  3. ${netbeans.dest.dir} - location of NB build (used only for NB.org modules) + *
  4. ${cluster.path} - location of clusters to build against (used only for suite and standalone modules) *
  5. ${basedir} - directory of the project initiating the scan (most significant for standalone modules) *
  6. ${suite.dir} - directory of the suite (used only for suite modules) *
  7. ${nb.cluster.TOKEN} - list of module paths included in cluster TOKEN (comma-separated) (used only for netbeans.org modules) @@ -679,23 +679,46 @@ */ public ModuleListParser(Map properties, int type, Project project) throws IOException { String nball = properties.get("nb_all"); - String buildS = properties.get("netbeans.dest.dir"); File basedir = new File(properties.get("basedir")); - if (buildS == null) { - throw new IOException("No definition of netbeans.dest.dir in " + basedir); - } - // Resolve against basedir, and normalize ../ sequences and so on in case they are used. - // Neither operation is likely to be needed, but just in case. - File build = FileUtils.getFileUtils().normalize(FileUtils.getFileUtils().resolveFile(basedir, buildS).getAbsolutePath()); - if (!build.isDirectory()) { - throw new IOException("No such netbeans.dest.dir: " + build); - } + final FileUtils fu = FileUtils.getFileUtils(); + if (type != ParseProjectXml.TYPE_NB_ORG) { + // add extra clusters + String suiteDirS = properties.get("suite.dir"); + boolean hasSuiteDir = suiteDirS != null && suiteDirS.length() > 0; + String clusterPath = properties.get("cluster.path"); + File[] clusters = null; + + if (clusterPath != null) { + String[] clustersS; + if (hasSuiteDir) { + // resolve suite modules against fake suite project + Project fakeproj = new Project(); + fakeproj.setBaseDir(new File(suiteDirS)); + clustersS = Path.translatePath(fakeproj, clusterPath); + } else { + clustersS = Path.translatePath(project, clusterPath); + } + clusters = new File[clustersS.length]; + if (clustersS != null && clustersS.length > 0) { + for (int j = 0; j < clustersS.length; j++) { + File cluster = new File(clustersS[j]); + if (! cluster.isDirectory()) { + throw new IOException("No such cluster " + cluster + " referred to from ${cluster.path}: " + clusterPath); + } + clusters[j] = cluster; + } + } + } + + if (clusters == null || clusters.length == 0) + throw new IOException("Invalid ${cluster.path}: " + clusterPath); + // External module. if (nball != null && project != null) { project.log("You must *not* declare or for a netbeans.org module in " + basedir + "; fix project.xml to use the /2 schema", Project.MSG_WARN); } - entries = scanBinaries(project, build); + entries = scanBinaries(project, clusters); if (type == ParseProjectXml.TYPE_SUITE) { entries.putAll(scanSuiteSources(properties, project)); } else { @@ -705,12 +728,29 @@ } } else { // netbeans.org module. + String buildS = properties.get("netbeans.dest.dir"); + if (buildS == null) { + throw new IOException("No definition of netbeans.dest.dir in " + basedir); + } + // Resolve against basedir, and normalize ../ sequences and so on in case they are used. + // Neither operation is likely to be needed, but just in case. + File build = fu.normalize(fu.resolveFile(basedir, buildS).getAbsolutePath()); + if (!build.isDirectory()) { + throw new IOException("No such netbeans.dest.dir: " + build); + } + + // expand clusters in build + File[] clusters = build.listFiles(); + if (clusters == null) { + throw new IOException("Cannot examine dir " + build); + } + if (nball == null) { throw new IOException("You must declare either or for an external module in " + new File(properties.get("basedir"))); } if (!build.equals(new File(new File(nball, "nbbuild"), "netbeans"))) { // Potentially orphaned module to be built against specific binaries, plus perhaps other source deps. - entries = scanBinaries(project, build); + entries = scanBinaries(project, clusters); // Add referenced module in case it does not appear otherwise. Entry e = scanStandaloneSource(properties, project); if (e != null) { diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/ParseProjectXml.java b/nbbuild/antsrc/org/netbeans/nbbuild/ParseProjectXml.java --- a/nbbuild/antsrc/org/netbeans/nbbuild/ParseProjectXml.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/ParseProjectXml.java @@ -54,9 +54,11 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -73,6 +75,10 @@ import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.util.CollectionUtils; +import org.apache.tools.ant.util.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; @@ -621,7 +627,7 @@ } private String implementationVersionOf(ModuleListParser modules, String cnb) throws BuildException { - File jar = computeClasspathModuleLocation(modules, cnb, null, null, null); + File jar = computeClasspathModuleLocation(modules, cnb, null, null); if (!jar.isFile()) { throw new BuildException("No such classpath entry: " + jar, getLocation()); } @@ -776,15 +782,15 @@ private String computeClasspath(Document pDoc, ModuleListParser modules, Dep[] deps, boolean runtime) throws BuildException, IOException, SAXException { String myCnb = getCodeNameBase(pDoc); StringBuffer cp = new StringBuffer(); - String includedClustersProp = getProject().getProperty("enabled.clusters"); - Set includedClusters = includedClustersProp != null ? - new HashSet(Arrays.asList(includedClustersProp.split(" *, *"))) : - null; - // Compatibility: - String excludedClustersProp = getProject().getProperty("disabled.clusters"); - Set excludedClusters = excludedClustersProp != null ? - new HashSet(Arrays.asList(excludedClustersProp.split(" *, *"))) : - null; + Path clusterPathS = (Path) getProject().getReference("cluster.path.id"); + Set clusterPath = null; + if (clusterPathS != null) { + clusterPath = new HashSet(); + for (Iterator it = clusterPathS.iterator(); it.hasNext();) { + File oneCluster = ((FileResource) it.next()).getFile(); + clusterPath.add(oneCluster); + } + } String excludedModulesProp = getProject().getProperty("disabled.modules"); Set excludedModules = excludedModulesProp != null ? new HashSet(Arrays.asList(excludedModulesProp.split(" *, *"))) : @@ -794,7 +800,7 @@ continue; } String cnb = dep.codenamebase; - File depJar = computeClasspathModuleLocation(modules, cnb, includedClusters, excludedClusters, excludedModules); + File depJar = computeClasspathModuleLocation(modules, cnb, clusterPath, excludedModules); Attributes attr; if (!depJar.isFile()) { @@ -819,7 +825,7 @@ additions.add(depJar); if (runtime) { Set skipCnb = new HashSet(); - addRecursiveDeps(additions, modules, cnb, includedClusters, excludedClusters, excludedModules, skipCnb); + addRecursiveDeps(additions, modules, cnb, clusterPath, excludedModules, skipCnb); } // #52354: look for s in dependent modules. @@ -862,16 +868,15 @@ return cp.toString(); } - private void addRecursiveDeps(List additions, ModuleListParser modules, String cnb, Set includedClusters, - Set excludedClusters, Set excludedModules, Set skipCnb - ) { + private void addRecursiveDeps(List additions, ModuleListParser modules, String cnb, + Set clusterPath, Set excludedModules, Set skipCnb) { if (!skipCnb.add(cnb)) { return; } log("Processing for recursive deps: " + cnb, Project.MSG_VERBOSE); // NO18N for (String nextModule : modules.findByCodeNameBase(cnb).getRuntimeDependencies()) { log(" Added dep: " + nextModule, Project.MSG_VERBOSE); // NO18N - File depJar = computeClasspathModuleLocation(modules, nextModule, includedClusters, excludedClusters, excludedModules); + File depJar = computeClasspathModuleLocation(modules, nextModule, clusterPath, excludedModules); if (!depJar.isFile()) { log("No such classpath entry: " + depJar, Project.MSG_WARN); @@ -890,28 +895,28 @@ } } - addRecursiveDeps(additions, modules, nextModule, includedClusters, excludedClusters, excludedModules, skipCnb); + addRecursiveDeps(additions, modules, nextModule, clusterPath, excludedModules, skipCnb); } } private File computeClasspathModuleLocation(ModuleListParser modules, String cnb, - Set includedClusters, Set excludedClusters, Set excludedModules) throws BuildException { + Set clusterPath, Set excludedModules) throws BuildException { ModuleListParser.Entry module = modules.findByCodeNameBase(cnb); if (module == null) { throw new BuildException("No dependent module " + cnb, getLocation()); } - String cluster = module.getClusterName(); - if (cluster != null) { // #68716 - if ((includedClusters != null && !includedClusters.isEmpty() && ! ModuleSelector.clusterMatch(includedClusters, cluster)) || - ((includedClusters == null || includedClusters.isEmpty()) && excludedClusters != null && excludedClusters.contains(cluster))) { - throw new BuildException("The module " + cnb + " cannot be compiled against because it is part of the cluster " + cluster + - " which has been excluded from the target platform in your suite configuration", getLocation()); - } - if (excludedModules != null && excludedModules.contains(cnb)) { // again #68716 - throw new BuildException("Module " + cnb + " excluded from the target platform", getLocation()); - } + File jar = module.getJar(); + if (jar == null) return null; + + if (clusterPath != null) { + File clusterF = jar.getParentFile().getParentFile(); + if (! clusterPath.contains(clusterF)) + throw new BuildException("The module " + cnb + " cannot be compiled against because it is part of the cluster " + + clusterF + + " which is not part of cluster.path in your suite configuration.\n\n" + + "Cluster.path is: " + clusterPath, getLocation()); } - return module.getJar(); + return jar; } final class TestDeps { @@ -967,6 +972,7 @@ // no cluster name is specified for standalone or module in module suite cluster = "cluster"; } + // TODO - path probably composed wrongly with respect to cluster.path return ParseProjectXml.cachedTestDistLocation + sep + testtype + sep + cluster + sep + cnb.replace('.','-'); } @@ -1177,6 +1183,7 @@ if (cluster == null) { cluster = "cluster"; } + // TODO - path probably composed wrongly with respect to cluster.path return ParseProjectXml.cachedTestDistLocation + sep + testType + sep + cluster + sep + entry.getCnb().replace('.', '-') + sep + "tests.jar"; } diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/PathFileSet.java b/nbbuild/antsrc/org/netbeans/nbbuild/PathFileSet.java new file mode 100644 --- /dev/null +++ b/nbbuild/antsrc/org/netbeans/nbbuild/PathFileSet.java @@ -0,0 +1,269 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 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]" + * + * 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 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.nbbuild; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.types.selectors.AbstractSelectorContainer; +import org.apache.tools.ant.types.selectors.AndSelector; +import org.apache.tools.ant.types.selectors.ContainsRegexpSelector; +import org.apache.tools.ant.types.selectors.ContainsSelector; +import org.apache.tools.ant.types.selectors.DateSelector; +import org.apache.tools.ant.types.selectors.DependSelector; +import org.apache.tools.ant.types.selectors.DepthSelector; +import org.apache.tools.ant.types.selectors.DifferentSelector; +import org.apache.tools.ant.types.selectors.ExtendSelector; +import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.FilenameSelector; +import org.apache.tools.ant.types.selectors.MajoritySelector; +import org.apache.tools.ant.types.selectors.NoneSelector; +import org.apache.tools.ant.types.selectors.NotSelector; +import org.apache.tools.ant.types.selectors.OrSelector; +import org.apache.tools.ant.types.selectors.PresentSelector; +import org.apache.tools.ant.types.selectors.SelectSelector; +import org.apache.tools.ant.types.selectors.SelectorContainer; +import org.apache.tools.ant.types.selectors.SizeSelector; +import org.apache.tools.ant.types.selectors.TypeSelector; +import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; + +/** + * + * @author Richard Michalsky + */ +public class PathFileSet extends DataType implements ResourceCollection, SelectorContainer { + private Path clusterPath; + private String include; + private AbstractSelectorContainer selectors = new AbstractSelectorContainer() {}; + private ArrayList files; + + /** + * Optional include pattern for filtering files. The same as fileset's nested >include< tag. + * + * Note that pattern is matched against relative path starting at each pathelement. + * E.g. when there is file /a/b/c/d.txt, it will be included in result + * of: + *
    <pathfileset include="c/**.txt property="output">
    +     *      <path path="/a/b"/>
    +     * </pathfileset>
    + * and it won't be included in result of: + *
    <pathfileset include="b/**.txt property="output">
    +     *      <path path="/a/b"/>
    +     * </pathfileset>
    + * @param include + */ + public void setInclude(String include) { + this.include = include; + } + + private List paths = new ArrayList(); + + /** + * Adds path in classpath notation. Searched in addition + * to any nested paths. + * @param stringPath + */ + public void setPath(Path stringPath) { + addPath(stringPath); + } + + /** + * Elements of nested paths are used as basedirs for fileset. + * @param clusterPath + */ + public void addPath(Path clusterPath) { + paths.add(clusterPath); + } + + // SelectorContainer impl. + + public Enumeration selectorElements() { + return selectors.selectorElements(); + } + + public int selectorCount() { + return selectors.selectorCount(); + } + + public boolean hasSelectors() { + return selectors.hasSelectors(); + } + + public FileSelector[] getSelectors(Project p) { + return selectors.getSelectors(p); + } + + public void appendSelector(FileSelector selector) { + selectors.appendSelector(selector); + } + + public void addType(TypeSelector selector) { + selectors.addType(selector); + } + + public void addSize(SizeSelector selector) { + selectors.addSize(selector); + } + + public void addSelector(SelectSelector selector) { + selectors.addSelector(selector); + } + + public void addPresent(PresentSelector selector) { + selectors.addPresent(selector); + } + + public void addOr(OrSelector selector) { + selectors.addOr(selector); + } + + public void addNot(NotSelector selector) { + selectors.addNot(selector); + } + + public void addNone(NoneSelector selector) { + selectors.addNone(selector); + } + + public void addModified(ModifiedSelector selector) { + selectors.addModified(selector); + } + + public void addMajority(MajoritySelector selector) { + selectors.addMajority(selector); + } + + public void addFilename(FilenameSelector selector) { + selectors.addFilename(selector); + } + + public void addDifferent(DifferentSelector selector) { + selectors.addDifferent(selector); + } + + public void addDepth(DepthSelector selector) { + selectors.addDepth(selector); + } + + public void addDepend(DependSelector selector) { + selectors.addDepend(selector); + } + + public void addDate(DateSelector selector) { + selectors.addDate(selector); + } + + public void addCustom(ExtendSelector selector) { + selectors.addCustom(selector); + } + + public void addContainsRegexp(ContainsRegexpSelector selector) { + selectors.addContainsRegexp(selector); + } + + public void addContains(ContainsSelector selector) { + selectors.addContains(selector); + } + + public void addAnd(AndSelector selector) { + selectors.addAnd(selector); + } + + public void add(FileSelector selector) { + selectors.add(selector); + } + + // ResourceCollection impl. + + public Iterator iterator() { + initFiles(); + return files.iterator(); + } + + public int size() { + initFiles(); + return files.size(); + } + + public boolean isFilesystemOnly() { + return true; + } + + private void initFiles() throws BuildException { + if (files != null) return; + try { + files = new ArrayList(); + log("ClusterPathSet: scanning " + paths.size() + " paths.", Project.MSG_VERBOSE); + DirectoryScanner scanner = new DirectoryScanner(); + if (paths.size() == 0) { + throw new BuildException("No path specified"); + } + for (Path path : paths) { + String[] includedClusters = path.list(); + for (String clusterName : includedClusters) { + log("ClusterPathSet: scanning pathelement '" + clusterName + "'.", Project.MSG_VERBOSE); + scanner.setBasedir(clusterName); + scanner.setSelectors(selectors.getSelectors(getProject())); + if (include != null) { + scanner.setIncludes(new String[]{include}); + } + scanner.scan(); + log("ClusterPathSet: " + scanner.getIncludedFilesCount() + " files found.", Project.MSG_VERBOSE); + for (String relFile : scanner.getIncludedFiles()) { + files.add(new FileResource(scanner.getBasedir(), relFile)); + } + } + } + } catch (BuildException ex) { + throw ex; + } catch (Exception ex) { + throw new BuildException(ex); + } + } + +} diff --git a/nbbuild/default.xml b/nbbuild/default.xml --- a/nbbuild/default.xml +++ b/nbbuild/default.xml @@ -108,6 +108,11 @@ + + @@ -128,6 +133,15 @@ + + + + + + + + + diff --git a/nbbuild/templates/common.xml b/nbbuild/templates/common.xml --- a/nbbuild/templates/common.xml +++ b/nbbuild/templates/common.xml @@ -340,7 +340,10 @@ - + + + + @@ -486,7 +489,7 @@ extralibs="extra.test.libs.short" extralibsdir="${extra.test.libs.dir}" testproperties="${test.@{test.type}.out.folder}/test.properties"> - + diff --git a/nbbuild/test/unit/src/org/netbeans/nbbuild/PathFileSetTest.java b/nbbuild/test/unit/src/org/netbeans/nbbuild/PathFileSetTest.java new file mode 100644 --- /dev/null +++ b/nbbuild/test/unit/src/org/netbeans/nbbuild/PathFileSetTest.java @@ -0,0 +1,241 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 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]" + * + * 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 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.nbbuild; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.StringTokenizer; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.types.selectors.FilenameSelector; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.netbeans.junit.NbTestCase; +import static org.junit.Assert.*; + +/** + * + * @author Richard Michalsky + */ +public class PathFileSetTest extends NbTestCase { + + private PathFileSet pfs; + private Project fakeproj; + private ClusterRecord cl1; + private ClusterRecord cl2; + + public PathFileSetTest(String testName) { + super(testName); + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + +// @Before + @Override + protected void setUp() throws IOException { + clearWorkDir(); + pfs = new PathFileSet(); + fakeproj = new Project(); + fakeproj.setBaseDir(getWorkDir()); + fakeproj.addBuildListener(new BuildListener() { + + public void messageLogged(BuildEvent buildEvent) { + if (buildEvent.getPriority() <= Project.MSG_VERBOSE) { + System.err.println(buildEvent.getMessage()); + } + } + + public void taskStarted(BuildEvent buildEvent) { + } + + public void taskFinished(BuildEvent buildEvent) { + } + + public void targetStarted(BuildEvent buildEvent) { + } + + public void targetFinished(BuildEvent buildEvent) { + } + + public void buildStarted(BuildEvent buildEvent) { + } + + public void buildFinished(BuildEvent buildEvent) { + } + }); + pfs.setProject(fakeproj); + cl1 = new ClusterRecord("cl1").create().addModule("org-m1", true, true, true); + cl2 = new ClusterRecord("cl2").create().addModule("org-m2", true, false, false); + pfs.addPath(new Path(fakeproj, "cl1" + File.pathSeparator + "cl2")); + } + +// @After + @Override + protected void tearDown() { + } + + private void executeAndCheckResults(String[] expected) throws BuildException, IOException { + String[] output = new String[pfs.size()]; + int j = 0; + for (Iterator it = pfs.iterator(); it.hasNext(); j++) { + FileResource fileResource = (FileResource) it.next(); + String path = fileResource.getFile().getAbsolutePath().replace('\\', '/'); + output[j] = path; + } + Arrays.sort(output); + String wd = getWorkDir().getPath().replace('\\', '/').concat("/"); + for (int i = 0; i < expected.length; i++) { + expected[i] = wd + expected[i]; + } + assertArrayEquals(expected, output); + } + + private class ClusterRecord { + + File ut; + File cm; + File m; + private String clusterName; + + public ClusterRecord(String clusterName) { + this.clusterName = clusterName; + } + + public ClusterRecord create() throws IOException { + ut = new File(getWorkDir(), clusterName + "/update_tracking"); + ut.mkdirs(); + assertTrue(ut.isDirectory()); + + cm = new File(getWorkDir(), clusterName + "/config/Modules"); + cm.mkdirs(); + assertTrue(cm.isDirectory()); + + m = new File(getWorkDir(), clusterName + "/modules"); + m.mkdirs(); + assertTrue(m.isDirectory()); + return this; + } + + public ClusterRecord addModule(String dashedCNB, boolean jar, boolean config, boolean updateTracking) throws IOException { + if (updateTracking) { + assertTrue(new File(ut, dashedCNB + ".xml").createNewFile()); + } + if (jar) { + assertTrue(new File(m, dashedCNB + ".jar").createNewFile()); + } + if (config) { + assertTrue(new File(cm, dashedCNB + ".xml").createNewFile()); + } + return this; + } + } + + @Test + public void testFindAllFiles() throws IOException { + executeAndCheckResults(new String[]{"cl1/config/Modules/org-m1.xml", + "cl1/modules/org-m1.jar", + "cl1/update_tracking/org-m1.xml", + "cl2/modules/org-m2.jar"}); + } + + @Test + public void testWildcardIncludes() throws IOException { + pfs.setInclude("**/*.jar"); + executeAndCheckResults(new String[]{"cl1/modules/org-m1.jar", "cl2/modules/org-m2.jar"}); + } + + @Test + public void testSimpleIncludes() throws IOException { + pfs.setInclude("modules/org-m1.jar"); + executeAndCheckResults(new String[]{"cl1/modules/org-m1.jar"}); + } + + @Test + /** Cluster name is part of the basedir and thus WON'T match. */ + public void testWrongRelativeIncludes() throws IOException { + pfs.setInclude("cl1/modules/org-m1.jar"); + assertEquals(pfs.size(), 0); + } + + @Test + public void testEmptySet() throws IOException { + pfs.setInclude("pattern not present"); + assertEquals(pfs.size(), 0); + } + + @Test + public void testFileNameSelector() throws IOException { + FilenameSelector sel = new FilenameSelector(); + sel.setCasesensitive(false); + sel.setName("**/config/**/*.xml"); + pfs.add(sel); + executeAndCheckResults(new String[]{"cl1/config/Modules/org-m1.xml"}); + } + + @Test + public void testPathAttribute() throws IOException { + new ClusterRecord("cl3").create().addModule("org-m3", true, false, false); + new ClusterRecord("cl4").create().addModule("org-m4", true, false, false); + Path path = new Path(fakeproj, getWorkDir().getPath() + File.separator + "cl3" + + File.pathSeparator + + getWorkDir().getPath() + File.separator + "cl4"); + pfs.setPath(path); + pfs.setInclude("**/*.jar"); + executeAndCheckResults(new String[] { + "cl1/modules/org-m1.jar", "cl2/modules/org-m2.jar", + "cl3/modules/org-m3.jar", "cl4/modules/org-m4.jar" + }); + } +} \ No newline at end of file