at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.JFXBuildConfigurationEditor.java Source code

Java tutorial

Introduction

Here is the source code for at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.JFXBuildConfigurationEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2012 BestSolution.at and others.
 * 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:
 *     Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
 *     Martin Bluehweis<martin.bluehweis@bestsolution.at> - rewritten, the build configuration is represented by an EMF model now
 *******************************************************************************/
package at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors;

import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.ANT_TASK__BUILD_DIRECTORY;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.ANT_TASK__CSS_TO_BIN;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.ANT_TASK__DEPLOY;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.ANT_TASK__SIGNJAR;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__APPLICATION;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__EMBEDJNLP;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__EXTENSION;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__HEIGHT;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__INCLUDE_DT;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__INFO;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__NATIVE_PACKAGE;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__OFFLINE_ALLOWED;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__PLACEHOLDERID;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__PLACEHOLDERREF;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__SPLASH_IMAGE;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__TEMPLATE;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.DEPLOY__WIDTH;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.SIGN_JAR__ALIAS;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.SIGN_JAR__KEYPASS;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.SIGN_JAR__KEYSTORE;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.SIGN_JAR__STOREPASS;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage.Literals.SIGN_JAR__STORETYPE;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.APPLICATION__MAINCLASS;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.APPLICATION__NAME;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.APPLICATION__PRELOADERCLASS;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.APPLICATION__TOOLKIT;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.APPLICATION__VERSION;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.INFO__VENDOR;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.TEMPLATE__FILE;
import static at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage.Literals.TEMPLATE__TO_FILE;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.WritableValue;
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.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
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.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.ui.MarkerHelper;
import org.eclipse.emf.common.ui.editor.ProblemEditorPart;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.databinding.FeaturePath;
import org.eclipse.emf.databinding.IEMFValueProperty;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor;
import org.eclipse.emf.edit.ui.util.EditUIMarkerHelper;
import org.eclipse.emf.edit.ui.util.EditUIUtil;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.ui.dialogs.MainTypeSelectionDialog;
import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.FolderSelectionDialog;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableMapCellLabelProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.dialogs.ResourceSelectionDialog;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;

import at.bestsolution.efxclipse.tooling.jdt.ui.internal.JavaFXUIPlugin;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTask;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.AntTasksPackage;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ApplicationToolkitType;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.Icon;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.KeyValuePair;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.Param;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersFactory;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.ParametersPackage;
import at.bestsolution.efxclipse.tooling.jdt.ui.internal.editors.model.anttasks.parameters.Splash;

/**
 * 
 * @author martin
 */
@SuppressWarnings("restriction")
public class JFXBuildConfigurationEditor extends MultiPageEditorPart {
    final WritableValue bean = new WritableValue();
    /**
     * This keeps track of the editing domain that is used to track all changes to the model.
     */
    private AdapterFactoryEditingDomain editingDomain;
    /**
     * This is the one adapter factory used for providing views of the model.
     */
    private ComposedAdapterFactory adapterFactory;
    /**
     * This keeps track of the active content viewer, which may be either one of the viewers in the pages or the content outline viewer.
     */
    private Viewer currentViewer;
    /**
     * Controls whether the problem indication should be updated.
     */
    private boolean updateProblemIndication = true;
    /**
     * Resources that have been removed since last activation.
     */
    private Collection<Resource> removedResources = new ArrayList<Resource>();
    /**
     * Resources that have been changed since last activation.
     */
    private Collection<Resource> changedResources = new ArrayList<Resource>();
    /**
     * Resources that have been saved.
     */
    private Collection<Resource> savedResources = new ArrayList<Resource>();
    /**
     * Properties from old build file.
     */
    private Properties properties = new Properties();
    /**
     * The MarkerHelper is responsible for creating workspace resource markers presented.
     */
    private MarkerHelper markerHelper = new EditUIMarkerHelper();

    /**
     * Map to store the diagnostic associated with a resource.
     */
    private Map<Resource, Diagnostic> resourceToDiagnosticMap = new LinkedHashMap<Resource, Diagnostic>();

    private FormToolkit toolkit;

    private static final int DELAY = 500;

    private DataBindingContext dbc;

    /**
     * This listens to which ever viewer is active. <!-- begin-user-doc --> <!-- end-user-doc -->
     * 
     * @generated
     */
    protected ISelectionChangedListener selectionChangedListener;

