/**
* Copyright 2005 Open Cloud Ltd.
*
* Licensed 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.mobicents.eclipslee.servicecreation.wizards.project;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.ui.util.CoreUtility;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.mobicents.eclipslee.servicecreation.APIDialog;
import org.mobicents.eclipslee.servicecreation.ServiceCreationPlugin;
import org.mobicents.eclipslee.servicecreation.util.FileUtil;
import org.mobicents.eclipslee.servicecreation.wizards.WizardChangeListener;
import org.mobicents.eclipslee.util.slee.xml.ant.AntBuildTargetXML;
import org.mobicents.eclipslee.util.slee.xml.ant.AntInitTargetXML;
import org.mobicents.eclipslee.util.slee.xml.ant.AntPathXML;
import org.mobicents.eclipslee.util.slee.xml.ant.AntProjectXML;
import org.mobicents.eclipslee.util.slee.xml.ant.AntTaskdefXML;
import org.mobicents.eclipslee.xml.SLEEEntityResolver;
/**
* @author cath
*/
public class ProjectWizard extends Wizard implements INewWizard {
private static final String WIZARD_TITLE_1_0 = "JAIN SLEE 1.0 Project Wizard";
private static final String WIZARD_TITLE_1_1 = "JAIN SLEE 1.1 Project Wizard";
private static final String WIZARD_TITLE = WIZARD_TITLE_1_1;
final String BUILDER_ID = "org.mobicents.eclipslee.servicecreation.jainsleebuilder";
private static final IPath SLEE_JAR = new Path("lib/" + APIDialog.SLEE_JAR);
private static final IPath SLEE_TASKS_JAR = new Path("lib/slee-tasks.jar");
private static final IPath SLEE_API_ZIP = new Path("lib/" + APIDialog.SLEE_API_ZIP);
private static final IPath[] LIBS = {
SLEE_TASKS_JAR
};
// SLEE_JAR,
// SLEE_DOC_JAR,
private static final String[][] TASKS = {
{ "sbbjar", "org.mobicents.eclipslee.ant.SbbJar" },
{ "eventjar", "org.mobicents.eclipslee.ant.EventJar" },
{ "profilespecjar", "org.mobicents.eclipslee.ant.ProfileSpecJar" },
{ "deployablejar", "org.mobicents.eclipslee.ant.DeployableJar" },
{ "resourceadaptortypejar", "org.mobicents.eclipslee.ant.ResourceAdaptorTypeJar" },
{ "resourceadaptorjar", "org.mobicents.eclipslee.ant.ResourceAdaptorJar" }
};
public ProjectWizard() {
super();
setNeedsProgressMonitor(true);
}
/**
* The worker method. It will find the container, create the
* file if missing or just replace its contents, and open
* the editor on the newly created file.
*/
public void doFinish(IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("Creating JAIN SLEE Project " + project.getName(), 2);
createProject(project, monitor);
createOutputFolders(project, monitor);
installLibraries(project, monitor);
installDTDs(project, monitor);
configureClasspath(project, monitor);
monitor.worked(1);
createAntBuildFile(project, monitor);
monitor.worked(1);
} catch (Exception e) {
e.printStackTrace();
throw newCoreException("Error", e);
}
monitor.worked(1);
monitor.done();
}
private void createProject(IProject project, IProgressMonitor monitor) throws CoreException {
// Create the project.
if (!project.exists()) {
if (!Platform.getLocation().equals(projectLocationPath)) {
IProjectDescription desc = project.getWorkspace().newProjectDescription(project.getName());
desc.setLocation(projectLocationPath);
project.create(desc, monitor);
} else
project.create(monitor);
project.open(monitor);
}
// Add the SLEE Nature to the project.
if (!project.hasNature(ServiceCreationPlugin.NATURE_ID)) {
IProjectDescription desc = project.getDescription();
String originalIds[] = desc.getNatureIds();
String newIds[] = new String[originalIds.length + 1];
System.arraycopy(originalIds, 0, newIds, 0, originalIds.length);
newIds[originalIds.length] = ServiceCreationPlugin.NATURE_ID;
desc.setNatureIds(newIds);
project.setDescription(desc, monitor);
}
// Add the Java Nature to the project.
if (!project.hasNature(JavaCore.NATURE_ID)) {
IProjectDescription desc = project.getDescription();
String originalIds[] = desc.getNatureIds();
String newIds[] = new String[originalIds.length + 1];
System.arraycopy(originalIds, 0, newIds, 0, originalIds.length);
newIds[originalIds.length] = JavaCore.NATURE_ID;
desc.setNatureIds(newIds);
ICommand[] commands = desc.getBuildSpec();
ICommand command = desc.newCommand();
command.setBuilderName(BUILDER_ID);
ICommand[] newCommands = new ICommand[commands.length + 1];
// Add it before other builders.
System.arraycopy(commands, 0, newCommands, 1, commands.length);
newCommands[0] = command;
desc.setBuildSpec(newCommands);
project.setDescription(desc, monitor);
}
}
private void createOutputFolders(IProject project, IProgressMonitor monitor) throws CoreException {
// Try to create the src folder.
IFolder folder = project.getFolder("/src");
if (!folder.exists())
CoreUtility.createFolder(folder, true, true, monitor);
// And now the destination classes folder.
folder = project.getFolder("/classes");
if (!folder.exists())
CoreUtility.createFolder(folder, true, true, monitor);
// And the compiled jars folder.
folder = project.getFolder("/jars");
if (!folder.exists())
CoreUtility.createFolder(folder, true, true, monitor);
}
private void createAntBuildFile(IProject project, IProgressMonitor monitor) throws IOException, ParserConfigurationException, CoreException {
// Create a build.xml file in the root of this project
AntProjectXML projectXML = new AntProjectXML();
projectXML.setName(project.getName());
projectXML.setDefault("all");
// The INIT target.
AntInitTargetXML initXML = projectXML.addInitTarget();
initXML.setName("init");
AntPathXML pathXML = initXML.addPath("slee");
// Replace with the path to slee.jar bundled with the plugin
pathXML.addPathElement(SLEE_JAR.toOSString());
for (int i = 0; i < TASKS.length; i++) {
AntTaskdefXML taskXML = initXML.addTaskdef();
taskXML.setName(TASKS[i][0]);
taskXML.setClassname(TASKS[i][1]);
taskXML.setClasspath(SLEE_TASKS_JAR.toOSString());
}
// The 'all' target, which does nothing to start with
AntBuildTargetXML allXML = projectXML.addBuildTarget();
allXML.setName("all");
allXML.setDepends(new String[] { "init" });
// The 'clean' target, which does nothing to start with
AntBuildTargetXML cleanXML = projectXML.addBuildTarget();
cleanXML.setName("clean");
cleanXML.setDepends(new String[] { "init" });
// Save this as 'build.xml' in the project's root.
FileUtil.createFromInputStream(project, new Path("/build.xml"),
projectXML.getInputStreamFromXML(), monitor);
}
private void configureClasspath(IProject project, IProgressMonitor monitor) throws CoreException {
// Add slee.jar to the project's classpath
IJavaProject javaProject = JavaCore.create(project);
IPath path = project.getFullPath().append("/classes");
javaProject.setOutputLocation(path, null);
IClasspathEntry[] entries = new IClasspathEntry[3];
path = project.getFullPath().append("/src");
entries[0] = JavaCore.newSourceEntry(path);
entries[1] = JavaCore.newContainerEntry(new Path("org.eclipse.jdt.launching.JRE_CONTAINER"));
// Path to slee.jar
path = project.getFullPath().append("/" + SLEE_JAR.toOSString());
IPath docPath = project.getFullPath().append("/" + SLEE_API_ZIP.toOSString());
entries[2] = JavaCore.newLibraryEntry(path, docPath /* No available source */, null /* hell knows */);
javaProject.setRawClasspath(entries, null);
}
private void installLibraries(IProject project, IProgressMonitor monitor) throws CoreException, IOException{
// Create the lib folder.
IFolder folder = project.getFolder("/lib");
if (!folder.exists())
CoreUtility.createFolder(folder, true, true, null);
for (int i = 0; i < LIBS.length; i++) {
IPath path = LIBS[i];
InputStream stream = FileLocator.openStream( ServiceCreationPlugin.getDefault().getBundle(), path, false);
FileUtil.createFromInputStream(project, path, stream, monitor);
}
InputStream apiZipIS = ServiceCreationPlugin.getDefault().getSleeAPIZip();
InputStream sleeJarIS = ServiceCreationPlugin.getDefault().getSleeJar();
if (apiZipIS != null) {
IPath path = SLEE_API_ZIP;
FileUtil.createFromInputStream(project, path, apiZipIS, monitor);
}
if (sleeJarIS != null) {
IPath path = SLEE_JAR;
FileUtil.createFromInputStream(project, path, sleeJarIS, monitor);
}
}
private void installDTDs(IProject project, IProgressMonitor monitor) throws IOException, CoreException {
// Create the DTD folder
IFolder folder = project.getFolder("/dtd");
if (!folder.exists())
CoreUtility.createFolder(folder, true, true, null);
// get the jslee reference zip file
ZipFile zipFile_1_1 = ServiceCreationPlugin.getSleeAPI_1_1ZipFile();
IPath dtds[] = SLEEEntityResolver.getDTDPaths();
/*
* populate the project's dtd directory with non-std extension DTD
* files only. The std-DTDs are kept in the ZIP. The XML entity
* resolver also looks into the ZIP.
* NOTE: the generated SLEE ant build file uses slee-tasks.jar, this
* jar also contains the std-DTD from 1.0 and 1.1 - synchronize if
* necessary.
*/
for (int i = 0; i < dtds.length; i++) {
InputStream stream = null;
ZipEntry ze = zipFile_1_1.getEntry(dtds[i].toString().substring(1));
if (ze != null) {
continue; // don't extract standard DTD. These are also in slee-task.jar file
}
else {
stream = FileLocator.openStream(ServiceCreationPlugin.getDefault().getBundle(), dtds[i], false);
}
FileUtil.createFromInputStream(project, dtds[i], stream, monitor);
}
}
/**
* If you override this method you must call super.addPages() if you want to use
* the standard Filename and Identity Pages provided in this abstract class.
*/
public void addPages() {
page = new WizardNewProjectCreationPage(WIZARD_TITLE);
page.setTitle(WIZARD_TITLE);
page.setDescription("Name the JAIN SLEE project.");
addPage(page);
}
/**
* When a page's contents change in a way that might impact other pages
* this method should be called so that other pages can react.
* @param page
*/
public void pageChanged(WizardPage page) {
IWizardPage pages[] = this.getPages();
for (int i= 0; i < pages.length; i++) {
if (pages[i] instanceof WizardChangeListener) {
((WizardChangeListener) pages[i]).onWizardPageChanged(page);
}
}
}
/**
* This method calls doFinish() in a new thread.
*/
public boolean performFinish() {
project = page.getProjectHandle();
projectLocationPath = page.getLocationPath();
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException {
try {
doFinish(monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
try {
getContainer().run(true, false, op);
} catch (InterruptedException e) {
return false;
} catch (InvocationTargetException e) {
CoreException ex = newCoreException("Error creating Project", e);
MessageDialog.openError(getShell(), "Error", ex.getMessage());
return false;
}
return true;
}
/**
* If you override this method be sure to call super.init() in your implementation.
*/
public void init(IWorkbench workbench, IStructuredSelection selection) {
}
protected CoreException newCoreException(String message, Exception cause) {
String stackTrace = "R" + message + "\n" + cause.toString() + ":" + cause.getMessage() + "\n";
Throwable next = cause.getCause();
while(next == null)
{
stackTrace += "\nNested cause:" + next.getMessage();
}
StackTraceElement elements[] = cause.getStackTrace();
for (int i = 0; i < elements.length; i++) {
stackTrace = stackTrace + elements[i].toString() + "\n";
}
return newCoreException(stackTrace);
}
protected CoreException newCoreException(String message) {
IStatus status = new Status(IStatus.ERROR, "org.mobicents.eclipslee.servicecreation", IStatus.OK, message, null);
return new CoreException(status);
}
protected void throwCoreException(String message) throws CoreException {
throw newCoreException(message);
}
protected void throwCoreException(String message, Exception cause) throws CoreException {
throw newCoreException(message, cause);
}
private WizardNewProjectCreationPage page;
private IProject project;
private IPath projectLocationPath;
}