blob: 9b917ca87655affd1ad1f06d1bca084b8368873c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.apisupport.project;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.queries.VisibilityQuery;
import org.netbeans.modules.apisupport.project.ProjectXMLManager.CyclicDependencyException;
import org.netbeans.modules.apisupport.project.api.ManifestManager;
import org.netbeans.modules.apisupport.project.api.Util;
import org.netbeans.modules.apisupport.project.suite.SuiteProject;
import org.netbeans.modules.apisupport.project.ui.customizer.ClusterInfo;
import org.netbeans.modules.apisupport.project.ui.customizer.SuiteProperties;
import org.netbeans.modules.apisupport.project.ui.customizer.SuiteUtils;
import org.netbeans.modules.apisupport.project.universe.LocalizedBundleInfo;
import org.netbeans.modules.apisupport.project.universe.ModuleEntry;
import org.netbeans.modules.apisupport.project.universe.ModuleList;
import org.netbeans.modules.apisupport.project.universe.TestModuleDependency;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
import org.netbeans.spi.project.support.ant.PropertyProvider;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.modules.SpecificationVersion;
import org.openide.util.ChangeSupport;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbCollections;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
public class ApisupportAntUtils {
private ApisupportAntUtils() {}
/**
* Tries to find {@link Project} in the given directory. If succeeds
* delegates to {@link ProjectInformation#getDisplayName}. Returns {@link
* FileUtil#getFileDisplayName} otherwise.
*/
public static String getDisplayName(FileObject projectDir) {
if (projectDir.isFolder()) {
try {
Project p = ProjectManager.getDefault().findProject(projectDir);
if (p != null) {
return ProjectUtils.getInformation(p).getDisplayName();
}
} catch (IOException e) {
// ignore
}
}
return FileUtil.getFileDisplayName(projectDir);
}
/**
* Check whether a given name can serve as a legal <ol>
* <li>Java class name
* <li>Java package name
* <li>NB module code name base
* </ol>
*/
public static boolean isValidJavaFQN(String name) {
if (name.length() == 0) {
return false;
}
StringTokenizer tk = new StringTokenizer(name,".",true); //NOI18N
boolean delimExpected = false;
while (tk.hasMoreTokens()) {
String namePart = tk.nextToken();
if (delimExpected ^ namePart.equals(".")) { // NOI18N
return false;
}
if (!delimExpected && !Utilities.isJavaIdentifier(namePart)) {
return false;
}
delimExpected = !delimExpected;
}
return delimExpected;
}
/**
* Check whether a given path can serve as a legal <ol>
* <li>File path name
* </ol>
*/
public static boolean isValidFilePath(String name) {
if (name.length() == 0) {
return false;
}
name = name.substring(0, name.lastIndexOf("."));
StringTokenizer tk = new StringTokenizer(name,"/",true); //NOI18N
boolean delimExpected = false;
while (tk.hasMoreTokens()) {
String namePart = tk.nextToken();
if (delimExpected ^ namePart.equals("/")) { // NOI18N
return false;
}
if (!delimExpected && !Utilities.isJavaIdentifier(namePart)) {
return false;
}
delimExpected = !delimExpected;
}
return delimExpected;
}
/**
* Search for an appropriate localized bundle (i.e.
* OpenIDE-Module-Localizing-Bundle) entry in the given
* <code>manifest</code> taking into account branding and localization
* (using {@link NbBundle#getLocalizingSuffixes}) and returns an
* appropriate <em>valid</em> {@link LocalizedBundleInfo} instance. By
* <em>valid</em> it's meant that a found localized bundle contains at
* least a display name. If <em>valid</em> bundle is not found
* <code>null</code> is returned.
*
* @param sourceDir source directory to be used for as a <em>searching
* path</em> for the bundle
* @param manifest manifest the bundle's path should be extracted from
* @return localized bundle info for the given project or <code>null</code>
*/
public static LocalizedBundleInfo findLocalizedBundleInfo(FileObject sourceDir, Manifest manifest) {
String locBundleResource =
ManifestManager.getInstance(manifest, false).getLocalizingBundle();
try {
if (locBundleResource != null) {
List<FileObject> bundleFOs = new ArrayList<FileObject>();
for (String resource : getPossibleResources(locBundleResource)) {
FileObject bundleFO = sourceDir.getFileObject(resource);
if (bundleFO != null) {
bundleFOs.add(bundleFO);
}
}
if (!bundleFOs.isEmpty()) {
Collections.reverse(bundleFOs);
return LocalizedBundleInfo.load(bundleFOs.toArray(new FileObject[bundleFOs.size()]));
}
}
} catch (IOException e) {
Util.err.notify(ErrorManager.INFORMATIONAL, e);
}
return null;
}
/**
* Actually deletages to {@link #findLocalizedBundleInfo(FileObject, Manifest)}.
*/
public static LocalizedBundleInfo findLocalizedBundleInfo(File projectDir) {
FileObject projectDirFO = FileUtil.toFileObject(projectDir);
if (projectDirFO == null) {
return null;
}
NbModuleProject p;
try {
p = (NbModuleProject) ProjectManager.getDefault().findProject(projectDirFO);
} catch (IOException e) {
return null;
}
if (p == null) {
return null;
}
String src = p.evaluator().getProperty("src.dir"); // NOI18N
if (src == null) {
return null;
}
File srcF = FileUtil.normalizeFile(new File(projectDir, src));
FileObject sourceDir = FileUtil.toFileObject(srcF);
FileObject manifestFO = FileUtil.toFileObject(FileUtil.normalizeFile(new File(projectDir, "manifest.mf"))); // NOI18N
LocalizedBundleInfo locInfo = null;
Manifest mf = Util.getManifest(manifestFO);
if (sourceDir != null && mf != null) {
locInfo = findLocalizedBundleInfo(sourceDir, mf);
}
return locInfo;
}
/**
* The same as {@link #findLocalizedBundleInfo(FileObject, Manifest)} but
* searching in the given JAR representing a NetBeans module.
*/
public static LocalizedBundleInfo findLocalizedBundleInfoFromJAR(File binaryProject) {
try {
JarFile main = new JarFile(binaryProject, false);
try {
Manifest mf = main.getManifest();
String locBundleResource =
ManifestManager.getInstance(mf, false).getLocalizingBundle();
if (locBundleResource != null) {
List<InputStream> bundleISs = new ArrayList<InputStream>();
Collection<JarFile> extraJarFiles = new ArrayList<JarFile>();
try {
// Look for locale variant JARs too.
// XXX the following could be simplified with #29580:
String name = binaryProject.getName();
int dot = name.lastIndexOf('.');
if (dot == -1) {
dot = name.length();
}
String base = name.substring(0, dot);
String suffix = name.substring(dot);
for (String infix : NbCollections.iterable(NbBundle.getLocalizingSuffixes())) {
File variant = new File(binaryProject.getParentFile(), "locale" + File.separatorChar + base + infix + suffix); // NOI18N
if (variant.isFile()) {
JarFile jf = new JarFile(variant, false);
extraJarFiles.add(jf);
addBundlesFromJar(jf, bundleISs, locBundleResource);
}
}
// Add main last, since we are about to reverse it:
addBundlesFromJar(main, bundleISs, locBundleResource);
if (!bundleISs.isEmpty()) {
Collections.reverse(bundleISs);
return LocalizedBundleInfo.load(bundleISs.toArray(new InputStream[bundleISs.size()]));
}
} finally {
for (InputStream bundleIS : bundleISs) {
bundleIS.close();
}
for (JarFile jarFile : extraJarFiles) {
jarFile.close();
}
}
}
if (mf.getMainAttributes().getValue(ManifestManager.BUNDLE_SYMBOLIC_NAME) != null) {
Properties p = new Properties();
String[] from = {"Bundle-Name", "Bundle-Category", "Bundle-Description", "Bundle-Description"};
String[] to = {LocalizedBundleInfo.NAME, LocalizedBundleInfo.DISPLAY_CATEGORY,
LocalizedBundleInfo.SHORT_DESCRIPTION, LocalizedBundleInfo.LONG_DESCRIPTION};
for (int i = 0; i < from.length; i++) {
String v = mf.getMainAttributes().getValue(from[i]);
if (v != null) {
p.setProperty(to[i], v);
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
p.store(baos, null);
return LocalizedBundleInfo.load(new InputStream[] {new ByteArrayInputStream(baos.toByteArray())});
}
} finally {
main.close();
}
} catch (IOException e) {
Util.err.notify(ErrorManager.INFORMATIONAL, e);
}
return null;
}
private static void addBundlesFromJar(JarFile jf, List<InputStream> bundleISs, String locBundleResource) throws IOException {
for (String resource : getPossibleResources(locBundleResource)) {
ZipEntry entry = jf.getEntry(resource);
if (entry != null) {
InputStream bundleIS = jf.getInputStream(entry);
bundleISs.add(bundleIS);
}
}
}
private static Iterable<String> getPossibleResources(String locBundleResource) {
String locBundleResourceBase, locBundleResourceExt;
int idx = locBundleResource.lastIndexOf('.');
if (idx != -1 && idx > locBundleResource.lastIndexOf('/')) {
locBundleResourceBase = locBundleResource.substring(0, idx);
locBundleResourceExt = locBundleResource.substring(idx);
} else {
locBundleResourceBase = locBundleResource;
locBundleResourceExt = "";
}
Collection<String> resources = new LinkedHashSet<String>();
for (String suffix : NbCollections.iterable(NbBundle.getLocalizingSuffixes())) {
String resource = locBundleResourceBase + suffix + locBundleResourceExt;
resources.add(resource);
resources.add(resource);
}
return resources;
}
/**
* Makes <code>target</code> project to be dependend on the given
* <code>dependency</code> project. I.e. adds new &lt;module-dependency&gt;
* element into target's <em>project.xml</em>. If such a dependency already
* exists the method does nothing. If the given code name base cannot be
* found in the module's universe or if adding the dependency creates dependency
* cycle (since 6.8) the method logs informational message and does nothing otherwise.
* <p>
* Note that the method does <strong>not</strong> save the
* <code>target</code> project. You need to do so explicitly (see {@link
* ProjectManager#saveProject}).
*
* @param codeNameBase codename base.
* @param releaseVersion release version, if <code>null</code> will be taken from the
* entry found in platform.
* @param version {@link SpecificationVersion specification version}, if
* <code>null</code>, will be taken from the entry found in the
* module's target platform.
* @param useInCompiler whether this this module needs a
* <code>dependency</code> module at a compile time.
* @return true if a dependency was successfully added; false otherwise
* (e.g. when such dependency already exists)
*/
public static boolean addDependency(final NbModuleProject target,
final String codeNameBase, final @NullAllowed String releaseVersion,
final @NullAllowed SpecificationVersion version, final boolean useInCompiler, String clusterName) throws IOException {
if(target.getModuleType() == NbModuleType.SUITE_COMPONENT && clusterName != null) {
final Project suiteProject = getSuiteProject(target);
if(suiteProject!=null) {
final SuiteProperties suiteProps = getSuiteProperties((SuiteProject)suiteProject);
boolean isClusterIncludedInTargetPlatform;
if((isClusterIncludedInTargetPlatform = isClusterIncludedInTargetPlatform(suiteProps, clusterName))
&& !isModuleIncludedInTargetPlatform(suiteProps, codeNameBase)) {
addModuleToTargetPlatform(suiteProject, suiteProps, codeNameBase);
} else if(!isClusterIncludedInTargetPlatform) {
addClusterToTargetPlatform(suiteProject, suiteProps, clusterName, codeNameBase);
}
}
}
ModuleEntry me = target.getModuleList().getEntry(codeNameBase);
if (me == null) { // ignore semi-silently (#72611)
Util.err.log(ErrorManager.INFORMATIONAL, "Trying to add " + codeNameBase + // NOI18N
" which cannot be found in the module's universe."); // NOI18N
return false;
}
ProjectXMLManager pxm = new ProjectXMLManager(target);
// firstly check if the dependency is already not there
for (ModuleDependency md : pxm.getDirectDependencies()) {
if (codeNameBase.equals(md.getModuleEntry().getCodeNameBase())) {
if (version != null && !md.hasImplementationDependency()) {
String old = md.getSpecificationVersion();
if (old == null || version.compareTo(new SpecificationVersion(old)) > 0) {
pxm.removeDependency(codeNameBase);
break;
}
}
Util.err.log(ErrorManager.INFORMATIONAL, codeNameBase + " already added"); // NOI18N
return false;
}
}
ModuleDependency md = new ModuleDependency(me,
(releaseVersion == null) ? me.getReleaseVersion() : releaseVersion,
version == null ? me.getSpecificationVersion() : version.toString(),
useInCompiler, false);
try {
pxm.addDependency(md);
} catch (CyclicDependencyException ex) {
Util.err.log(ErrorManager.INFORMATIONAL, ex.getLocalizedMessage());
return false;
}
return true;
}
static void addTestDependency(NbModuleProject prj, String codeNameBase, String clusterName) throws IOException {
if(prj.getModuleType() == NbModuleType.SUITE_COMPONENT && clusterName != null) {
final Project suiteProject = getSuiteProject(prj);
if(suiteProject!=null) {
final SuiteProperties suiteProps = getSuiteProperties((SuiteProject)suiteProject);
boolean isClusterIncludedInTargetPlatform;
if((isClusterIncludedInTargetPlatform = isClusterIncludedInTargetPlatform(suiteProps, clusterName))
&& !isModuleIncludedInTargetPlatform(suiteProps, codeNameBase)) {
addModuleToTargetPlatform(suiteProject, suiteProps, codeNameBase);
} else if(!isClusterIncludedInTargetPlatform) {
addClusterToTargetPlatform(suiteProject, suiteProps, clusterName, codeNameBase);
}
}
}
ModuleEntry me = prj.getModuleList().getEntry(codeNameBase);
if (me == null) { // ignore semi-silently (#72611)
Util.err.log(ErrorManager.INFORMATIONAL, "Trying to add " + codeNameBase + // NOI18N
" which cannot be found in the module's universe."); // NOI18N
return;
}
ProjectXMLManager pxm = new ProjectXMLManager(prj);
Map<String, Set<TestModuleDependency>> map = pxm.getTestDependencies(prj.getModuleList());
if (map != null && map.get("unit") != null) {
// firstly check if the dependency is already not there
for (TestModuleDependency md : map.get("unit")) {
if (codeNameBase.equals(md.getModule().getCodeNameBase())) {
Util.err.log(ErrorManager.INFORMATIONAL, codeNameBase + " already added"); // NOI18N
return;
}
}
}
TestModuleDependency md = new TestModuleDependency(me, true, true, true);
pxm.addTestDependency("unit", md);
}
public static URL findJavadocURL(final String cnbdashes, final URL[] roots) {
URL indexURL = null;
for (int i = 0; i < roots.length; i++) {
URL root = roots[i];
try {
indexURL = normalizeURL(new URL(root, cnbdashes + "/index.html")); // NOI18N
if (indexURL == null && (root.toExternalForm().indexOf(cnbdashes) != -1)) {
indexURL = normalizeURL(new URL(root, "index.html")); // NOI18N
}
} catch (MalformedURLException ex) {
// ignore - let the indexURL == null
}
if (indexURL != null) {
break;
}
}
return indexURL;
}
private static URL normalizeURL(URL url) {
FileObject fo = URLMapper.findFileObject(url);
if (fo != null) {
return URLMapper.findURL(fo, URLMapper.EXTERNAL);
} else {
return null;
}
}
/**
* Property provider which computes one or more properties based on some properties coming
* from an intermediate evaluator, and is capable of firing changes correctly.
*/
public abstract static class ComputedPropertyProvider implements PropertyProvider, PropertyChangeListener {
private final PropertyEvaluator eval;
private final ChangeSupport cs = new ChangeSupport(this);
protected ComputedPropertyProvider(PropertyEvaluator eval) {
this.eval = eval;
eval.addPropertyChangeListener(WeakListeners.propertyChange(this, eval));
}
/** get properties based on the incoming properties */
protected abstract Map<String,String> getProperties(Map<String,String> inputPropertyValues);
/** specify interesting input properties */
protected abstract Collection<String> inputProperties();
@Override
public final Map<String,String> getProperties() {
Map<String,String> vals = new HashMap<String, String>();
for (String k : inputProperties()) {
vals.put(k, eval.getProperty(k));
}
return getProperties(vals);
}
@Override
public final void addChangeListener(ChangeListener l) {
cs.addChangeListener(l);
}
@Override
public final void removeChangeListener(ChangeListener l) {
cs.removeChangeListener(l);
}
@Override
public final void propertyChange(PropertyChangeEvent evt) {
String p = evt.getPropertyName();
if (p != null && !inputProperties().contains(p)) {
return;
}
cs.fireChange();
}
}
public static final class UserPropertiesFileProvider implements PropertyProvider, PropertyChangeListener, ChangeListener {
private final PropertyEvaluator eval;
private final File basedir;
private final ChangeSupport changeSupport = new ChangeSupport(this);
private final ChangeListener listener = WeakListeners.change(this, null);
private PropertyProvider delegate;
public UserPropertiesFileProvider(PropertyEvaluator eval, File basedir) {
this.eval = eval;
this.basedir = basedir;
eval.addPropertyChangeListener(WeakListeners.propertyChange(this, eval));
computeDelegate();
}
private void computeDelegate() {
if (delegate != null) {
delegate.removeChangeListener(listener);
}
String buildS = eval.getProperty("user.properties.file"); // NOI18N
if (buildS != null) {
delegate = PropertyUtils.propertiesFilePropertyProvider(PropertyUtils.resolveFile(basedir, buildS));
} else {
/* XXX what should we do?
delegate = null;
*/
delegate = PropertyUtils.globalPropertyProvider();
}
delegate.addChangeListener(listener);
}
@Override
public Map<String,String> getProperties() {
if (delegate != null) {
return delegate.getProperties();
} else {
return Collections.emptyMap();
}
}
@Override
public void addChangeListener(ChangeListener l) {
changeSupport.addChangeListener(l);
}
@Override
public void removeChangeListener(ChangeListener l) {
changeSupport.removeChangeListener(l);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
String p = evt.getPropertyName();
if (p == null || p.equals("user.properties.file")) { // NOI18N
computeDelegate();
changeSupport.fireChange();
}
}
@Override
public void stateChanged(ChangeEvent e) {
changeSupport.fireChange();
}
}
/**
* Finds all available packages in a given project directory, including <tt>%lt;class-path-extension&gt;</tt>-s.
* See {@link #scanJarForPackageNames(java.util.Set, java.io.File)} for details.
*
* @param prjDir directory containing project to be scanned
* @return a set of found packages
*/
public static SortedSet<String> scanProjectForPackageNames(final File prjDir) {
return scanProjectForPackageNames(prjDir, true);
}
/**
* Finds all available packages in a given project directory. Found entries
* are in the form of a regular java package (x.y.z).
*
* @param prjDir directory containing project to be scanned
* @param withCPExt When <tt>false</tt> only source roots are scanned, otherwise scans <tt>%lt;class-path-extension&gt;</tt>-s as well.
* @return a set of found packages
*/
public static SortedSet<String> scanProjectForPackageNames(final File prjDir, boolean withCPExt) {
NbModuleProject project = null;
// find all available public packages in classpath extensions
FileObject source = FileUtil.toFileObject(prjDir);
if (source != null) { // ??
try {
project = (NbModuleProject) ProjectManager.getDefault().findProject(source);
} catch (IOException e) {
Util.err.notify(ErrorManager.INFORMATIONAL, e);
}
}
if (project == null) {
return new TreeSet<String>(Collections.<String>emptySet());
}
SortedSet<String> availablePublicPackages = new TreeSet<String>();
// find all available public packages in a source root
Set<FileObject> pkgs = new HashSet<FileObject>();
FileObject srcDirFO = project.getSourceDirectory();
scanForPackages(pkgs, srcDirFO, "java"); // NOI18N
for (FileObject pkg : pkgs) {
if (srcDirFO.equals(pkg)) { // default package #71532
continue;
}
String pkgS = PropertyUtils.relativizeFile(FileUtil.toFile(srcDirFO), FileUtil.toFile(pkg));
availablePublicPackages.add(pkgS.replace('/', '.'));
}
if (withCPExt) {
String[] libsPaths = new ProjectXMLManager(project).getBinaryOrigins();
for (int i = 0; i < libsPaths.length; i++) {
scanJarForPackageNames(availablePublicPackages, project.getHelper().resolveFile(libsPaths[i]));
}
}
// #72669: remove invalid packages.
Iterator<String> it = availablePublicPackages.iterator();
while (it.hasNext()) {
String pkg = it.next();
if (!isValidJavaFQN(pkg)) {
it.remove();
}
}
return availablePublicPackages;
}
/**
* Scans a given jar file for all packages which contains at least one
* .class file. Found entries are in the form of a regular java package
* (x.y.z).
*
* @param jarFile jar file to be scanned
* @param packages a set into which found packages will be added
*/
public static void scanJarForPackageNames(final Set<String> packages, final File jarFile) {
FileObject jarFileFO = FileUtil.toFileObject(jarFile);
if (jarFileFO == null) {
// Broken classpath entry, perhaps.
return;
}
FileObject root = FileUtil.getArchiveRoot(jarFileFO);
if (root == null) {
// Not really a JAR?
return;
}
Set<FileObject> pkgs = new HashSet<FileObject>();
scanForPackages(pkgs, root, "class"); // NOI18N
for (FileObject pkg : pkgs) {
if (root.equals(pkg)) { // default package #71532
continue;
}
String pkgS = pkg.getPath().replace('/', '.');
if (isValidJavaFQN(pkgS))
packages.add(pkgS);
}
}
/**
* Scan recursively through all folders in the given <code>dir</code> and
* add every directory/package, which contains at least one file with the
* given extension (probably class or java), into the given
* <code>validPkgs</code> set. Added entries are in the form of regular java
* package (x.y.z)
*/
private static void scanForPackages(final Set<FileObject> validPkgs, final FileObject dir, final String ext) {
if (dir == null) {
return;
}
for (Enumeration<? extends FileObject> en1 = dir.getFolders(false); en1.hasMoreElements(); ) {
FileObject subDir = (FileObject) en1.nextElement();
if (VisibilityQuery.getDefault().isVisible(subDir)) {
scanForPackages(validPkgs, subDir, ext);
}
}
for (Enumeration<? extends FileObject> en2 = dir.getData(false); en2.hasMoreElements(); ) {
FileObject kid = (FileObject) en2.nextElement();
if (kid.hasExt(ext) && Utilities.isJavaIdentifier(kid.getName())) {
// at least one class inside directory -> valid package
validPkgs.add(dir);
break;
}
}
}
public static String urlsToAntPath(final URL[] urls) {
return ClassPathSupport.createClassPath(urls).toString(ClassPath.PathConversionMode.WARN);
}
public static URL[] findURLs(final String path) {
if (path == null) {
return new URL[0];
}
String[] pieces = PropertyUtils.tokenizePath(path);
URL[] urls = new URL[pieces.length];
for (int i = 0; i < pieces.length; i++) {
// XXX perhaps also support http: URLs somehow?
urls[i] = FileUtil.urlForArchiveOrDir(FileUtil.normalizeFile(new File(pieces[i])));
}
return urls;
}
public static final String CPEXT_BINARY_PATH = "release/modules/ext/";
public static final String CPEXT_RUNTIME_RELATIVE_PATH = "ext/";
/**
* Copies given JAR file into <tt>release/modules/ext</tt> folder under <tt>projectDir</tt>.
* <tt>release/modules/ext</tt> will be created if necessary.
*
* @param projectDir Project folder
* @param jar JAR file to be copied
* @return If JAR copied successfully, returns string array <tt>{&lt;runtime-relative path&gt, &lt;binary origin path&gt;}</tt>,
* otherwise <tt>null</tt>.
* @throws IOException When <tt>release/modules/ext</tt> folder cannot be created.
*/
public static String[] copyClassPathExtensionJar(File projectDir, File jar) throws IOException {
String[] ret = null;
File releaseDir = new File(projectDir, CPEXT_BINARY_PATH); //NOI18N
if (! releaseDir.isDirectory() && !releaseDir.mkdirs()) {
throw new IOException("cannot create release directory '" + releaseDir + "'."); // NOI18N
}
FileObject relDirFo = FileUtil.toFileObject(releaseDir);
FileObject orig = FileUtil.toFileObject(FileUtil.normalizeFile(jar));
if (orig != null) {
FileObject existing = relDirFo.getFileObject(orig.getName(), orig.getExt());
if (existing != null)
existing.delete();
FileUtil.copyFile(orig, relDirFo, orig.getName());
ret = new String[2];
ret[0] = CPEXT_RUNTIME_RELATIVE_PATH + orig.getNameExt(); // NOI18N
ret[1] = CPEXT_BINARY_PATH + orig.getNameExt(); // NOI18N
}
return ret;
}
static SuiteProperties getSuiteProperties(NbModuleProject target) {
final Project suiteProject = getSuiteProject(target);
if(suiteProject!=null) {
return getSuiteProperties((SuiteProject) suiteProject);
}
return null;
}
static SuiteProperties getSuiteProperties(SuiteProject suiteProject) {
if(suiteProject!=null) {
Set<NbModuleProject> subModules = SuiteUtils.getSubProjects(suiteProject);
return new SuiteProperties(suiteProject, suiteProject.getHelper(),
suiteProject.getEvaluator(), subModules);
}
return null;
}
static Project getSuiteProject(NbModuleProject target) {
File suiteDirectory = target.getLookup().lookup(SuiteProvider.class).getSuiteDirectory();
if(suiteDirectory!=null) {
FileObject suiteDirectoryFO = FileUtil.toFileObject(suiteDirectory);
if(suiteDirectoryFO != null) {
try {
return ProjectManager.getDefault().findProject(suiteDirectoryFO);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (IllegalArgumentException ex) {
Exceptions.printStackTrace(ex);
}
}
}
return null;
}
static boolean isModuleIncludedInTargetPlatform(SuiteProperties suiteProps, String codeNameBase) {
if(suiteProps != null) {
for(String disabledModuleIter : suiteProps.getDisabledModules()) {
if(disabledModuleIter.equals(codeNameBase)) {
return false;
}
}
}
return true;
}
static boolean isClusterIncludedInTargetPlatform(SuiteProperties suiteProps, String clusterName) {
if(suiteProps != null) {
Set<ClusterInfo> clusterInfoSet = suiteProps.getClusterPath();
if(clusterInfoSet!=null) {
for(ClusterInfo infoIter : clusterInfoSet) {
if(infoIter.getClusterDir().getName().equals(clusterName)) {
return true;
}
}
}
}
return false;
}
static void addModuleToTargetPlatform(final Project suiteProject, final SuiteProperties suiteProps, String codeNameBase) {
if(suiteProps != null) {
Set<String> disabledModules = new HashSet<String>(Arrays.asList(suiteProps.getDisabledModules()));
for(String disableModuleIter:disabledModules) {
if(codeNameBase.equals(disableModuleIter)) {
disabledModules.remove(codeNameBase);
break;
}
}
String [] updatedDiasabledModules = new String[disabledModules.size()];
disabledModules.toArray(updatedDiasabledModules);
suiteProps.setDisabledModules(updatedDiasabledModules);
ProjectManager.mutex().writeAccess(new Runnable() {
@Override
public void run() {
try {
suiteProps.storeProperties();
ProjectManager.getDefault().saveProject(suiteProject);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
});
}
}
static void addClusterToTargetPlatform(final Project suiteProject, final SuiteProperties suiteProps, String clusterName, String codeNameBase) {
if(suiteProps != null) {
List<ClusterInfo> clusterInfoSet = new ArrayList<ClusterInfo>(suiteProps.getClusterPath());
if(suiteProps.getActivePlatform() != null) {
File clusterDirectory = null;
Set<ModuleEntry> moduleList = suiteProps.getActivePlatform().getModules();
for(ModuleEntry entryIter:moduleList) {
if(entryIter.getClusterDirectory().getName().equals(clusterName)) {
clusterDirectory = entryIter.getClusterDirectory();
break;
}
}
if(clusterDirectory != null) {
ClusterInfo newClusterInfo = ClusterInfo.create(clusterDirectory,
true, true);
clusterInfoSet.add(newClusterInfo);
Set<String> disabledModules = new HashSet<String>(Arrays.asList(suiteProps.getDisabledModules()));
for(ModuleEntry entryIter:moduleList) {
if(entryIter.getClusterDirectory().equals(clusterDirectory)) {
disabledModules.add(entryIter.getCodeNameBase());
}
}
suiteProps.setClusterPath(clusterInfoSet);
disabledModules.remove(codeNameBase);
String [] updatedDiasabledModules = new String[disabledModules.size()];
disabledModules.toArray(updatedDiasabledModules);
suiteProps.setDisabledModules(updatedDiasabledModules);
ProjectManager.mutex().writeAccess(new Runnable() {
@Override
public void run() {
try {
suiteProps.storeProperties();
ProjectManager.getDefault().saveProject(suiteProject);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
});
}
}
}
}
}