    public JFXBuildConfigurationEditor() {
        super();
        initializeEditingDomain();
        ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceChangeListener);
    }

    /**
     * This listens for workspace changes. <!-- begin-user-doc --> <!-- end-user-doc -->
     * 
     * @generated
     */
    protected IResourceChangeListener resourceChangeListener = new IResourceChangeListener() {
        public void resourceChanged(IResourceChangeEvent event) {
            IResourceDelta delta = event.getDelta();
            try {
                class ResourceDeltaVisitor implements IResourceDeltaVisitor {
                    protected ResourceSet resourceSet = editingDomain.getResourceSet();
                    protected Collection<Resource> changedResources = new ArrayList<Resource>();
                    protected Collection<Resource> removedResources = new ArrayList<Resource>();

                    public boolean visit(IResourceDelta delta) {
                        if (delta.getResource().getType() == IResource.FILE) {
                            if (delta.getKind() == IResourceDelta.REMOVED
                                    || delta.getKind() == IResourceDelta.CHANGED
                                            && delta.getFlags() != IResourceDelta.MARKERS) {
                                Resource resource = resourceSet.getResource(
                                        URI.createPlatformResourceURI(delta.getFullPath().toString(), true), false);
                                if (resource != null) {
                                    if (delta.getKind() == IResourceDelta.REMOVED) {
                                        removedResources.add(resource);
                                    } else if (!savedResources.remove(resource)) {
                                        changedResources.add(resource);
                                    }
                                }
                            }
                        }

                        return true;
                    }

                    public Collection<Resource> getChangedResources() {
                        return changedResources;
                    }

                    public Collection<Resource> getRemovedResources() {
                        return removedResources;
                    }
                }

                final ResourceDeltaVisitor visitor = new ResourceDeltaVisitor();
                delta.accept(visitor);

                if (!visitor.getRemovedResources().isEmpty()) {
                    getSite().getShell().getDisplay().asyncExec(new Runnable() {
                        public void run() {
                            removedResources.addAll(visitor.getRemovedResources());
                            if (!isDirty()) {
                                getSite().getPage().closeEditor(JFXBuildConfigurationEditor.this, false);
                            }
                        }
                    });
                }

                if (!visitor.getChangedResources().isEmpty()) {
                    getSite().getShell().getDisplay().asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            changedResources.addAll(visitor.getChangedResources());
                            if (getSite().getPage().getActiveEditor() == JFXBuildConfigurationEditor.this) {
                                handleActivate();
                            }
                        }
                    });
                }
            } catch (CoreException e) {
                e.printStackTrace();
            }
        }
    };

    /**
     * Handles activation of the editor or it's associated views.
     */
    private void handleActivate() {
        if (editingDomain.getResourceToReadOnlyMap() != null) {
            editingDomain.getResourceToReadOnlyMap().clear();
        }

        if (!removedResources.isEmpty()) {
            if (handleDirtyConflict()) {
                getSite().getPage().closeEditor(JFXBuildConfigurationEditor.this, false);
            } else {
                removedResources.clear();
                changedResources.clear();
                savedResources.clear();
            }
        } else if (!changedResources.isEmpty()) {
            changedResources.removeAll(savedResources);
            handleChangedResources();
            changedResources.clear();
            savedResources.clear();
        }
    }

    /**
     * Shows a dialog that asks if conflicting changes should be discarded.
     */
    private boolean handleDirtyConflict() {
        return MessageDialog.openQuestion(getSite().getShell(), "File Conflict",
                "There are unsaved changes that conflict with changes made outside the editor.  Do you wish to discard this editor's changes?");
    }

    /**
     * Handles what to do with changed resources on activation.
     */
    private void handleChangedResources() {
        if (!changedResources.isEmpty() && (!isDirty() || handleDirtyConflict())) {
            if (isDirty()) {
                changedResources.addAll(editingDomain.getResourceSet().getResources());
            }
            editingDomain.getCommandStack().flush();

            updateProblemIndication = false;
            for (Resource resource : changedResources) {
                if (resource.isLoaded()) {
                    resource.unload();
                    try {
                        resource.load(Collections.EMPTY_MAP);
                        bean.setValue(getTask());
                        dbc.updateTargets();
                    } catch (IOException exception) {
                        if (!resourceToDiagnosticMap.containsKey(resource)) {
                            resourceToDiagnosticMap.put(resource, analyzeResourceProblems(resource, exception));
                        }
                    }
                }
            }
            updateProblemIndication = true;
            updateProblemIndication();
        }
    }

    /**
     * This sets up the editing domain for the model editor.
     */
    private void initializeEditingDomain() {
        // Create an adapter factory that yields item providers.
        //
        adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);

        adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory());
        // adapterFactory.addAdapterFactory( new AntTasksItemProviderAdapterFactory() );
        // adapterFactory.addAdapterFactory( new ParametersItemProviderAdapterFactory() );
        adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());

        // Create the command stack that will notify this editor as commands are executed.
        //
        BasicCommandStack commandStack = new BasicCommandStack();

        // Add a listener to set the most recent command's affected objects to be the selection of the viewer with focus.
        //
        commandStack.addCommandStackListener(new CommandStackListener() {
            public void commandStackChanged(final EventObject event) {
                getContainer().getDisplay().asyncExec(new Runnable() {
                    public void run() {
                        firePropertyChange(IEditorPart.PROP_DIRTY);

                        // Try to select the affected objects.
                        //
                        Command mostRecentCommand = ((CommandStack) event.getSource()).getMostRecentCommand();
                        if (mostRecentCommand != null) {
                            setSelectionToViewer(mostRecentCommand.getAffectedObjects());
                        }
                    }
                });
            }
        });

        // Create the editing domain with a special command stack.
        //
        editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack,
                new HashMap<Resource, Boolean>());
    }

    /**
     * This sets the selection into whichever viewer is active.
     */
    public void setSelectionToViewer(Collection<?> collection) {
        final Collection<?> theSelection = collection;
        // Make sure it's okay.
        //
        if (theSelection != null && !theSelection.isEmpty()) {
            Runnable runnable = new Runnable() {
                public void run() {
                    // Try to select the items in the current content viewer of the editor.
                    //
                    if (currentViewer != null) {
                        currentViewer.setSelection(new StructuredSelection(theSelection.toArray()), true);
                    }
                }
            };
            getSite().getShell().getDisplay().asyncExec(runnable);
        }
    }

    /**
     * This is for implementing {@link IEditorPart} and simply tests the command stack.
     */
    @Override
    public boolean isDirty() {
        return ((BasicCommandStack) editingDomain.getCommandStack()).isSaveNeeded();
    }

    /**
     * This is for implementing {@link IEditorPart} and simply saves the model file.
     */
    @Override
    public void doSave(IProgressMonitor progressMonitor) {
        // Save only resources that have actually changed.
        //
        final Map<Object, Object> saveOptions = new HashMap<Object, Object>();
        saveOptions.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED, Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);

        // Do the work within an operation because this is a long running activity that modifies the workbench.
        //
        WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
            // This is the method that gets invoked when the operation runs.
            //
            @Override
            public void execute(IProgressMonitor monitor) {
                // Save the resources to the file system.
                //
                boolean first = true;
                for (Resource resource : editingDomain.getResourceSet().getResources()) {
                    if ((first || !resource.getContents().isEmpty() || isPersisted(resource))
                            && !editingDomain.isReadOnly(resource)) {
                        try {
                            long timeStamp = resource.getTimeStamp();
                            resource.save(saveOptions);
                            if (resource.getTimeStamp() != timeStamp) {
                                savedResources.add(resource);
                            }
                        } catch (Exception exception) {
                            resourceToDiagnosticMap.put(resource, analyzeResourceProblems(resource, exception));
                        }
                        first = false;
                    }
                }
            }
        };

        updateProblemIndication = false;
        try {
            // This runs the options, and shows progress.
            //
            new ProgressMonitorDialog(getSite().getShell()).run(true, false, operation);

            // Refresh the necessary state.
            //
            ((BasicCommandStack) editingDomain.getCommandStack()).saveIsDone();
            firePropertyChange(IEditorPart.PROP_DIRTY);
        } catch (Exception e) {
            // TODO
            e.printStackTrace();
        }
        updateProblemIndication = true;
        updateProblemIndication();
    }

    /**
     * Updates the problems indication with the information described in the specified diagnostic. <!-- begin-user-doc --> <!-- end-user-doc -->
     */
    private void updateProblemIndication() {
        if (updateProblemIndication) {
            BasicDiagnostic diagnostic = new BasicDiagnostic(Diagnostic.OK, JavaFXUIPlugin.PLUGIN_ID, 0, null,
                    new Object[] { editingDomain.getResourceSet() });
            for (Diagnostic childDiagnostic : resourceToDiagnosticMap.values()) {
                if (childDiagnostic.getSeverity() != Diagnostic.OK) {
                    diagnostic.add(childDiagnostic);
                }
            }

            int lastEditorPage = getPageCount() - 1;
            if (lastEditorPage >= 0 && getEditor(lastEditorPage) instanceof ProblemEditorPart) {
                ((ProblemEditorPart) getEditor(lastEditorPage)).setDiagnostic(diagnostic);
                if (diagnostic.getSeverity() != Diagnostic.OK) {
                    setActivePage(lastEditorPage);
                }
            } else if (diagnostic.getSeverity() != Diagnostic.OK) {
                ProblemEditorPart problemEditorPart = new ProblemEditorPart();
                problemEditorPart.setDiagnostic(diagnostic);
                problemEditorPart.setMarkerHelper(markerHelper);
                try {
                    addPage(++lastEditorPage, problemEditorPart, getEditorInput());
                    setPageText(lastEditorPage, problemEditorPart.getPartName());
                    setActivePage(lastEditorPage);
                    showTabs();
                } catch (PartInitException e) {
                    // TODO
                    e.printStackTrace();
                }
            }

            if (markerHelper.hasMarkers(editingDomain.getResourceSet())) {
                markerHelper.deleteMarkers(editingDomain.getResourceSet());
                if (diagnostic.getSeverity() != Diagnostic.OK) {
                    try {
                        markerHelper.createMarkers(diagnostic);
                    } catch (CoreException e) {
                        // TODO
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * Returns a diagnostic describing the errors and warnings listed in the resource and the specified exception (if any). <!-- begin-user-doc --> <!--
     * end-user-doc -->
     * 
     * @generated
     */
    private Diagnostic analyzeResourceProblems(Resource resource, Exception exception) {
        if (!resource.getErrors().isEmpty() || !resource.getWarnings().isEmpty()) {
            BasicDiagnostic basicDiagnostic = new BasicDiagnostic(Diagnostic.ERROR, JavaFXUIPlugin.PLUGIN_ID, 0,
                    "_UI_CreateModelError_message",
                    new Object[] { exception == null ? (Object) resource : exception });
            basicDiagnostic.merge(EcoreUtil.computeDiagnostic(resource, true));
            return basicDiagnostic;
        } else if (exception != null) {
            return new BasicDiagnostic(Diagnostic.ERROR, JavaFXUIPlugin.PLUGIN_ID, 0,
                    "_UI_CreateModelError_message", new Object[] { exception });
        } else {
            return Diagnostic.OK_INSTANCE;
        }
    }

    private boolean isPersisted(Resource resource) {
        boolean result = false;
        try {
            InputStream stream = editingDomain.getResourceSet().getURIConverter()
                    .createInputStream(resource.getURI());
            if (stream != null) {
                result = true;
                stream.close();
            }
        } catch (IOException e) {
            // Ignore
        }
        return result;
    }

    /**
     * This always returns true because it is not currently supported. <!-- begin-user-doc --> <!-- end-user-doc -->
     * 
     * @generated
     */
    @Override
    public boolean isSaveAsAllowed() {
        return true;
    }

    /**
     * This also changes the editor's input. <!-- begin-user-doc --> <!-- end-user-doc -->
     * 
     * @generated
     */
    @Override
    public void doSaveAs() {
        SaveAsDialog saveAsDialog = new SaveAsDialog(getSite().getShell());
        saveAsDialog.open();
        IPath path = saveAsDialog.getResult();
        if (path != null) {
            IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
            if (file != null) {
                doSaveAs(URI.createPlatformResourceURI(file.getFullPath().toString(), true),
                        new FileEditorInput(file));
            }
        }
    }

    private void doSaveAs(URI uri, IEditorInput editorInput) {
        (editingDomain.getResourceSet().getResources().get(0)).setURI(uri);
        setInputWithNotify(editorInput);
        setPartName(editorInput.getName());
        IProgressMonitor progressMonitor = getActionBars().getStatusLineManager() != null
                ? getActionBars().getStatusLineManager().getProgressMonitor()
                : new NullProgressMonitor();
        doSave(progressMonitor);
    }

    private EditingDomainActionBarContributor getActionBarContributor() {
        return (EditingDomainActionBarContributor) getEditorSite().getActionBarContributor();
    }

    private IActionBars getActionBars() {
        return getActionBarContributor().getActionBars();
    }

    @Override
    public void dispose() {
        ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceChangeListener);
        dbc.dispose();
        super.dispose();
    }

    @Override
    protected void createPages() {
        createModel();

        // Only creates the other pages if there is something that can be edited
        if (!editingDomain.getResourceSet().getResources().isEmpty()) {
            AntTask task = getTask();
            createPageOverview(task);
            createPageDeploy(task);
            createPageSigning(task);
        }

        getSite().getShell().getDisplay().asyncExec(new Runnable() {
            public void run() {
                setActivePage(0);
            }
        });
    }

    private AntTask getTask() {
        AntTask task;
        try {
            task = (AntTask) editingDomain.getResourceSet().getResources().get(0).getContents().get(0);
        } catch (Exception e) {
            if (!properties.isEmpty()) {
                task = PropertiesToModelTransformer.transform(properties);
                editingDomain.getResourceSet().getResources().get(0).getContents().add(0, task);
                doSave(new NullProgressMonitor());
            } else {
                throw new UnsupportedOperationException("Could not read file");
            }
        }
        return task;
    }

    /**
     * This is the method called to load a resource into the editing domain's resource set based on the editor's input. <!-- begin-user-doc --> <!--
     * end-user-doc -->
     * 
     * @generated
     */
    private void createModel() {
        // Initialize the model, this is important for the class loader.
        AntTasksPackage.eINSTANCE.eClass();
        ParametersPackage.eINSTANCE.eClass();

        URI resourceURI = EditUIUtil.getURI(getEditorInput());
        Exception exception = null;
        Resource resource = null;
        try {
            // Load the resource through the editing domain.
            //
            resource = editingDomain.getResourceSet().getResource(resourceURI, true);
        } catch (Exception e) {
            exception = e;
            resource = editingDomain.getResourceSet().getResource(resourceURI, false);
        }

        Diagnostic diagnostic = analyzeResourceProblems(resource, exception);
        if (diagnostic.getSeverity() != Diagnostic.OK) {
            resourceToDiagnosticMap.put(resource, diagnostic);
        }
        editingDomain.getResourceSet().eAdapters().add(problemIndicationAdapter);
    }

    private EContentAdapter problemIndicationAdapter = new EContentAdapter() {
        @Override
        public void notifyChanged(Notification notification) {
            if (notification.getNotifier() instanceof Resource) {
                switch (notification.getFeatureID(Resource.class)) {
                case Resource.RESOURCE__IS_LOADED:
                case Resource.RESOURCE__ERRORS:
                case Resource.RESOURCE__WARNINGS: {
                    Resource resource = (Resource) notification.getNotifier();
                    Diagnostic diagnostic = analyzeResourceProblems(resource, null);
                    if (diagnostic.getSeverity() != Diagnostic.OK) {
                        resourceToDiagnosticMap.put(resource, diagnostic);
                    } else {
                        resourceToDiagnosticMap.remove(resource);
                    }

                    if (updateProblemIndication) {
                        getSite().getShell().getDisplay().asyncExec(new Runnable() {
                            public void run() {
                                updateProblemIndication();
                            }
                        });
                    }
                    break;
                }
                }
            } else {
                super.notifyChanged(notification);
            }
        }

        @Override
        protected void setTarget(Resource target) {
            basicSetTarget(target);
        }

        @Override
        protected void unsetTarget(Resource target) {
            basicUnsetTarget(target);
        }
    };

    @Override
    public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException {
        if (!(editorInput instanceof IFileEditorInput))
            throw new PartInitException("Invalid Input: Must be IFileEditorInput");
        super.init(site, editorInput);
        try {
            IFileEditorInput i = (IFileEditorInput) editorInput;
            properties.load(i.getFile().getContents());
            setPartName(editorInput.getName());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void createPageOverview(final AntTask task) {
        Composite composite = new Composite(getContainer(), SWT.NONE);
        FillLayout layout = new FillLayout();
        composite.setLayout(layout);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
                JavaFXUIPlugin.PLUGIN_ID + ".JFXBuildConfigurationEditor_overview");

        bean.setValue(task);

        toolkit = new FormToolkit(composite.getDisplay());

        final Form form = toolkit.createForm(composite);
        form.setText("FX Build Configuration");
        form.setImage(getTitleImage());
        form.getBody().setLayout(new FillLayout());
        toolkit.decorateFormHeading(form);

        initToolbar(form);

        ScrolledForm scrolledForm = toolkit.createScrolledForm(form.getBody());
        scrolledForm.getBody().setLayout(new GridLayout(2, false));
        Composite sectionParent = scrolledForm.getBody();

        dbc = new DataBindingContext();
        IWidgetValueProperty textModify = WidgetProperties.text(SWT.Modify);
        IWidgetValueProperty selChange = WidgetProperties.selection();

        {
            Section section = toolkit.createSection(sectionParent,
                    Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED);
            section.setText("Build && Package Properties");
            section.setDescription("The following properties are needed to build the JavaFX-Application");
            section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

            Composite sectionClient = toolkit.createComposite(section);
            sectionClient.setLayout(new GridLayout(4, false));

            {
                toolkit.createLabel(sectionClient, "Build Directory*:");
                final Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
                toolkit.createButton(sectionClient, "Filesystem ...", SWT.PUSH)
                        .addSelectionListener(new SelectionAdapter() {
                            @Override
                            public void widgetSelected(final SelectionEvent e) {
                                String dir = handleBuildFilesystemDirectorySelection(t.getShell());
                                if (dir != null) {
                                    t.setText(dir);
                                }
                            }
                        });
                toolkit.createButton(sectionClient, "Workspace ...", SWT.PUSH)
                        .addSelectionListener(new SelectionAdapter() {
                            @Override
                            public void widgetSelected(final SelectionEvent e) {
                                String dir = handleBuildWorkbenchDirectorySelection(t.getShell());
                                if (dir != null) {
                                    t.setText(dir);
                                }
                            }
                        });
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain, ANT_TASK__BUILD_DIRECTORY);
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Vendor name*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__INFO, INFO__VENDOR));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Application title*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__APPLICATION, APPLICATION__NAME));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Application version*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__APPLICATION, APPLICATION__VERSION));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Application class*:");
                final Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1));
                Button b = toolkit.createButton(sectionClient, "Browse ...", SWT.PUSH);
                b.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        String name = handleRootclassSelection(t.getShell());
                        if (name != null) {
                            t.setText(name);
                        }
                    }
                });
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__APPLICATION, APPLICATION__MAINCLASS));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Preloader class:");
                final Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1));
                Button b = toolkit.createButton(sectionClient, "Browse ...", SWT.PUSH);
                b.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        String name = handlePreloaderclassSelection(t.getShell());
                        if (name != null) {
                            t.setText(name);
                        }
                    }
                });
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__APPLICATION, APPLICATION__PRELOADERCLASS));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Splash:");
                final Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1));
                Button b = toolkit.createButton(sectionClient, "Browse ...", SWT.PUSH);
                b.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        String name = handleSplashImage(t.getShell());
                        if (name != null) {
                            t.setText(name);
                        }
                    }
                });
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__SPLASH_IMAGE));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Manifest-Attributes:")
                        .setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
                Composite container = toolkit.createComposite(sectionClient);
                GridLayout gl = new GridLayout(2, false);
                gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = gl.marginTop = gl.marginWidth = 0;
                container.setLayout(gl);
                GridData gdContainer = new GridData(GridData.FILL_HORIZONTAL);
                gdContainer.horizontalSpan = 2;
                container.setLayoutData(gdContainer);

                Composite tableContainer = toolkit.createComposite(container);
                Table t = toolkit.createTable(tableContainer,
                        SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
                t.setHeaderVisible(true);
                t.setLinesVisible(true);

                GridData gdTable = new GridData(GridData.FILL_HORIZONTAL);
                gdTable.heightHint = t.getHeaderHeight() + t.getItemHeight() * 5;
                tableContainer.setLayoutData(gdTable);

                TableColumnLayout tablelayout = new TableColumnLayout();
                final TableViewer v = new TableViewer(t);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.heightHint = t.getHeaderHeight() + t.getItemHeight() * 5;
                v.getControl().setLayoutData(gd);
                v.setContentProvider(ArrayContentProvider.getInstance());

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(final Object element) {
                            return ((Param) element).getName();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(33));
                    c.getColumn().setText("Name");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(final Object element) {
                            return ((Param) element).getValue();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(67));
                    c.getColumn().setText("Value");
                }
                tableContainer.setLayout(tablelayout);
                v.setInput(task.getManifestEntries());

                Composite buttonComp = toolkit.createComposite(sectionClient);
                buttonComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.END, false, false));
                buttonComp.setLayout(new GridLayout());

                {
                    Button b = toolkit.createButton(buttonComp, "Add ...", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            if (handleAddManifestAttr(getSite().getShell())) {
                                v.setInput(task.getManifestEntries());
                                v.setSelection(new StructuredSelection(
                                        task.getManifestEntries().get(task.getManifestEntries().size() - 1)));
                            }
                        }
                    });
                }

                {
                    Button b = toolkit.createButton(buttonComp, "Remove", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            Param value = (Param) ((IStructuredSelection) v.getSelection()).getFirstElement();
                            if (value != null) {
                                if (handleRemoveManifestAttr(value)) {
                                    v.setInput(task.getManifestEntries());
                                }
                            } else {
                                MessageDialog.openWarning(getSite().getShell(), "Warning",
                                        "Please select an entry");
                            }
                        }
                    });
                }
                {
                    toolkit.createLabel(sectionClient, "Toolkit Type:")
                            .setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
                    ComboViewer c = new ComboViewer(sectionClient);
                    c.getCombo().setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                    c.setContentProvider(new ArrayContentProvider());
                    c.setInput(ApplicationToolkitType.VALUES);
                    IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                            FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__APPLICATION, APPLICATION__TOOLKIT));
                    dbc.bindValue(selChange.observe(c.getCombo()), prop.observeDetail(bean));
                }
                {
                    Button b = toolkit.createButton(sectionClient, "Convert CSS into binary form", SWT.CHECK);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 4, 1));
                    IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                            FeaturePath.fromList(ANT_TASK__CSS_TO_BIN));
                    dbc.bindValue(selChange.observe(b), prop.observeDetail(bean));
                }
            }

            section.setClient(sectionClient);
        }

        {
            Section section = toolkit.createSection(sectionParent,
                    Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED);
            section.setText("Building & Exporting");
            section.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, true, 1, 2));

            Composite sectionClient = toolkit.createComposite(section);
            sectionClient.setLayout(new GridLayout(1, false));

            {
                FormText text = toolkit.createFormText(sectionClient, false);
                text.setText(
                        "<p>To generate build instructions and export the project: <li style=\"bullet\" bindent=\"1\">Generate <a href=\"generateAnt\">ant build.xml</a> only</li><li style=\"bullet\" bindent=\"2\">Generate <a href=\"generateAndRun\">ant build.xml and run</a></li>&#160;</p>",
                        true, false);
                text.addHyperlinkListener(new IHyperlinkListener() {

                    @Override
                    public void linkExited(final HyperlinkEvent e) {

                    }

                    @Override
                    public void linkEntered(HyperlinkEvent e) {
                    }

                    @Override
                    public void linkActivated(HyperlinkEvent e) {
                        try {
                            if ("generateAndRun".equals(e.getHref())) {
                                executeExport();
                            } else {
                                executeGenerateAnt();
                            }
                        } catch (Exception e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                        }
                    }
                });
            }

            section.setClient(sectionClient);
        }

        int index = addPage(composite);
        setPageText(index, "Overview");
    }

    private void createPageDeploy(final AntTask task) {
        Composite composite = new Composite(getContainer(), SWT.NONE);
        FillLayout layout = new FillLayout();
        composite.setLayout(layout);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
                JavaFXUIPlugin.PLUGIN_ID + ".JFXBuildConfigurationEditor_deploy");

        // TODO
        final WritableValue bean = new WritableValue();
        bean.setValue(task);

        toolkit = new FormToolkit(composite.getDisplay());

        final Form form = toolkit.createForm(composite);
        form.setText("FX Build Configuration");
        form.setImage(getTitleImage());
        form.getBody().setLayout(new FillLayout());
        toolkit.decorateFormHeading(form);

        initToolbar(form);

        ScrolledForm scrolledForm = toolkit.createScrolledForm(form.getBody());
        scrolledForm.getBody().setLayout(new GridLayout(2, false));
        Composite sectionParent = scrolledForm.getBody();

        dbc = new DataBindingContext();
        IWidgetValueProperty textModify = WidgetProperties.text(SWT.Modify);
        IWidgetValueProperty selChange = WidgetProperties.selection();

        {
            Section section = toolkit.createSection(sectionParent,
                    Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED);
            section.setText("Deploy Properties");
            section.setDescription("The following properties are needed to create a Java Webstart Deployment");
            section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

            Composite sectionClient = toolkit.createComposite(section);
            final int COLUMN_COUNT = 3;
            sectionClient.setLayout(new GridLayout(COLUMN_COUNT, false));

            {
                toolkit.createLabel(sectionClient, "Applet Width*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.horizontalSpan = COLUMN_COUNT - 1;
                t.setLayoutData(gd);
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__WIDTH));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Applet Height*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.horizontalSpan = COLUMN_COUNT - 1;
                t.setLayoutData(gd);
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__HEIGHT));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                Button b = toolkit.createButton(sectionClient, "Embed JNLP", SWT.CHECK);
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, COLUMN_COUNT, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__EMBEDJNLP));
                dbc.bindValue(selChange.observe(b), prop.observeDetail(bean));
            }

            {
                Button b = toolkit.createButton(sectionClient, "Treat files as extensions", SWT.CHECK);
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, COLUMN_COUNT, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__EXTENSION));
                dbc.bindValue(selChange.observe(b), prop.observeDetail(bean));
            }

            {
                Button b = toolkit.createButton(sectionClient, "Include deployment toolkit", SWT.CHECK);
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, COLUMN_COUNT, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__INCLUDE_DT));
                dbc.bindValue(selChange.observe(b), prop.observeDetail(bean));
            }

            {
                Button b = toolkit.createButton(sectionClient, "Native Package", SWT.CHECK);
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, COLUMN_COUNT, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__NATIVE_PACKAGE));
                dbc.bindValue(selChange.observe(b), prop.observeDetail(bean));
            }

            {
                Button b = toolkit.createButton(sectionClient, "Offline allowed", SWT.CHECK);
                b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, COLUMN_COUNT, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__OFFLINE_ALLOWED));
                dbc.bindValue(selChange.observe(b), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Placeholder Ref.*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.horizontalSpan = COLUMN_COUNT - 1;
                t.setLayoutData(gd);
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__PLACEHOLDERREF));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Placeholder ID*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.horizontalSpan = COLUMN_COUNT - 1;
                t.setLayoutData(gd);
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__PLACEHOLDERID));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "HTML Template:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__TEMPLATE, TEMPLATE__FILE));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
                Button b = toolkit.createButton(sectionClient, "Workspace ...", SWT.NONE);
                b.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(final SelectionEvent e) {
                        FilteredResourcesSelectionDialog d = new FilteredResourcesSelectionDialog(
                                getSite().getShell(), false,
                                ((IFileEditorInput) getEditorInput()).getFile().getProject(), IResource.FILE) {
                            @Override
                            protected IStatus validateItem(final Object item) {
                                IFile f = (IFile) item;
                                if (f.getParent() instanceof IProject) {
                                    return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                                            "The selected resource has to be part of the source folder");
                                }
                                if (!f.getName().endsWith(JavaFXUIPlugin.FILEEXTENSION_HTML_TEMPLATE)) {
                                    return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                                            "The selected resource does not seem to be a html file");
                                }
                                return super.validateItem(item);
                            }
                        };

                        if (d.open() == ResourceSelectionDialog.OK) {
                            Object[] rv = d.getResult();
                            if (rv.length == 1) {
                                IFile f = (IFile) rv[0];
                                IJavaElement j = JavaCore.create(f.getParent());
                                String template = null;
                                if (j instanceof IPackageFragment) {
                                    IPackageFragment p = (IPackageFragment) j;
                                    template = p.getElementName().replace('.', '/') + "/" + f.getName();
                                } else if (j instanceof IPackageFragmentRoot) {
                                    IPackageFragmentRoot p = (IPackageFragmentRoot) j;
                                    template = f.getName();
                                } else {
                                    MessageDialog.openInformation(getSite().getShell(), "Not valid",
                                            "The selected resource has to be part of the source folder");
                                }
                                if (template != null) {
                                    if (getTask().getDeploy().getTemplate() == null) {
                                        Command cmd = new SetCommand(editingDomain, getTask().getDeploy(),
                                                DEPLOY__TEMPLATE, ParametersFactory.eINSTANCE.createTemplate());
                                        if (cmd.canExecute()) {
                                            cmd.execute();
                                        }
                                    }
                                    Command cmd = new SetCommand(editingDomain, getTask().getDeploy().getTemplate(),
                                            TEMPLATE__FILE, template);
                                    if (cmd.canExecute()) {
                                        cmd.execute();
                                    }
                                }
                            }
                        }
                    }
                });
            }

            {
                toolkit.createLabel(sectionClient, "Template Output File:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.horizontalSpan = COLUMN_COUNT - 1;
                t.setLayoutData(gd);
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__DEPLOY, DEPLOY__TEMPLATE, TEMPLATE__TO_FILE));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Webstart Splash:")
                        .setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
                Composite container = toolkit.createComposite(sectionClient);
                GridLayout gl = new GridLayout(2, false);
                gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = gl.marginTop = gl.marginWidth = 0;
                container.setLayout(gl);
                GridData gdContainer = new GridData(GridData.FILL_HORIZONTAL);
                gdContainer.horizontalSpan = COLUMN_COUNT - 1;
                container.setLayoutData(gdContainer);

                Composite tableContainer = toolkit.createComposite(container);
                Table t = toolkit.createTable(tableContainer,
                        SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
                t.setHeaderVisible(true);
                t.setLinesVisible(true);

                GridData gdTable = new GridData(GridData.FILL_HORIZONTAL);
                gdTable.heightHint = t.getItemHeight() * 5;
                tableContainer.setLayoutData(gdTable);

                TableColumnLayout tablelayout = new TableColumnLayout();

                final TableViewer v = new TableViewer(t);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.heightHint = t.getItemHeight() * 5;
                v.getControl().setLayoutData(gd);
                v.setContentProvider(ArrayContentProvider.getInstance());

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(final Object element) {
                            return ((Splash) element).getMode().getName();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(10, 100, false));
                    c.getColumn().setText("Mode");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(final Object element) {
                            return ((Splash) element).getHref();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(90));
                    c.getColumn().setText("URL");
                }
                tableContainer.setLayout(tablelayout);
                v.setInput(task.getDeploy().getInfo().getSplash());

                Composite buttonComp = toolkit.createComposite(container);
                buttonComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.END, false, false));
                buttonComp.setLayout(new GridLayout());

                {
                    Button b = toolkit.createButton(buttonComp, "Add ...", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            if (handleAddSplash()) {
                                v.setInput(task.getDeploy().getInfo().getSplash());
                                v.setSelection(new StructuredSelection(task.getDeploy().getInfo().getSplash()
                                        .get(task.getDeploy().getInfo().getSplash().size() - 1)));
                            }
                        }
                    });
                }

                {
                    Button b = toolkit.createButton(buttonComp, "Remove", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            Splash value = (Splash) ((IStructuredSelection) v.getSelection()).getFirstElement();
                            if (value != null) {
                                if (handleRemoveSplash(value)) {
                                    v.setInput(getTask().getDeploy().getInfo().getSplash());
                                }
                            } else {
                                MessageDialog.openWarning(getSite().getShell(), "Warning",
                                        "Please select an entry");
                            }
                        }
                    });
                }
            }

            {
                toolkit.createLabel(sectionClient, "Webstart Icons:")
                        .setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
                Composite container = toolkit.createComposite(sectionClient);
                GridLayout gl = new GridLayout(2, false);
                gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = gl.marginTop = gl.marginWidth = 0;
                container.setLayout(gl);
                GridData gdContainer = new GridData(GridData.FILL_HORIZONTAL);
                gdContainer.horizontalSpan = COLUMN_COUNT - 1;
                container.setLayoutData(gdContainer);

                Composite tableContainer = toolkit.createComposite(container);
                Table t = toolkit.createTable(tableContainer,
                        SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
                t.setHeaderVisible(true);
                t.setLinesVisible(true);

                GridData gdTable = new GridData(GridData.FILL_HORIZONTAL);
                gdTable.heightHint = t.getItemHeight() * 5;
                tableContainer.setLayoutData(gdTable);

                TableColumnLayout tablelayout = new TableColumnLayout();

                final TableViewer v = new TableViewer(t);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.heightHint = t.getItemHeight() * 5;
                v.getControl().setLayoutData(gd);
                v.setContentProvider(ArrayContentProvider.getInstance());

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((Icon) element).getDepth();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(10, 50, false));
                    c.getColumn().setText("Depth");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((Icon) element).getKind().getName();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(10, 100, false));
                    c.getColumn().setText("Kind");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((Icon) element).getWidth();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(10, 50, false));
                    c.getColumn().setText("Width");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((Icon) element).getHeight();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(10, 50, false));
                    c.getColumn().setText("Height");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((Icon) element).getHref();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(60));
                    c.getColumn().setText("Url");
                }
                tableContainer.setLayout(tablelayout);
                v.setInput(task.getDeploy().getInfo().getIcon());

                Composite buttonComp = toolkit.createComposite(container);
                buttonComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.END, false, false));
                buttonComp.setLayout(new GridLayout());

                {
                    Button b = toolkit.createButton(buttonComp, "Add ...", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            if (handleAddIcon()) {
                                v.setInput(task.getDeploy().getInfo().getIcon());
                                v.setSelection(new StructuredSelection(task.getDeploy().getInfo().getIcon()
                                        .get(task.getDeploy().getInfo().getIcon().size() - 1)));
                            }
                        }
                    });
                }

                {
                    Button b = toolkit.createButton(buttonComp, "Remove", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            Icon value = (Icon) ((IStructuredSelection) v.getSelection()).getFirstElement();
                            if (value != null) {
                                if (handleRemoveIcon(value)) {
                                    v.setInput(task.getDeploy().getInfo().getIcon());
                                }
                            } else {
                                MessageDialog.openWarning(getSite().getShell(), "Warning",
                                        "Please select an entry");
                            }
                        }
                    });
                }
            }

            {
                toolkit.createLabel(sectionClient, "Additional META-INF files:")
                        .setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
                Composite container = toolkit.createComposite(sectionClient);
                GridLayout gl = new GridLayout(2, false);
                gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = gl.marginTop = gl.marginWidth = 0;
                container.setLayout(gl);
                GridData gdContainer = new GridData(GridData.FILL_HORIZONTAL);
                gdContainer.horizontalSpan = COLUMN_COUNT - 1;
                container.setLayoutData(gdContainer);

                Composite tableContainer = toolkit.createComposite(container);
                Table t = toolkit.createTable(tableContainer,
                        SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
                t.setHeaderVisible(true);
                t.setLinesVisible(true);

                GridData gdTable = new GridData(GridData.FILL_HORIZONTAL);
                gdTable.heightHint = t.getItemHeight() * 5;
                tableContainer.setLayoutData(gdTable);

                TableColumnLayout tablelayout = new TableColumnLayout();

                final TableViewer v = new TableViewer(t);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.heightHint = t.getItemHeight() * 5;
                v.getControl().setLayoutData(gd);
                v.setContentProvider(ArrayContentProvider.getInstance());

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((KeyValuePair) element).getKey();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(33));
                    c.getColumn().setText("Folder");
                }

                {
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((KeyValuePair) element).getValue();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(67));
                    c.getColumn().setText("File");
                }
                tableContainer.setLayout(tablelayout);
                v.setInput(task.getFiles());

                Composite buttonComp = toolkit.createComposite(container);
                buttonComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.END, false, false));
                buttonComp.setLayout(new GridLayout());

                {
                    Button b = toolkit.createButton(buttonComp, "Add ...", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            if (handleAddMetaInfFile()) {
                                v.setInput(task.getFiles());
                                v.setSelection(
                                        new StructuredSelection(task.getFiles().get(task.getFiles().size() - 1)));
                            }
                        }
                    });
                }

                {
                    Button b = toolkit.createButton(buttonComp, "Remove", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            KeyValuePair value = (KeyValuePair) ((IStructuredSelection) v.getSelection())
                                    .getFirstElement();
                            if (value != null) {
                                if (handleRemoveMetaInfFile(value)) {
                                    v.setInput(task.getFiles());
                                }
                            } else {
                                MessageDialog.openWarning(getSite().getShell(), "Warning",
                                        "Please select an entry");
                            }
                        }
                    });
                }
            }

            {
                toolkit.createLabel(sectionClient, "Fonts:")
                        .setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
                Composite container = toolkit.createComposite(sectionClient);
                GridLayout gl = new GridLayout(2, false);
                gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = gl.marginTop = gl.marginWidth = 0;
                container.setLayout(gl);
                GridData gdContainer = new GridData(GridData.FILL_HORIZONTAL);
                gdContainer.horizontalSpan = COLUMN_COUNT - 1;
                container.setLayoutData(gdContainer);

                Composite tableContainer = toolkit.createComposite(container);
                Table t = toolkit.createTable(tableContainer,
                        SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
                t.setHeaderVisible(true);
                t.setLinesVisible(true);

                GridData gdTable = new GridData(GridData.FILL_HORIZONTAL);
                gdTable.heightHint = t.getItemHeight() * 5;
                tableContainer.setLayoutData(gdTable);

                TableColumnLayout tablelayout = new TableColumnLayout();

                final TableViewer v = new TableViewer(t);
                GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.heightHint = t.getItemHeight() * 5;
                v.getControl().setLayoutData(gd);
                final ArrayContentProvider cp = new ArrayContentProvider();
                v.setContentProvider(cp);

                {
                    IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                            ParametersPackage.Literals.KEY_VALUE_PAIR__KEY);
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    TableColumn tc = c.getColumn();
                    tc.setText("Font name");
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((KeyValuePair) element).getKey();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(33));
                }

                {
                    IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                            ParametersPackage.Literals.KEY_VALUE_PAIR__VALUE);
                    TableViewerColumn c = new TableViewerColumn(v, SWT.NONE);
                    TableColumn tc = c.getColumn();
                    tc.setText("File");
                    c.setLabelProvider(new ColumnLabelProvider() {
                        @Override
                        public String getText(Object element) {
                            return ((KeyValuePair) element).getValue();
                        }
                    });
                    tablelayout.setColumnData(c.getColumn(), new ColumnWeightData(67));
                }
                tableContainer.setLayout(tablelayout);
                v.setInput(task.getFonts());

                Composite buttonComp = toolkit.createComposite(container);
                buttonComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.END, false, false));
                buttonComp.setLayout(new GridLayout());

                {
                    Button b = toolkit.createButton(buttonComp, "Add ...", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            if (handleAddFont()) {
                                final KeyValuePair newFont = task.getFonts().get(task.getFonts().size() - 1);
                                v.refresh();
                                v.setSelection(new StructuredSelection(newFont));
                            }
                        }
                    });
                }

                {
                    Button b = toolkit.createButton(buttonComp, "Remove", SWT.PUSH);
                    b.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
                    b.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            KeyValuePair value = (KeyValuePair) ((IStructuredSelection) v.getSelection())
                                    .getFirstElement();
                            if (value != null) {
                                if (handleRemoveFont(value)) {
                                    v.setInput(task.getFonts());
                                }
                            } else {
                                MessageDialog.openWarning(getSite().getShell(), "Warning",
                                        "Please select an entry");
                            }
                        }
                    });
                }
            }
            section.setClient(sectionClient);
        }
        int index = addPage(composite);
        setPageText(index, "Deploy");
    }

    /**
     * initialize tool bar for a form.
     */
    private void initToolbar(final Form form) {
        IToolBarManager mgr = form.getToolBarManager();
        // TODO do not use the hard coded image name here
        mgr.add(new Action("Build & Export FX Application", ImageDescriptor
                .createFromURL(getClass().getClassLoader().getResource("/icons/exportrunnablejar_wiz.gif"))) {
            @Override
            public void run() {
                try {
                    executeExport();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        // mgr.add(new Action("Export Ant File",ImageDescriptor.createFromURL(getClass().getClassLoader().getResource("/icons/exportAnt_co.gif"))) {
        // @Override
        // public void run() {
        //
        // }
        // });
        form.updateToolBar();
    }

    /**
     * handleRemoveMetaInfFile.
     * 
     * @param value
     *            the value to delete
     * @return true if value was deleted, and false otherwise.
     */
    private boolean handleRemoveMetaInfFile(final KeyValuePair value) {
        if (MessageDialog.openConfirm(getSite().getShell(), "Confirm delete",
                "Would really like to remove the selected META-INF file")) {
            RemoveCommand cmd = new RemoveCommand(editingDomain, getTask().getFiles(), value);
            if (cmd.canExecute()) {
                cmd.execute();
                return true;
            }
        }
        return false;
    }

    /**
     * handleRemoveFont.
     * 
     * @param value
     *            the value to delete
     * @return true if value was deleted, and false otherwise.
     */
    private boolean handleRemoveFont(final KeyValuePair value) {
        if (MessageDialog.openConfirm(getSite().getShell(), "Confirm delete",
                "Would really like to remove the selected font")) {
            RemoveCommand cmd = new RemoveCommand(editingDomain, getTask().getFonts(), value);
            if (cmd.canExecute()) {
                cmd.execute();
                return true;
            }
        }
        return false;
    }

    /**
     * handleAddService.
     * 
     * @return the return code
     * 
     * @see TitleAreaDialog#open()
     */
    private boolean handleAddMetaInfFile() {
        AddMetaInfFileDialog d = new AddMetaInfFileDialog(getSite().getShell(), editingDomain, getTask(),
                ((IFileEditorInput) getEditorInput()).getFile().getProject().getWorkspace().getRoot());
        return d.open() == TitleAreaDialog.OK;
    }

    /**
     * handleAddFont.
     * 
     * @return the return code
     * 
     * @see TitleAreaDialog#open()
     */
    private boolean handleAddFont() {
        AddFontDialog d = new AddFontDialog(getSite().getShell(), editingDomain, getTask(),
                ((IFileEditorInput) getEditorInput()).getFile().getProject());
        return d.open() == TitleAreaDialog.OK;
    }

    private void createPageSigning(AntTask task) {
        Composite composite = new Composite(getContainer(), SWT.NONE);
        FillLayout layout = new FillLayout();
        composite.setLayout(layout);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
                JavaFXUIPlugin.PLUGIN_ID + ".JFXBuildConfigurationEditor_signing");

        final WritableValue bean = new WritableValue();
        bean.setValue(task);

        toolkit = new FormToolkit(composite.getDisplay());

        final Form form = toolkit.createForm(composite);
        form.setText("FX Build Configuration");
        form.setImage(getTitleImage());
        form.getBody().setLayout(new FillLayout());
        toolkit.decorateFormHeading(form);

        initToolbar(form);

        ScrolledForm scrolledForm = toolkit.createScrolledForm(form.getBody());
        scrolledForm.getBody().setLayout(new GridLayout(2, false));
        Composite sectionParent = scrolledForm.getBody();

        dbc = new DataBindingContext();
        IWidgetValueProperty textModify = WidgetProperties.text(SWT.Modify);

        {
            Section section = toolkit.createSection(sectionParent,
                    Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED);
            section.setText("Signing Properties");
            section.setDescription("Information for signing result jar");
            section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

            Composite sectionClient = toolkit.createComposite(section);
            sectionClient.setLayout(new GridLayout(4, false));

            {
                toolkit.createLabel(sectionClient, "Alias*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__SIGNJAR, SIGN_JAR__ALIAS));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Key-Password*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__SIGNJAR, SIGN_JAR__KEYPASS));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Keystore*:");
                final Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
                toolkit.createButton(sectionClient, "Filesystem ...", SWT.PUSH)
                        .addSelectionListener(new SelectionAdapter() {
                            @Override
                            public void widgetSelected(final SelectionEvent e) {
                                String v = handleKeyStoreFilesystemSelection(t.getShell());
                                if (v != null) {
                                    t.setText(v);
                                }
                            }
                        });
                toolkit.createButton(sectionClient, "Workspace ...", SWT.PUSH)
                        .addSelectionListener(new SelectionAdapter() {
                            @Override
                            public void widgetSelected(final SelectionEvent e) {
                                String v = handleKeyStoreWorkspaceSelection(t.getShell());
                                if (v != null) {
                                    t.setText(v);
                                }
                            }
                        });
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__SIGNJAR, SIGN_JAR__KEYSTORE));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Store-Password*:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__SIGNJAR, SIGN_JAR__STOREPASS));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            {
                toolkit.createLabel(sectionClient, "Storetype:");
                Text t = toolkit.createText(sectionClient, "", SWT.BORDER);
                t.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
                IEMFValueProperty prop = EMFEditProperties.value(editingDomain,
                        FeaturePath.fromList(ANT_TASK__SIGNJAR, SIGN_JAR__STORETYPE));
                dbc.bindValue(textModify.observeDelayed(DELAY, t), prop.observeDetail(bean));
            }

            section.setClient(sectionClient);
        }

        int index = addPage(composite);
        setPageText(index, "Signing");
    }

    /**
     * handleRemoveManifestAttr.
     * 
     * @param value
     *            the value to delete
     * @return true if value was deleted, and false otherwise.
     */
    private boolean handleRemoveManifestAttr(final Param value) {
        if (MessageDialog.openConfirm(getSite().getShell(), "Confirm delete",
                "Would really like to remove the selected attribute")) {
            RemoveCommand cmd = new RemoveCommand(editingDomain, getTask().getManifestEntries(), value);
            if (cmd.canExecute()) {
                cmd.execute();
                return true;
            }
        }
        return false;
    }

    /**
     * handleAddManifestAttr.
     * 
     * @return the return code
     * 
     * @see TitleAreaDialog#open()
     */
    private boolean handleAddManifestAttr(Shell shell) {
        AddManifestAttributeDialog d = new AddManifestAttributeDialog(getSite().getShell(), editingDomain,
                getTask());
        return d.open() == TitleAreaDialog.OK;
    }

    private String handleSplashImage(Shell shell) {
        FilteredResourcesSelectionDialog d = new FilteredResourcesSelectionDialog(shell, false,
                ((IFileEditorInput) getEditorInput()).getFile().getProject(), IResource.FILE) {
            @Override
            protected IStatus validateItem(Object item) {
                IFile f = (IFile) item;
                if (f.getParent() instanceof IProject) {
                    return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                            "The selected resource has to part of the source folder");
                }
                return super.validateItem(item);
            }
        };
        if (d.open() == ResourceSelectionDialog.OK) {
            Object[] rv = d.getResult();
            if (rv.length == 1) {
                IFile f = (IFile) rv[0];
                IJavaElement j = JavaCore.create(f.getParent());
                if (j instanceof IPackageFragment) {
                    IPackageFragment p = (IPackageFragment) j;
                    return p.getElementName().replace('.', '/') + "/" + f.getName();
                } else if (j instanceof IPackageFragmentRoot) {
                    return f.getName();
                } else {
                    MessageDialog.openInformation(shell, "Not valid",
                            "The selected resource has to part of the source folder");
                }
            }
        }
        return null;
    }

    /**
     * handleRemoveIcon.
     * 
     * @param value
     *            the value to delete
     * @return true if value was deleted, and false otherwise.
     */
    private boolean handleRemoveIcon(final Icon value) {
        if (MessageDialog.openConfirm(getSite().getShell(), "Confirm delete",
                "Would really like to remove the selected icon")) {
            RemoveCommand cmd = new RemoveCommand(editingDomain, getTask().getDeploy().getInfo().getIcon(), value);
            if (cmd.canExecute()) {
                cmd.execute();
                return true;
            }
        }
        return false;
    }

    /**
     * handleAddIcon.
     * 
     * @return the return code
     * 
     * @see TitleAreaDialog#open()
     */
    private boolean handleAddIcon() {
        AddIconDialog d = new AddIconDialog(getSite().getShell(), editingDomain, getTask());
        return d.open() == TitleAreaDialog.OK;
    }

    /**
     * handleAddSplash.
     * 
     * @return the return code
     * 
     * @see TitleAreaDialog#open()
     */
    private boolean handleAddSplash() {
        AddSplashDialog d = new AddSplashDialog(getSite().getShell(), editingDomain, getTask());
        return d.open() == TitleAreaDialog.OK;
    }

    /**
     * handleRemoveSplash.
     * 
     * @param value
     *            the value to delete
     * @return true if value was deleted, and false otherwise.
     */
    private boolean handleRemoveSplash(final Splash value) {
        if (MessageDialog.openConfirm(getSite().getShell(), "Confirm delete",
                "Would really like to remove the selected splash")) {
            RemoveCommand cmd = new RemoveCommand(editingDomain, getTask().getDeploy().getInfo().getSplash(),
                    value);
            if (cmd.canExecute()) {
                cmd.execute();
                return true;
            }
        }
        return false;
    }

    private String handleBuildFilesystemDirectorySelection(final Shell parent) {
        DirectoryDialog dialog = new DirectoryDialog(parent);
        return dialog.open();
    }

    private String handleBuildWorkbenchDirectorySelection(final Shell parent) {
        ILabelProvider lp = new WorkbenchLabelProvider();
        ITreeContentProvider cp = new WorkbenchContentProvider();

        Class<?>[] acceptedClasses = new Class[] { IProject.class, IFolder.class };
        ViewerFilter filter = new TypedViewerFilter(acceptedClasses);

        FolderSelectionDialog dialog = new FolderSelectionDialog(parent, lp, cp);
        dialog.setTitle("Output directory");
        dialog.setMessage("Select output directory");
        dialog.addFilter(filter);
        dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
        if (dialog.open() == Window.OK) {
            IContainer c = (IContainer) dialog.getFirstResult();
            if (c.getProject() == ((IFileEditorInput) getEditorInput()).getFile().getProject()) {
                return "${project}/" + c.getProjectRelativePath().toString();
            } else {
                return "${workspace}/" + c.getProject().getName() + "/" + c.getProjectRelativePath().toString();
            }
        }
        return null;
    }

    private String handleRootclassSelection(Shell parent) {
        IFileEditorInput i = (IFileEditorInput) getEditorInput();
        IJavaProject project = JavaCore.create(i.getFile().getProject());
        if (project == null) {
            return null;
        }

        IJavaElement[] elements = new IJavaElement[] { project };

        int constraints = IJavaSearchScope.SOURCES;
        constraints |= IJavaSearchScope.APPLICATION_LIBRARIES;

        IJavaSearchScope searchScope = SearchEngine.createJavaSearchScope(elements, constraints);
        BusyIndicatorRunnableContext context = new BusyIndicatorRunnableContext();

        MainTypeSelectionDialog dialog = new MainTypeSelectionDialog(parent, context, searchScope, 0);
        dialog.setTitle("Find class");
        dialog.setMessage("Find the class used to launch the application");
        if (dialog.open() == Window.CANCEL) {
            return null;
        }
        Object[] results = dialog.getResult();
        IType type = (IType) results[0];
        if (type != null) {
            return type.getFullyQualifiedName();
        }

        return null;
    }

    private String handlePreloaderclassSelection(Shell parent) {
        IFileEditorInput i = (IFileEditorInput) getEditorInput();
        IJavaProject project = JavaCore.create(i.getFile().getProject());
        if (project == null) {
            return null;
        }

        try {
            IType superType = project.findType("javafx.application.Preloader");

            IJavaSearchScope searchScope = SearchEngine.createStrictHierarchyScope(project, superType, true, false,
                    null);

            SelectionDialog dialog = JavaUI.createTypeDialog(parent, PlatformUI.getWorkbench().getProgressService(),
                    searchScope, IJavaElementSearchConstants.CONSIDER_CLASSES, false, "");
            dialog.setTitle("Find Preloader");
            if (dialog.open() == Window.OK) {
                IType type = (IType) dialog.getResult()[0];
                return type.getFullyQualifiedName('$');
            }
        } catch (JavaModelException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

    private String handleKeyStoreFilesystemSelection(Shell parent) {
        FileDialog dialog = new FileDialog(parent, SWT.OPEN);
        String keystore = dialog.open();
        if (keystore != null) {
            IStatus s = validateKeyStore(new File(keystore));
            if (s.isOK()) {
                return keystore;
            } else {
                MessageDialog.openError(parent, "Not a keystore", "Looks like the selected file is not a keystore");
                return handleKeyStoreFilesystemSelection(parent);
            }
        }
        return null;
    }

    private String handleKeyStoreWorkspaceSelection(Shell parent) {
        ILabelProvider lp = new WorkbenchLabelProvider();
        ITreeContentProvider cp = new WorkbenchContentProvider();

        ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(parent, lp, cp);
        dialog.setValidator(new ISelectionStatusValidator() {

            @Override
            public IStatus validate(final Object[] selection) {
                if (selection.length > 1) {
                    return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID, "Only one file allowed.");
                } else if (selection.length == 1) {
                    if (selection[0] instanceof IFile) {
                        IFile f = (IFile) selection[0];
                        return validateKeyStore(f.getLocation().toFile());
                    }
                }
                return Status.OK_STATUS;
            }
        });
        dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());

        if (dialog.open() == Window.OK) {
            IFile f = (IFile) dialog.getFirstResult();
            if (f != null) {
                if (f.getProject() == ((IFileEditorInput) getEditorInput()).getFile().getProject()) {
                    return "${project}/" + f.getProjectRelativePath().toString();
                } else {
                    return "${workspace}/" + f.getProject().getName() + "/" + f.getProjectRelativePath().toString();
                }
            }
        }
        return null;
    }

    private IStatus validateKeyStore(final File f) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(f);
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(fis, null);
        } catch (FileNotFoundException e) {
            return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                    "The keystore file '" + f.getAbsolutePath() + "' is not found.", e);
        } catch (KeyStoreException e) {
            return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID, "Unable to initialize keystore", e);
        } catch (NoSuchAlgorithmException e) {
            return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                    "Loading keystore failed. Is this a valid keystore?", e);
        } catch (CertificateException e) {
            return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                    "Loading keystore failed. Is this a valid keystore?", e);
        } catch (IOException e) {
            if (e.getCause() instanceof UnrecoverableKeyException) {
                return Status.OK_STATUS;
            }
            return new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID,
                    "Loading keystore failed. Is this a valid keystore?", e);
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                }
            }
        }
        return Status.OK_STATUS;
    }

    @Override
    protected void pageChange(int newPageIndex) {
        dbc.updateTargets();
    }

    @Override
    public Object getAdapter(@SuppressWarnings("rawtypes") final Class adapter) {
        // TODO we could show an outline page here
        return super.getAdapter(adapter);
    }

    /**
     * If there is more than one page in the multi-page editor part, this shows the tabs at the bottom. <!-- begin-user-doc --> <!-- end-user-doc -->
     * 
     * @generated
     */
    private void showTabs() {
        if (getPageCount() > 1) {
            setPageText(0, "Selection");
            if (getContainer() instanceof CTabFolder) {
                ((CTabFolder) getContainer()).setTabHeight(SWT.DEFAULT);
                Point point = getContainer().getSize();
                getContainer().setSize(point.x, point.y - 6);
            }
        }
    }

    /**
     * @throws Exception
     *             exception
     */
    private void executeExport() throws Exception {
        if (validateAndShowErrors()) {
            IHandlerService hs = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
            hs.executeCommand("at.bestsolution.efxclipse.tooling.jdt.ui.export", null);
        }
    }

    /**
     * @throws Exception
     *             exception
     */
    private void executeGenerateAnt() throws Exception {
        if (validateAndShowErrors()) {
            IHandlerService hs = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
            hs.executeCommand("at.bestsolution.efxclipse.tooling.jdt.ui.generateAnt", null);
        }
    }

    /**
     * @return <true> if build configuration is valid, <false> otherwise
     */
    private boolean validateAndShowErrors() {
        MultiStatus status = new MultiStatus(JavaFXUIPlugin.PLUGIN_ID, IStatus.OK, null, null);
        // dirty
        if (isDirty()) {
            boolean option = MessageDialog.openQuestion(getSite().getShell(), "Save FX Build Configuration",
                    getEditorInput().getName()
                            + " must be saved before generating ant build.xml file.\nSave changes now?");
            if (option) {
                doSave(new NullProgressMonitor());
            } else {
                return false;
            }
        }
        // height
        if (getTask().getDeploy().getHeight() != null && getTask().getDeploy().getHeight().length() > 0) {
            try {
                Integer.parseInt(getTask().getDeploy().getHeight());
            } catch (Exception e) {
                status.add(new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID, "Height must be an integer value"));
            }
        }
        // width
        if (getTask().getDeploy().getWidth() != null && getTask().getDeploy().getWidth().length() > 0) {
            try {
                Integer.parseInt(getTask().getDeploy().getWidth());
            } catch (Exception e) {
                status.add(new Status(IStatus.ERROR, JavaFXUIPlugin.PLUGIN_ID, "Width must be an integer value"));
            }
        }
        // Show the collected errors
        if (!status.isOK()) {
            StringBuffer errors = new StringBuffer();
            for (IStatus err : status.getChildren()) {
                errors.append(err.getMessage()).append("\n");
            }
            MessageDialog.openWarning(getSite().getShell(), "Invalid FX Build configuration", errors.toString());
        }
        return status.isOK();
    }
}

/**
 * Implementation of a cell label provider which provides support for formatting using {@link MessageFormat#format(String, Object...)}
 */
class GenericMapCellLabelProvider extends ObservableMapCellLabelProvider {
    private IObservableMap[] attributeMaps;
    private String messagePattern;

    /**
     * Create a new label provider
     * 
     * @param messagePattern
     *            the message pattern
     * @param attributeMaps
     *            the values to observe
     */
    public GenericMapCellLabelProvider(String messagePattern, IObservableMap... attributeMaps) {
        super(attributeMaps);
        this.messagePattern = messagePattern;
        this.attributeMaps = attributeMaps;
    }

    @Override
    public void update(ViewerCell cell) {
        Object element = cell.getElement();
        Object[] values = new Object[attributeMaps.length];
        int i = 0;
        for (IObservableMap m : attributeMaps) {
            values[i++] = m.get(element);
            if (values[i - 1] == null) {
                cell.setText(""); //$NON-NLS-1$
                return;
            }
        }
        cell.setText(MessageFormat.format(messagePattern, values));
    }
}