org.eclipse.jst.j2ee.internal.ui.JavaEEDeploymentAssemblyAdvancedSectionBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jst.j2ee.internal.ui.JavaEEDeploymentAssemblyAdvancedSectionBuilder.java

Source

/*******************************************************************************
 * Copyright (c) 2011 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jst.j2ee.internal.ui;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEUIPlugin;
import org.eclipse.jst.j2ee.project.JavaEEProjectUtilities;
import org.eclipse.jst.j2ee.project.facet.IJ2EEFacetConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.wst.common.componentcore.internal.ComponentResource;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.componentcore.internal.impl.TaskModel;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.ui.internal.propertypage.ResourceMappingFilterExtensionRegistry;
import org.eclipse.wst.common.componentcore.ui.propertypage.AddModuleDependenciesPropertiesPage;
import org.eclipse.wst.common.componentcore.ui.propertypage.AddModuleDependenciesPropertiesPage.ComponentResourceProxy;
import org.eclipse.wst.common.componentcore.ui.propertypage.IReferenceWizardConstants;

/**
 * This is a helper class to build and handle the logic of the "Advanced" section 
 * of the Deployment Assembly page that is common to all the Java EE modules (EAR
 * project, Web project, etc.)
 *  
 */

public class JavaEEDeploymentAssemblyAdvancedSectionBuilder
        implements IJavaEEDeploymentAssemblySectionBuilder, SelectionListener {

    private Label defaulDDFolderLabel;
    private Combo rootSourceMappings;

    private IVirtualComponent rootComponent;
    private AddModuleDependenciesPropertiesPage page;
    private String currentSelectedDDFolder = null;
    private List<String> resourceMappingsList = new ArrayList<String>();
    boolean shouldDisplaySection;

    String folderToLook;
    String fileToLook;
    String projectType;

    public JavaEEDeploymentAssemblyAdvancedSectionBuilder(IVirtualComponent component,
            AddModuleDependenciesPropertiesPage page) {
        rootComponent = component;
        this.page = page;
        shouldDisplaySection = !JavaEEProjectUtilities.isUtilityProject(rootComponent.getProject());
        IVirtualFolder rootFolder = rootComponent.getRootFolder();
        IPath defaultDDFolder = J2EEModuleVirtualComponent.getDefaultDeploymentDescriptorFolder(rootFolder);
        shouldDisplaySection &= (defaultDDFolder == null);
        projectType = JavaEEProjectUtilities.getJ2EEProjectType(component.getProject());
        if (projectType.equals(IJ2EEFacetConstants.APPLICATION_CLIENT)) {
            folderToLook = J2EEConstants.META_INF;
            fileToLook = J2EEConstants.APP_CLIENT_DD_URI;
        } else if (projectType.equals(IJ2EEFacetConstants.JCA)) {
            folderToLook = J2EEConstants.META_INF;
            fileToLook = J2EEConstants.RAR_DD_URI;
        } else if (projectType.equals(IJ2EEFacetConstants.EJB)) {
            folderToLook = J2EEConstants.META_INF;
            fileToLook = J2EEConstants.EJBJAR_DD_URI;
        } else if (projectType.equals(IJ2EEFacetConstants.DYNAMIC_WEB)) {
            folderToLook = J2EEConstants.WEB_INF;
            fileToLook = J2EEConstants.WEBAPP_DD_URI;
        } else if (projectType.equals(IJ2EEFacetConstants.ENTERPRISE_APPLICATION)) {
            folderToLook = J2EEConstants.META_INF;
            fileToLook = J2EEConstants.APPLICATION_DD_URI;
        } else if (projectType.equals(IJ2EEFacetConstants.WEBFRAGMENT)) {
            folderToLook = J2EEConstants.META_INF;
            fileToLook = J2EEConstants.WEBFRAGMENT_DD_URI;
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.jst.j2ee.internal.ui.IJavaEEDeploymentAssemblySectionBuilder#buildSection(org.eclipse.swt.widgets.Composite)
     */
    public void buildSection(Composite parent) {
        if (shouldDisplaySection()) {
            Composite advancedSectionComposite = createAdvancedSection(parent);
            addDefaultDeploymentDescriptorFolderFields(advancedSectionComposite);
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.jst.j2ee.internal.ui.IJavaEEDeploymentAssemblySectionBuilder#loadContents()
     */
    public void loadContents() {
        if (shouldDisplaySection()) {
            loadDefaultDeploymentDescriptorFolderContents();
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.jst.j2ee.internal.ui.IJavaEEDeploymentAssemblySectionBuilder#saveContents()
     */
    public boolean saveContents() {
        boolean success = true;
        if (shouldDisplaySection()) {
            success = saveDefaultDeploymentDescriptorFolderContents();
            loadContents();
        }
        return success;
    }

    private void loadDefaultDeploymentDescriptorFolderContents() {
        resourceMappingsList.clear();
        // First, retrieve all the mappings to root. Assume there are no duplicated mappings.
        IPath[] allRootMappings = findAllRootMappings();
        // Now, see if any of that is tagged as default root mapping
        IVirtualFolder rootFolder = rootComponent.getRootFolder();
        IPath defaultDDFolder = J2EEModuleVirtualComponent.getDefaultDeploymentDescriptorFolder(rootFolder);

        currentSelectedDDFolder = defaultDDFolder == null ? null : defaultDDFolder.toString();

        for (IPath mapping : allRootMappings) {
            resourceMappingsList.add(mapping.toString());
        }

        updateSourceMappingsCombo(currentSelectedDDFolder, resourceMappingsList);
    }

    private List<String> filterMappings(List<String> mappings) {
        Set<String> mappingWithDD = new HashSet<String>();
        Set<String> mappingWithFolder = new HashSet<String>();

        IProject project = this.rootComponent.getProject();
        for (String mapping : mappings) {
            if (fileToLook != null && !fileToLook.equals("")) { //$NON-NLS-1$
                IFile ddFile = project.getFile(new Path(mapping).addTrailingSeparator() + fileToLook);
                if (ddFile != null && ddFile.exists()) {
                    mappingWithDD.add(mapping);
                }
            }
            if (folderToLook != null && !folderToLook.equals("")) { //$NON-NLS-1$
                IFolder ddFolder = project.getFolder(new Path(mapping).addTrailingSeparator() + folderToLook);
                if (ddFolder != null && ddFolder.exists()) {
                    mappingWithFolder.add(mapping);
                }
            }
        }
        if (!mappingWithDD.isEmpty()) {
            // return only the mappings that contain a DD file.
            return new ArrayList<String>(mappingWithDD);
        }
        return new ArrayList<String>(mappingWithFolder);
    }

    private void updateSourceMappingsCombo(String selectedDDFolder, List<String> resourceMappings) {

        List<String> filteredMappings = filterMappings(resourceMappings);

        ArrayList<String> tmpList = new ArrayList<String>(filteredMappings);
        if (selectedDDFolder == null) {
            tmpList.add(0, Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDER);
        }
        rootSourceMappings.setItems(tmpList.toArray(new String[] {}));
        if (selectedDDFolder == null) {
            //No tagged source folder, so select "None"
            rootSourceMappings.select(
                    tmpList.indexOf(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDER));
        } else {
            rootSourceMappings.select(tmpList.indexOf(selectedDDFolder.toString()));
        }
    }

    private boolean saveDefaultDeploymentDescriptorFolderContents() {
        if (currentSelectedDDFolder != null) {
            IVirtualFolder rootFolder = rootComponent.getRootFolder();
            J2EEModuleVirtualComponent.setDefaultDeploymentDescriptorFolder(rootFolder,
                    new Path(currentSelectedDDFolder), null);
        }
        return true;
    }

    private IPath[] findAllRootMappings() {

        StructureEdit structureEdit = null;
        try {
            structureEdit = StructureEdit.getStructureEditForRead(rootComponent.getProject());
            WorkbenchComponent component = structureEdit.getComponent();
            Object[] arr = component.getResources().toArray();
            Set<IPath> result = new LinkedHashSet<IPath>();
            for (int i = 0; i < arr.length; i++) {
                ComponentResource resource = (ComponentResource) arr[i];
                if (resource.getRuntimePath().equals(IVirtualComponent.ROOT)
                        && !ResourceMappingFilterExtensionRegistry.shouldFilter(resource.getSourcePath())) {
                    result.add(((ComponentResource) arr[i]).getSourcePath());
                }
            }
            return result.toArray(new IPath[] {});
        } catch (NullPointerException e) {
            J2EEUIPlugin.logError(e);
        } finally {
            if (structureEdit != null)
                structureEdit.dispose();
        }
        return new IPath[] {};
    }

    protected boolean shouldDisplaySection() {
        return shouldDisplaySection;
    }

    /*
     * Creates the Advanced section. Returns the composite to which all the other 
     * widgets should be added.
     */
    private Composite createAdvancedSection(Composite parent) {

        // Build the expandable composite
        ExpandableComposite excomposite = new ExpandableComposite(parent, SWT.NONE,
                ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT | ExpandableComposite.COMPACT);
        excomposite.setText(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED);
        excomposite.setExpanded(false);
        excomposite.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
        excomposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1));
        excomposite.addExpansionListener(new ExpansionAdapter() {
            @Override
            public void expansionStateChanged(ExpansionEvent e) {
                expandedStateChanged((ExpandableComposite) e.getSource());
            }
        });

        // Build the composite has the contents of the expandable widget
        Composite innerComposite = new Composite(excomposite, SWT.NONE);
        excomposite.setClient(innerComposite);
        GridLayout gl = new GridLayout(2, false);
        gl.marginHeight = 0;
        gl.marginWidth = 0;
        innerComposite.setLayout(gl);
        return innerComposite;
    }

    private void addDefaultDeploymentDescriptorFolderFields(Composite parent) {
        defaulDDFolderLabel = new Label(parent, SWT.NONE);
        defaulDDFolderLabel.setText(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_DDFOLDER);
        rootSourceMappings = new Combo(parent, SWT.READ_ONLY);
        rootSourceMappings.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        rootSourceMappings.addSelectionListener(this);
    }

    private final void expandedStateChanged(ExpandableComposite expandable) {
        // Get the scrolled composite of the deployment assembly page, and the child
        // composite of this scrolled composite that contains the expandable composite 
        Composite[] composites = getCompositesToResize(expandable);
        ScrolledComposite parentScrolledComposite = (ScrolledComposite) composites[0];
        Composite childComposite = composites[1];
        if (parentScrolledComposite != null && childComposite != null) {
            parentScrolledComposite.layout(true, true);
            // Resize the scrolled composite so the scroll bars are shown if necessary
            parentScrolledComposite.setMinSize(childComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT, true));

        }
    }

    /*
     * Returns an array of composites used to resize the deployment assembly page
     * when the advanced section is expanded.
     * The first element is the scrolled composite (instance of ScrolledComposite) of the 
     * deployment assembly page
     * The second element is the composite with the contents of the deployment assembly page
     */
    private Composite[] getCompositesToResize(Control control) {
        Control parent = control.getParent();
        Control previousParent = null;
        Composite[] result = new Composite[2];
        while (!(parent instanceof ScrolledComposite) && parent != null) {
            previousParent = parent;
            parent = parent.getParent();
        }
        if (parent instanceof ScrolledComposite) {
            result[0] = (ScrolledComposite) parent;
        }
        if (previousParent instanceof Composite) {
            result[1] = (Composite) previousParent;
        }
        return result;
    }

    public void directiveAdded(Object element) {
        if (shouldDisplaySection()) {
            if (!(element instanceof TaskModel))
                return;
            TaskModel model = (TaskModel) element;
            final Object folderMapping = model.getObject(IReferenceWizardConstants.FOLDER_MAPPING);
            if (folderMapping != null && folderMapping instanceof ComponentResourceProxy) {
                ComponentResourceProxy proxy = (ComponentResourceProxy) folderMapping;
                //if ((proxy.runtimePath.equals(IVirtualComponent.ROOT) && !resourceMappingsList.contains(proxy.source.toString()))){
                if ((proxy.runtimePath.equals(IVirtualComponent.ROOT))) {
                    resourceMappingsList.add(proxy.source.toString());
                    updateSourceMappingsCombo(currentSelectedDDFolder, resourceMappingsList);
                }
            }
        }
    }

    public void directiveRemoved(Object element) {
        if (shouldDisplaySection()) {
            if (element instanceof ComponentResourceProxy) {
                ComponentResourceProxy proxy = (ComponentResourceProxy) element;
                if (proxy.runtimePath.equals(IVirtualComponent.ROOT)) {
                    String proxySource = proxy.source.toString();
                    if (resourceMappingsList.contains(proxySource)) {
                        resourceMappingsList.remove(proxySource);
                        if (proxySource.equals(currentSelectedDDFolder)) {
                            currentSelectedDDFolder = null;
                        }
                        updateSourceMappingsCombo(currentSelectedDDFolder, resourceMappingsList);
                    }
                }
            }
        }
    }

    public void widgetDefaultSelected(SelectionEvent event) {
        // Intentionally left blank

    }

    public void widgetSelected(SelectionEvent event) {
        if (event.getSource() == rootSourceMappings) {
            String tmp = rootSourceMappings.getText();
            if (tmp != null) {
                if (tmp.equals(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDER)
                        && currentSelectedDDFolder == null) {
                    // Do nothing, because the value did not change.
                    return;
                }
                if (tmp.equals(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDER)) {
                    // This means the user selected None, but there was already a value selected (this should not happen)
                    J2EEUIPlugin.logWarning("Unexpected condition when validating deployment descriptor folder"); //$NON-NLS-1$
                    return;
                }
                // We now the user selected something different from None, so remove this item so it cannot be selected again
                if (rootSourceMappings
                        .indexOf(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDER) != -1)
                    rootSourceMappings
                            .remove(Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDER);
                // Only refresh if changing from None to a folder
                boolean shouldRefresh = (currentSelectedDDFolder == null);
                if (!tmp.equals(currentSelectedDDFolder)) {
                    currentSelectedDDFolder = tmp;
                    if (shouldRefresh)
                        page.refresh();
                }
            }
        }

    }

    public IStatus validate(IStatus currentStatus) {
        IStatus status = currentStatus != null ? currentStatus : Status.OK_STATUS;
        if (shouldDisplaySection()) {
            if (currentSelectedDDFolder == null && resourceMappingsList.size() > 1) {
                // Only show the warning if none of the root mappings is selected and there are more than 1 root mapping            
                int severity = Status.WARNING;
                status = appendStatusMessage(status,
                        Messages.J2EEModuleDependenciesPropertyPage_ADVANCED_NODEFAULTDDFOLDERWARNING, severity);
            }
        }
        return status;
    }

    private IStatus appendStatusMessage(IStatus existingStatus, String message, int severity) {
        MultiStatus multiStatus;
        IStatus newStatus = new Status(severity, J2EEUIPlugin.PLUGIN_ID, message);
        int newSeverity = severity;
        if (existingStatus.getSeverity() > severity)
            newSeverity = existingStatus.getSeverity();
        if (existingStatus instanceof MultiStatus) {
            multiStatus = (MultiStatus) existingStatus;
            multiStatus.merge(newStatus);
        } else {
            if (!existingStatus.isMultiStatus() && existingStatus.isOK()) {
                return newStatus;
            }
            IStatus[] children = new IStatus[] { existingStatus, newStatus };
            multiStatus = new MultiStatus(J2EEUIPlugin.PLUGIN_ID, newSeverity, children, null, null);
        }
        return multiStatus;
    }

    public void componentResourceModified(ComponentResourceProxy originalResource,
            ComponentResourceProxy modifiedResource) {
        if (shouldDisplaySection()) {
            // We are interested only in two cases:
            // 1. When the deploy path changes from / to any other thing...
            if (originalResource.runtimePath.isRoot() && !modifiedResource.runtimePath.isRoot()) {
                resourceMappingsList.remove(originalResource.source.toString());
                if (originalResource.source.toString().equals(currentSelectedDDFolder)) {
                    currentSelectedDDFolder = null;
                }
                updateSourceMappingsCombo(currentSelectedDDFolder, resourceMappingsList);
                page.refresh();
            }
            // 2. When the deploy path changes from any thing to /
            else if (!originalResource.runtimePath.isRoot() && modifiedResource.runtimePath.isRoot()) {
                resourceMappingsList.add(originalResource.source.toString());
                updateSourceMappingsCombo(currentSelectedDDFolder, resourceMappingsList);
                page.refresh();
            }
        }
    }
}