blob: a3892f67c75532a7f50ca874a3e268060ad64f6e [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.projectimport.eclipse.j2se;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.modules.java.api.common.project.ProjectProperties;
import org.netbeans.modules.java.j2seproject.J2SEProject;
import org.netbeans.modules.java.j2seproject.J2SEProjectGenerator;
import org.netbeans.modules.java.j2seproject.ui.customizer.J2SEProjectProperties;
import org.netbeans.modules.projectimport.eclipse.core.spi.LaunchConfiguration;
import org.netbeans.modules.projectimport.eclipse.core.spi.ProjectFactorySupport;
import org.netbeans.modules.projectimport.eclipse.core.spi.ProjectImportModel;
import org.netbeans.modules.projectimport.eclipse.core.spi.ProjectTypeUpdater;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.openide.WizardDescriptor;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.ImageUtilities;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
*
*/
@org.openide.util.lookup.ServiceProvider(service=org.netbeans.modules.projectimport.eclipse.core.spi.ProjectTypeFactory.class, position=1000)
public class J2SEProjectFactory implements ProjectTypeUpdater {
private static final String JAVA_NATURE = "org.eclipse.jdt.core.javanature"; // NOI18N
private static final Icon J2SE_PROJECT_ICON = ImageUtilities.loadImageIcon("org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png", false); // NOI18N
private static final String MANIFEST_FILE = "manifest.mf";
public J2SEProjectFactory() {
}
public boolean canHandle(ProjectDescriptor descriptor) {
return descriptor.getNatures().contains(JAVA_NATURE);
}
public Project createProject(final ProjectImportModel model, final List<String> importProblems) throws IOException {
// calculate nb project location
File nbProjectDir = model.getNetBeansProjectLocation(); // NOI18N
if (ProjectFactorySupport.areSourceRootsOwned(model, nbProjectDir, importProblems)) {
return null;
}
// create basic NB project
String buildScript = null;
if (new File(nbProjectDir, "build.xml").exists()) { //NOI18N
buildScript = "nb-build.xml"; //NOI18N
}
final AntProjectHelper helper = J2SEProjectGenerator.createProject(
nbProjectDir, model.getProjectName(), model.getEclipseSourceRootsAsFileArray(),
model.getEclipseTestSourceRootsAsFileArray(), null, null, buildScript);
EditableProperties ep = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
boolean changed = false;
if (new File(nbProjectDir, "dist").exists()) { //NOI18N
ep.setProperty("dist.dir", "nbdist"); //NOI18N
changed = true;
}
if (new File(nbProjectDir, "build").exists()) { //NOI18N
ep.setProperty("build.dir", "nbbuild"); //NOI18N
changed = true;
}
if (changed) {
helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
}
// get NB project
J2SEProject nbProject = (J2SEProject) ProjectManager.getDefault().
findProject(FileUtil.toFileObject(
FileUtil.normalizeFile(nbProjectDir)));
// set labels for source roots
ProjectFactorySupport.updateSourceRootLabels(model.getEclipseSourceRoots(), nbProject.getSourceRoots());
ProjectFactorySupport.updateSourceRootLabels(model.getEclipseTestSourceRoots(), nbProject.getTestSourceRoots());
ProjectFactorySupport.setupSourceExcludes(helper, model, importProblems);
setupCompilerProperties(helper, model);
// update project classpath
ProjectFactorySupport.updateProjectClassPath(helper, nbProject.getReferenceHelper(), model, importProblems);
// set platform used by an Eclipse project
if (model.getJavaPlatform() != null) {
setExplicitJavaPlatform(helper, model);
}
addLaunchConfigurations(nbProject, model.getLaunchConfigurations());
// save project
ProjectManager.getDefault().saveProject(nbProject);
return nbProject;
}
private void setExplicitJavaPlatform(final AntProjectHelper helper, final ProjectImportModel model) {
Element pcd = helper.getPrimaryConfigurationData(true);
NodeList sourceRootNodes = pcd.getElementsByTagNameNS(J2SEProject.PROJECT_CONFIGURATION_NAMESPACE, "source-roots"); //NOI18N
assert sourceRootNodes.getLength() == 1 : "Broken project.xml file"; // NOI18N
Element el = pcd.getOwnerDocument().createElementNS(J2SEProject.PROJECT_CONFIGURATION_NAMESPACE, "explicit-platform"); // NOI18N
el.setAttribute("explicit-source-supported", "true"); // NOI18N
pcd.insertBefore(el, sourceRootNodes.item(0));
helper.putPrimaryConfigurationData(pcd, true);
EditableProperties prop = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
String ver = model.getJavaPlatform().getSpecification().getVersion().toString();
String normalizedName = model.getJavaPlatform().getProperties().get("platform.ant.name"); // NOI18N
prop.setProperty(ProjectProperties.PLATFORM_ACTIVE, normalizedName);
helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, prop);
}
public String calculateKey(ProjectImportModel model) {
return ProjectFactorySupport.calculateKey(model);
}
public String update(Project project, ProjectImportModel model, String oldKey, List<String> importProblems) throws IOException {
if (!(project instanceof J2SEProject)) {
throw new IOException("is not java project: "+project.getClass().getName()); //NOI18N
}
String newKey = calculateKey(model);
// update project classpath
String actualKey = ProjectFactorySupport.synchronizeProjectClassPath(project,
((J2SEProject)project).getAntProjectHelper(),
((J2SEProject)project).getReferenceHelper(), model, oldKey, newKey, importProblems);
setupCompilerProperties(((J2SEProject) project).getAntProjectHelper(), model);
// TODO:
// update source roots and platform
// save project
ProjectManager.getDefault().saveProject(project);
return actualKey;
}
public Icon getProjectTypeIcon() {
return J2SE_PROJECT_ICON;
}
public String getProjectTypeName() {
return org.openide.util.NbBundle.getMessage(J2SEProjectFactory.class, "LABEL_Java_Project");
}
public List<WizardDescriptor.Panel<WizardDescriptor>> getAdditionalImportWizardPanels() {
return Collections.<WizardDescriptor.Panel<WizardDescriptor>>emptyList();
}
private void setupCompilerProperties(AntProjectHelper helper, ProjectImportModel model) {
EditableProperties ep = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
ep.setProperty(ProjectProperties.JAVAC_SOURCE, model.getSourceLevel());
ep.setProperty(ProjectProperties.JAVAC_TARGET, model.getTargetLevel());
ep.setProperty(ProjectProperties.JAVAC_DEPRECATION, Boolean.toString(model.isDeprecation()));
ep.setProperty(ProjectProperties.JAVAC_COMPILERARGS, model.getCompilerArgs());
ep.setProperty(ProjectProperties.SOURCE_ENCODING, model.getEncoding());
helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
ep = helper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
ep.setProperty(ProjectProperties.JAVAC_DEBUG, Boolean.toString(model.isDebug()));
helper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
}
public File getProjectFileLocation(ProjectDescriptor descriptor, String token) {
// N/A
return null;
}
private void addLaunchConfigurations(J2SEProject nbProject, Collection<LaunchConfiguration> launchConfigurations) throws IOException {
Iterator<LaunchConfiguration> it = launchConfigurations.iterator();
while (it.hasNext()) {
LaunchConfiguration config = it.next();
if (!config.getType().equals(LaunchConfiguration.TYPE_LOCAL_JAVA_APPLICATION) || config.getMainType() == null) {
it.remove();
}
}
AntProjectHelper aph = nbProject.getAntProjectHelper();
// Adding manifest.file property to ensure correct behavior of jar after build.
if (!launchConfigurations.isEmpty()) {
EditableProperties props = aph.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
createManifest(nbProject.getProjectDirectory(), MANIFEST_FILE);
props.put("manifest.file", MANIFEST_FILE);
aph.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
}
if (launchConfigurations.size() == 1) {
// For just a single config, treat it as the default config.
LaunchConfiguration config = launchConfigurations.iterator().next();
EditableProperties props = aph.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
storeConfig(config, props);
aph.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
} else if (!launchConfigurations.isEmpty()) {
// >1 config. No idea which is "default" so just create them all and let user pick if they want.
for (LaunchConfiguration config : launchConfigurations) {
String path = "nbproject/configs/" + config.getName() + ".properties"; // NOI18N
EditableProperties props = aph.getProperties(path);
storeConfig(config, props);
aph.putProperties(path, props);
}
// Set one of them to current so that it is clear they got imported.
String path = "nbproject/private/config.properties"; // NOI18N
EditableProperties props = aph.getProperties(path);
props.setProperty("config", launchConfigurations.iterator().next().getName()); // NOI18N
aph.putProperties(path, props);
}
}
private void storeConfig(LaunchConfiguration config, EditableProperties props) {
props.setProperty(ProjectProperties.MAIN_CLASS, config.getMainType());
// XXX normally APPLICATION_ARGS and RUN_VM_ARGS are put in private properties; does it matter here?
if (config.getProgramArguments() != null) {
props.setProperty(ProjectProperties.APPLICATION_ARGS, config.getProgramArguments());
}
if (config.getVmArguments() != null) {
props.setProperty(ProjectProperties.RUN_JVM_ARGS, config.getVmArguments());
}
}
/**
* Create a new application manifest file with minimal initial contents.
* @param dir the directory to create it in
* @throws IOException in case of problems
*/
private static void createManifest(final FileObject dir, final String manifestFile) throws IOException {
FileObject manifest = dir.createData(manifestFile);
FileLock lock = manifest.lock();
try {
OutputStream os = manifest.getOutputStream(lock);
try {
PrintWriter pw = new PrintWriter(os);
pw.println("Manifest-Version: 1.0"); // NOI18N
pw.println("X-COMMENT: Main-Class will be added automatically by build"); // NOI18N
pw.println(); // safest to end in \n\n due to JRE parsing bug
pw.flush();
} finally {
os.close();
}
} finally {
lock.releaseLock();
}
}
}