/*******************************************************************************
* Copyright (c) 2012 BundleMaker Project Team
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nils Hartmann - initial API and implementation
******************************************************************************/
package org.bundlemaker.core.transformations.support;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.bundlemaker.core.BundleMakerCore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*
*/
public class TransformationScriptSupport {
/**
* Name of the sample transformation script that is created the first time the transformation script support is
* enabled
*/
public static final IPath SAMPLE_TRANSFORMATION_SCRIPT_FILENAME = new Path(
"org/bundlemaker/example/transformation/SampleTransformationScript.java");
/**
* Enables transformation script capability to the specified project.
*
* <p>
* This method adds all missing natures, classpaths and folders to the specified project
*
* @param eclipseProject
* @param jreClasspathEntries
* @throws CoreException
*/
/**
* @param eclipseProject
* @param jreClasspathEntries
* @throws CoreException
*/
public static void enableTransformationScriptSupport(IProject eclipseProject, IClasspathEntry[] jreClasspathEntries)
throws CoreException {
// hier: org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage.init(IJavaProject, IPath, IClasspathEntry[],
// boolean)
// Convert to JDT java project
boolean alreadyJavaProject = BundleMakerCore.isJavaProject(eclipseProject);
if (!alreadyJavaProject) {
BundleMakerCore.addJavaNature(eclipseProject);
}
IPath projectPath = new Path(eclipseProject.getName()).makeAbsolute();
IWorkspaceRoot root = eclipseProject.getWorkspace().getRoot();
// Create source and binary folders
IPath sourceFolderPath = projectPath.append("src");
IPath binFolderPath = projectPath.append("bin");
createFolder(root.getFolder(sourceFolderPath), true, true, null);
createDerivedFolder(root.getFolder(binFolderPath), true, true, null);
// Create classpath including the BundleMaker Classpath Container containing BM libs
// from running Eclipse instance
ClasspathBuilder.forProject(eclipseProject, alreadyJavaProject) //
.setOutputLocation(binFolderPath) //
.addSourceEntry(sourceFolderPath) //
.addContainerEntry(BundleMakerCore.BUNDLEMAKER_CONTAINER_PATH) //
.addEntries(jreClasspathEntries) //
.save();
// Write sample script
InputStream is = TransformationScriptSupport.class.getResourceAsStream("TransformationScriptTemplate.txt");
IFolder examplePackageFolder = createFolder(
root.getFolder(sourceFolderPath.append(SAMPLE_TRANSFORMATION_SCRIPT_FILENAME.removeLastSegments(1))), true,
true, null);
IFile sampleScript = examplePackageFolder.getFile(SAMPLE_TRANSFORMATION_SCRIPT_FILENAME.lastSegment());
// don't override if already existing
if (!sampleScript.exists()) {
sampleScript.create(is, true, null);
}
}
/**
* Returns an {@link IFile} pointing to the sample transformation script if available
*
* @param project
* @return
*/
public static IFile findSampleTransformationScript(IProject project) {
IFile result = project.getFile(new Path("src").append(SAMPLE_TRANSFORMATION_SCRIPT_FILENAME));
if (result == null || result.exists() == false) {
return null;
}
return result;
}
static class ClasspathBuilder {
private final IJavaProject _javaProject;
private final List<IClasspathEntry> _cpEntries;
private IPath _outputLocation;
static ClasspathBuilder forProject(IProject eclipseProject, boolean alreadyJavaProject) throws CoreException {
IJavaProject javaProject = JavaCore.create(eclipseProject);
IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
List<IClasspathEntry> cpEntries = new ArrayList<IClasspathEntry>();
// // add already existing classpath entries
if (alreadyJavaProject) {
for (IClasspathEntry iClasspathEntry : rawClasspath) {
cpEntries.add(iClasspathEntry);
}
}
return new ClasspathBuilder(javaProject, cpEntries);
}
private ClasspathBuilder(IJavaProject project, List<IClasspathEntry> cpEntries) throws CoreException {
_javaProject = project;
_cpEntries = cpEntries;
}
public ClasspathBuilder addSourceEntry(IPath sourceFolderPath) {
IClasspathEntry sourceEntry = JavaCore.newSourceEntry(sourceFolderPath);
if (!_cpEntries.contains(sourceEntry)) {
_cpEntries.add(sourceEntry);
}
return this;
}
public ClasspathBuilder addContainerEntry(IPath containerPath) {
IClasspathEntry containerEntry = JavaCore.newContainerEntry(containerPath);
if (!_cpEntries.contains(containerEntry)) {
_cpEntries.add(containerEntry);
}
return this;
}
public ClasspathBuilder setOutputLocation(IPath outputLocation) {
this._outputLocation = outputLocation;
return this;
}
/**
* @param jreClasspathEntries
*/
public ClasspathBuilder addEntries(IClasspathEntry[] jreClasspathEntries) {
for (IClasspathEntry iClasspathEntry : jreClasspathEntries) {
if (!_cpEntries.contains(iClasspathEntry)) {
_cpEntries.add(iClasspathEntry);
}
}
return this;
}
public void save() throws CoreException {
IClasspathEntry[] classpathEntries = _cpEntries.toArray(new IClasspathEntry[0]);
_javaProject.setRawClasspath(classpathEntries, _outputLocation, null);
// save changes to the jdt project
_javaProject.save(null, true);
}
}
public static void createDerivedFolder(IFolder folder, boolean force, boolean local, IProgressMonitor monitor)
throws CoreException {
if (!folder.exists()) {
IContainer parent = folder.getParent();
if (parent instanceof IFolder) {
createDerivedFolder((IFolder) parent, force, local, null);
}
folder.create(force ? (IResource.FORCE | IResource.DERIVED) : IResource.DERIVED, local, monitor);
}
}
/**
* Creates a folder and all parent folders if not existing. Project must exist.
* <code> org.eclipse.ui.dialogs.ContainerGenerator</code> is too heavy (creates a runnable)
*
* @param folder
* the folder to create
* @param force
* a flag controlling how to deal with resources that are not in sync with the local file system
* @param local
* a flag controlling whether or not the folder will be local after the creation
* @param monitor
* the progress monitor
* @throws CoreException
* thrown if the creation failed
*/
public static IFolder createFolder(IFolder folder, boolean force, boolean local, IProgressMonitor monitor)
throws CoreException {
if (!folder.exists()) {
IContainer parent = folder.getParent();
if (parent instanceof IFolder) {
createFolder((IFolder) parent, force, local, null);
}
folder.create(force, local, monitor);
}
return folder;
}
}