# HG changeset patch # User Richard Michalsky # Date 1227272488 -3600 # Node ID dc57dbbca18a952d610b10b332663746cfe68ee5 # Parent 150850d6d01be84848ca570216156dd0516089e3 #152960 early patch - not for integration 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 @@ -84,6 +84,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/run.xml b/apisupport.harness/release/run.xml --- a/apisupport.harness/release/run.xml +++ b/apisupport.harness/release/run.xml @@ -48,7 +48,10 @@ - + + + + @@ -93,7 +96,7 @@ - + - - - + + + + - + + + + - + + @@ -181,11 +201,12 @@ This target only works when run from inside the NetBeans IDE. + + + - - - + @@ -200,15 +221,16 @@ This target only works when run from inside the NetBeans IDE. + + + - - - + 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 @@ -105,14 +105,14 @@ - - - - - - - - + + + + + + + + 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 +pathfileset=org.netbeans.nbbuild.PathFileSet 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 @@ -104,13 +104,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) { @@ -128,6 +141,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); @@ -155,119 +170,137 @@ 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(); + } + if (isEager || isAutoload || isEnabled) { + 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(); - } - - if (isEager || isAutoload || isEnabled) { - 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/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 @@ -899,17 +899,18 @@ 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()); - } - } +// XXX - no more included/excluded clusters +// String cluster = module.getClusterName(); // TODO - abs. path in clusterName, get rid of netbeans.dest.dir altogether +// 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()); +// } +// } return module.getJar(); } @@ -966,6 +967,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('.','-'); } @@ -1176,6 +1178,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,262 @@ +/* + * 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.util.ArrayList; +import java.util.Enumeration; +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.Task; +import org.apache.tools.ant.types.Path; +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; + +/** + * Does the same as ant's fileset, only for given path instead of single basedir. + * Files in set are returned as absolute paths. + * + * @author Richard Michalsky + */ +public class PathFileSet extends Task implements SelectorContainer { + private Path clusterPath; + private String property; +// private String excludedModules; + private String pathsep = File.pathSeparator; + private String include; + private AbstractSelectorContainer selectors = new AbstractSelectorContainer() {}; + + public PathFileSet() { + + } + + /** + * Returned fileset is stored in property specified with 'property' attribute. + * @param property + */ + public void setProperty(String property) { + this.property = property; + } + +// public void setExcludedModules(String excludedModules) { +// this.excludedModules = excludedModules; +// } + + /** + * Separator of entries in fileset. Defaults to path separator. + * @param pathsep + */ + public void setPathsep(String pathsep) { + this.pathsep = pathsep; + } + + /** + * Optional include pattern for filtering files. The same as fileset's nested >include< tag. + * @param include + */ + public void setInclude(String include) { + this.include = include; + } + + private List paths = new ArrayList(); + + /** + * Elements of nested paths are used as basedirs for fileset. + * @param clusterPath + */ + public void addPath(Path clusterPath) { + paths.add(clusterPath); + } + + @Override + public void execute() throws BuildException { + try { + log("Scanning " + paths.size() + " paths.", Project.MSG_VERBOSE); + DirectoryScanner scanner = new DirectoryScanner(); + if (paths.size() == 0) + throw new BuildException("No path specified"); + if (property == null) + throw new BuildException("No output property specified."); + + StringBuilder sb = new StringBuilder(); + + for (Path path : paths) { + String[] includedClusters = path.list(); + for (String clusterName : includedClusters) { + scanner.setBasedir(clusterName); + scanner.setSelectors(selectors.getSelectors(getProject())); + if (include != null) + scanner.setIncludes(new String[] { include }); + scanner.scan(); + + log("Scanned pathelement '" + clusterName + "', " + + scanner.getIncludedFilesCount() + " files found.", Project.MSG_VERBOSE); + for (String relFile: scanner.getIncludedFiles()) { + if (sb.length() > 0) + sb.append(pathsep); + sb.append(new File(clusterName, relFile).getPath()); + } + } + } + getProject().setNewProperty(property, sb.toString()); + log("Set property " + property + " = " + sb.toString(), Project.MSG_VERBOSE); + } catch (Exception ex) { + throw new BuildException(ex); + } + } + + 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); + } + +} diff --git a/nbbuild/templates/common.xml b/nbbuild/templates/common.xml --- a/nbbuild/templates/common.xml +++ b/nbbuild/templates/common.xml @@ -324,6 +324,9 @@ + + + - + 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,233 @@ +/* + * 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.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.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 task; + 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(); + task = 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) { + } + }); + task.setProject(fakeproj); + cl1 = new ClusterRecord("cl1").create().addModule("org-m1", true, true, true); + cl2 = new ClusterRecord("cl2").create().addModule("org-m2", true, false, false); + task.addPath(new Path(fakeproj, "cl1" + File.pathSeparator + "cl2")); + } + +// @After + protected void tearDown() { + } + + private void executeAndCheckResults(String[] expected) throws BuildException, IOException { + task.setProperty("output"); + task.execute(); + String[] output = fakeproj.getProperty("output").replace('\\', '/').split(File.pathSeparator); + 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 testSeparator() throws IOException { + task.setPathsep(","); + String[] expected = new String[]{"cl1/config/Modules/org-m1.xml", + "cl1/modules/org-m1.jar", + "cl1/update_tracking/org-m1.xml", + "cl2/modules/org-m2.jar"}; + task.setProperty("output"); + task.execute(); + String[] output = fakeproj.getProperty("output").replace('\\', '/').split(","); + 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); + } + + @Test + public void testWildcardIncludes() throws IOException { + task.setInclude("**/*.jar"); + executeAndCheckResults(new String[]{"cl1/modules/org-m1.jar", "cl2/modules/org-m2.jar"}); + } + + @Test + public void testSimpleIncludes() throws IOException { + task.setInclude("modules/org-m1.jar"); + executeAndCheckResults(new String[]{"cl1/modules/org-m1.jar"}); + } + + @Test + public void testEmptySet() throws IOException { + task.setProperty("output"); + task.setInclude("pattern not present"); + task.execute(); + String output = fakeproj.getProperty("output"); + assertEquals(0, output.length()); + } + + @Test + public void testFileNameSelector() throws IOException { + FilenameSelector sel = new FilenameSelector(); + sel.setCasesensitive(false); + sel.setName("**/config/**/*.xml"); + task.add(sel); + executeAndCheckResults(new String[]{"cl1/config/Modules/org-m1.xml"}); + } +} \ No newline at end of file