/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.netbeans.modules.scala.project;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.platform.JavaPlatformManager;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.api.queries.FileEncodingQuery;
import org.netbeans.modules.scala.project.ui.customizer.J2SEProjectProperties;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.netbeans.spi.project.support.ant.ProjectGenerator;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.netbeans.spi.project.support.ant.ReferenceHelper;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.modules.SpecificationVersion;
import org.openide.util.Mutex;
import org.openide.util.MutexException;
import org.openide.ErrorManager;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Creates a J2SEProject from scratch according to some initial configuration.
*/
public class J2SEProjectGenerator {
static final String MINIMUM_ANT_VERSION = "1.6.5";
private J2SEProjectGenerator() {}
/**
* Create a new empty J2SE project.
* @param dir the top-level directory (need not yet exist but if it does it must be empty)
* @param name the name for the project
* @param librariesDefinition project relative or absolute OS path to libraries definition; can be null
* @return the helper object permitting it to be further customized
* @throws IOException in case something went wrong
*/
public static AntProjectHelper createProject(final File dir, final String name, final String mainClass,
final String manifestFile, final String librariesDefinition) throws IOException {
final FileObject dirFO = FileUtil.createFolder(dir);
// if manifestFile is null => it's TYPE_LIB
final AntProjectHelper[] h = new AntProjectHelper[1];
dirFO.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
public void run() throws IOException {
h[0] = createProject(dirFO, name, "src", "test", mainClass, manifestFile, manifestFile == null, librariesDefinition); //NOI18N
final J2SEProject p = (J2SEProject) ProjectManager.getDefault().findProject(dirFO);
ProjectManager.getDefault().saveProject(p);
final ReferenceHelper refHelper = p.getReferenceHelper();
try {
ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
public Void run() throws Exception {
copyRequiredLibraries(h[0], refHelper);
return null;
}
});
} catch (MutexException ex) {
Exceptions.printStackTrace(ex.getException());
}
FileObject srcFolder = dirFO.createFolder("src"); // NOI18N
dirFO.createFolder("test"); // NOI18N
if ( mainClass != null ) {
createMainClass( mainClass, srcFolder );
}
}
});
return h[0];
}
public static AntProjectHelper createProject(final File dir, final String name,
final File[] sourceFolders, final File[] testFolders,
final String manifestFile, final String librariesDefinition) throws IOException {
assert sourceFolders != null && testFolders != null: "Package roots can't be null"; //NOI18N
final FileObject dirFO = FileUtil.createFolder(dir);
final AntProjectHelper[] h = new AntProjectHelper[1];
// this constructor creates only java application type
dirFO.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
public void run () throws IOException {
h[0] = createProject(dirFO, name, null, null, null, manifestFile, false, librariesDefinition);
final J2SEProject p = (J2SEProject) ProjectManager.getDefault().findProject(dirFO);
final ReferenceHelper refHelper = p.getReferenceHelper();
try {
ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
public Void run() throws Exception {
Element data = h[0].getPrimaryConfigurationData(true);
Document doc = data.getOwnerDocument();
NodeList nl = data.getElementsByTagNameNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"source-roots");
assert nl.getLength() == 1;
Element sourceRoots = (Element) nl.item(0);
nl = data.getElementsByTagNameNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"test-roots"); //NOI18N
assert nl.getLength() == 1;
Element testRoots = (Element) nl.item(0);
for (int i=0; i<sourceFolders.length; i++) {
String propName;
if (i == 0) {
//Name the first src root src.dir to be compatible with NB 4.0
propName = "src.dir"; //NOI18N
}
else {
String name = sourceFolders[i].getName();
propName = name + ".dir"; //NOI18N
}
int rootIndex = 1;
EditableProperties props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
while (props.containsKey(propName)) {
rootIndex++;
propName = name + rootIndex + ".dir"; //NOI18N
}
String srcReference = refHelper.createForeignFileReference(sourceFolders[i], JavaProjectConstants.SOURCES_TYPE_JAVA);
Element root = doc.createElementNS (J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); //NOI18N
root.setAttribute ("id",propName); //NOI18N
sourceRoots.appendChild(root);
props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
props.put(propName,srcReference);
h[0].putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props); // #47609
}
for (int i = 0; i < testFolders.length; i++) {
if (!testFolders[i].exists()) {
testFolders[i].mkdirs();
}
String propName;
if (i == 0) {
//Name the first test root test.src.dir to be compatible with NB 4.0
propName = "test.src.dir"; //NOI18N
}
else {
String name = testFolders[i].getName();
propName = "test." + name + ".dir"; // NOI18N
}
int rootIndex = 1;
EditableProperties props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
while (props.containsKey(propName)) {
rootIndex++;
propName = "test." + name + rootIndex + ".dir"; // NOI18N
}
String testReference = refHelper.createForeignFileReference(testFolders[i], JavaProjectConstants.SOURCES_TYPE_JAVA);
Element root = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root"); // NOI18N
root.setAttribute("id", propName); // NOI18N
testRoots.appendChild(root);
props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); // #47609
props.put(propName, testReference);
h[0].putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
}
h[0].putPrimaryConfigurationData(data,true);
ProjectManager.getDefault().saveProject (p);
copyRequiredLibraries(h[0], refHelper);
return null;
}
});
} catch (MutexException me ) {
ErrorManager.getDefault().notify (me);
}
}
});
return h[0];
}
private static AntProjectHelper createProject(FileObject dirFO, String name,
String srcRoot, String testRoot, String mainClass, String manifestFile,
boolean isLibrary, String librariesDefinition) throws IOException {
AntProjectHelper h = ProjectGenerator.createProject(dirFO, J2SEProjectType.TYPE, librariesDefinition);
Element data = h.getPrimaryConfigurationData(true);
Document doc = data.getOwnerDocument();
Element nameEl = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); // NOI18N
nameEl.appendChild(doc.createTextNode(name));
data.appendChild(nameEl);
Element minant = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "minimum-ant-version"); // NOI18N
minant.appendChild(doc.createTextNode(MINIMUM_ANT_VERSION)); // NOI18N
data.appendChild(minant);
EditableProperties ep = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
Element sourceRoots = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"source-roots"); //NOI18N
if (srcRoot != null) {
Element root = doc.createElementNS (J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); //NOI18N
root.setAttribute ("id","src.dir"); //NOI18N
sourceRoots.appendChild(root);
ep.setProperty("src.dir", srcRoot); // NOI18N
}
data.appendChild (sourceRoots);
Element testRoots = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"test-roots"); //NOI18N
if (testRoot != null) {
Element root = doc.createElementNS (J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); //NOI18N
root.setAttribute ("id","test.src.dir"); //NOI18N
testRoots.appendChild (root);
ep.setProperty("test.src.dir", testRoot); // NOI18N
}
data.appendChild (testRoots);
h.putPrimaryConfigurationData(data, true);
ep.setProperty("dist.dir", "dist"); // NOI18N
ep.setComment("dist.dir", new String[] {"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_dist.dir")}, false); // NOI18N
ep.setProperty("dist.jar", "${dist.dir}/" + PropertyUtils.getUsablePropertyName(name) + ".jar"); // NOI18N
ep.setProperty("javac.classpath", new String[0]); // NOI18N
ep.setProperty("build.sysclasspath", "ignore"); // NOI18N
ep.setComment("build.sysclasspath", new String[] {"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_build.sysclasspath")}, false); // NOI18N
ep.setProperty("run.classpath", new String[] { // NOI18N
"${javac.classpath}:", // NOI18N
"${build.classes.dir}", // NOI18N
});
ep.setProperty("debug.classpath", new String[] { // NOI18N
"${run.classpath}", // NOI18N
});
ep.setProperty("jar.compress", "false"); // NOI18N
if (!isLibrary) {
ep.setProperty("main.class", mainClass == null ? "" : mainClass); // NOI18N
}
ep.setProperty("javac.compilerargs", ""); // NOI18N
ep.setComment("javac.compilerargs", new String[] {
"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_javac.compilerargs"), // NOI18N
}, false);
ep.setProperty("scalac.compilerargs", ""); // NOI18N
ep.setComment("scalac.compilerargs", new String[] {
"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_scalac.compilerargs"), // NOI18N
}, false);
SpecificationVersion sourceLevel = getDefaultSourceLevel();
ep.setProperty("javac.source", sourceLevel.toString()); // NOI18N
ep.setProperty("javac.target", sourceLevel.toString()); // NOI18N
ep.setProperty("javac.deprecation", "false"); // NOI18N
ep.setProperty("scalac.deprecation", "no"); // NOI18N
ep.setProperty("scalac.unchecked", "no"); // NOI18N
ep.setProperty("javac.test.classpath", new String[] { // NOI18N
"${javac.classpath}:", // NOI18N
"${build.classes.dir}:", // NOI18N
"${libs.junit.classpath}:", // NOI18N
"${libs.junit_4.classpath}", //NOI18N
});
ep.setProperty("run.test.classpath", new String[] { // NOI18N
"${javac.test.classpath}:", // NOI18N
"${build.test.classes.dir}", // NOI18N
});
ep.setProperty("debug.test.classpath", new String[] { // NOI18N
"${run.test.classpath}", // NOI18N
});
ep.setProperty("build.generated.dir", "${build.dir}/generated"); // NOI18N
ep.setProperty("meta.inf.dir", "${src.dir}/META-INF"); // NOI18N
ep.setProperty("build.dir", "build"); // NOI18N
ep.setComment("build.dir", new String[] {"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_build.dir")}, false); // NOI18N
ep.setProperty("build.classes.dir", "${build.dir}/classes"); // NOI18N
ep.setProperty("build.test.classes.dir", "${build.dir}/test/classes"); // NOI18N
ep.setProperty("build.test.results.dir", "${build.dir}/test/results"); // NOI18N
ep.setProperty("build.classes.excludes", "**/*.java,**/*.form,**/*.scala"); // NOI18N
ep.setProperty("dist.javadoc.dir", "${dist.dir}/scaladoc"); // NOI18N
ep.setProperty("platform.active", "default_platform"); // NOI18N
ep.setProperty("java.platform.active", "java_default_platform"); // NOI18N
ep.setProperty("run.jvmargs", ""); // NOI18N
ep.setComment("run.jvmargs", new String[] {
"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_run.jvmargs"), // NOI18N
"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_run.jvmargs_2"), // NOI18N
"# " + NbBundle.getMessage(J2SEProjectGenerator.class, "COMMENT_run.jvmargs_3"), // NOI18N
}, false);
ep.setProperty(J2SEProjectProperties.JAVADOC_PRIVATE, "false"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_NO_TREE, "false"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_USE, "true"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_NO_NAVBAR, "false"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_NO_INDEX, "false"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_SPLIT_INDEX, "true"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_AUTHOR, "false"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_VERSION, "false"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_WINDOW_TITLE, ""); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_ENCODING, "${"+J2SEProjectProperties.SOURCE_ENCODING+"}"); // NOI18N
ep.setProperty(J2SEProjectProperties.JAVADOC_ADDITIONALPARAM, ""); // NOI18N
Charset enc = FileEncodingQuery.getDefaultEncoding();
ep.setProperty(J2SEProjectProperties.SOURCE_ENCODING, enc.name());
if (manifestFile != null) {
ep.setProperty("manifest.file", manifestFile); // NOI18N
}
h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
return h;
}
private static void copyRequiredLibraries(AntProjectHelper h, ReferenceHelper rh) throws IOException {
if (!h.isSharableProject()) {
return;
}
if (rh.getProjectLibraryManager().getLibrary("junit") == null) {
rh.copyLibrary(LibraryManager.getDefault().getLibrary("junit")); // NOI18N
}
if (rh.getProjectLibraryManager().getLibrary("junit_4") == null) {
rh.copyLibrary(LibraryManager.getDefault().getLibrary("junit_4")); // NOI18N
}
if (rh.getProjectLibraryManager().getLibrary("CopyLibs") == null) {
rh.copyLibrary(LibraryManager.getDefault().getLibrary("CopyLibs")); // NOI18N
}
}
private static void createMainClass( String mainClassName, FileObject srcFolder ) throws IOException {
int lastDotIdx = mainClassName.lastIndexOf( '.' );
String mName, pName;
if ( lastDotIdx == -1 ) {
mName = mainClassName.trim();
pName = null;
}
else {
mName = mainClassName.substring( lastDotIdx + 1 ).trim();
pName = mainClassName.substring( 0, lastDotIdx ).trim();
}
if ( mName.length() == 0 ) {
return;
}
FileObject mainTemplate = FileUtil.getConfigFile( "Templates/Scala/Main.scala" ); // NOI18N
if ( mainTemplate == null ) {
return; // Don't know the template
}
DataObject mt = DataObject.find( mainTemplate );
FileObject pkgFolder = srcFolder;
if ( pName != null ) {
String fName = pName.replace( '.', '/' ); // NOI18N
pkgFolder = FileUtil.createFolder( srcFolder, fName );
}
DataFolder pDf = DataFolder.findFolder( pkgFolder );
mt.createFromTemplate(pDf, mName, Collections.singletonMap("package", pName));
}
//------------ Used by unit tests -------------------
private static SpecificationVersion defaultSourceLevel;
private static SpecificationVersion getDefaultSourceLevel () {
if (defaultSourceLevel != null) {
return defaultSourceLevel;
}
else {
JavaPlatform defaultPlatform = JavaPlatformManager.getDefault().getDefaultPlatform();
SpecificationVersion v = defaultPlatform.getSpecification().getVersion();
if (v.equals(new SpecificationVersion("1.6")) || v.equals(new SpecificationVersion("1.7"))) {
// #89131: these levels are not actually distinct from 1.5. - xxx not true, but may be acceptable to have 1.5 as default
return new SpecificationVersion("1.5");
} else {
return v;
}
}
}
/**
* Unit test only method. Sets the default source level for tests
* where the default platform is not available.
* @param version the default source level set to project when it is created
*
*/
public static void setDefaultSourceLevel (SpecificationVersion version) {
defaultSourceLevel = version;
}
}