org.jboss.tools.arquillian.ui.internal.utils.ArquillianUIUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.arquillian.ui.internal.utils.ArquillianUIUtil.java

Source

/*************************************************************************************
 * Copyright (c) 2008-2014 Red Hat, Inc. 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:
 *     JBoss by Red Hat - Initial implementation.
 ************************************************************************************/
package org.jboss.tools.arquillian.ui.internal.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.maven.model.Build;
import org.apache.maven.model.Resource;
import org.apache.maven.project.MavenProject;
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.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility.GenStubSettings;
import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TableViewerEditor;
import org.eclipse.jface.viewers.TableViewerFocusCellManager;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.internal.IMavenConstants;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.jboss.forge.arquillian.container.Container;
import org.jboss.tools.arquillian.core.ArquillianCoreActivator;
import org.jboss.tools.arquillian.core.internal.ArquillianConstants;
import org.jboss.tools.arquillian.core.internal.archives.Archive;
import org.jboss.tools.arquillian.core.internal.archives.IEntry;
import org.jboss.tools.arquillian.core.internal.util.ArquillianSearchEngine;
import org.jboss.tools.arquillian.core.internal.util.ArquillianUtility;
import org.jboss.tools.arquillian.ui.ArquillianUIActivator;
import org.jboss.tools.arquillian.ui.internal.launcher.ArquillianProperty;
import org.jboss.tools.arquillian.ui.internal.launcher.AutoResizeTableLayout;
import org.jboss.tools.arquillian.ui.internal.preferences.ContainerEditingSupport;
import org.jboss.tools.arquillian.ui.internal.wizards.ProjectResource;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * @author snjeza
 *
 */
public class ArquillianUIUtil {

    private static final String DEFAULT = "default"; //$NON-NLS-1$
    private static final String JBOSSTOOLS_QUALIFIER = "jbosstools"; //$NON-NLS-1$
    private static final String UNKNOWN = "Unknown"; //$NON-NLS-1$
    private static final String CONFIGURATION = "configuration"; //$NON-NLS-1$
    private static final String ARQ_PREFIX = "arq"; //$NON-NLS-1$
    private static final String CONTAINER = "container"; //$NON-NLS-1$
    private static final String PERIOD = "."; //$NON-NLS-1$
    private static final String NAME = "name"; //$NON-NLS-1$
    private static final String PROPERTY = "property"; //$NON-NLS-1$
    private static final String QUALIFIER = "qualifier"; //$NON-NLS-1$
    private static final String ARQUILLIAN_XML = "arquillian.xml"; //$NON-NLS-1$
    private static final String ARQUILLIAN_PROPERTIES = "arquillian.properties"; //$NON-NLS-1$
    private static final String ARQUILLIAN_LAUNCH = "arquillian.launch"; //$NON-NLS-1$
    private static final String CREATE_DEPLOYMENT = "createDeployment"; //$NON-NLS-1$
    private static final String ORG_JBOSS_SHRINKWRAP_API_ARCHIVE = "org.jboss.shrinkwrap.api.Archive"; //$NON-NLS-1$
    private static final String ORG_JBOSS_SHRINKWRAP_API_SHRINK_WRAP = "org.jboss.shrinkwrap.api.ShrinkWrap"; //$NON-NLS-1$
    public static final String ADD_AS_MANIFEST_RESOURCE_METHOD = "addAsManifestResource"; //$NON-NLS-1$
    public static final String ADD_AS_WEB_INF_RESOURCE_METHOD = "addAsWebInfResource"; //$NON-NLS-1$
    public static final String ADD_AS_RESOURCE_METHOD = "addAsResource"; //$NON-NLS-1$

    public static IWorkbenchWindow getActiveWorkbenchWindow() {
        IWorkbench workbench = ArquillianUIActivator.getDefault().getWorkbench();
        if (workbench == null)
            return null;
        return workbench.getActiveWorkbenchWindow();
    }

    public static IWorkbenchPage getActivePage() {
        IWorkbenchWindow activeWorkbenchWindow = getActiveWorkbenchWindow();
        if (activeWorkbenchWindow == null)
            return null;
        return activeWorkbenchWindow.getActivePage();
    }

    public static IType getActiveType() {
        IWorkbenchPage page = getActivePage();
        if (page == null) {
            return null;
        }
        IEditorPart editor = page.getActiveEditor();
        if (editor instanceof CompilationUnitEditor) {
            CompilationUnitEditor cue = (CompilationUnitEditor) editor;
            IEditorInput editorInput = cue.getEditorInput();
            if (editorInput == null) {
                return null;
            }
            IJavaElement javaElement = (IJavaElement) editorInput.getAdapter(IJavaElement.class);
            if (javaElement != null && !javaElement.exists())
                return null;
            try {
                ITypeRoot rootType = EditorUtility.getEditorInputJavaElement(editor, true);
                if (rootType != null && rootType.isConsistent()) {
                    IJavaElement element = SelectionConverter.getElementAtOffset(cue);
                    if (element == null) {
                        return null;
                    }
                    return SelectionConverter.getTypeAtOffset(cue);
                }
            } catch (JavaModelException e) {
                ArquillianUIActivator.log(e);
            }
        }
        return null;
    }

    /**
     * Creates a deployment method
     * 
     * @param icu
     * @param type
     * @param imports
     * @param isAddComments
     * @param delimiter
     * @param deploymentDescriptor
     * @param sibling
     * @param force
     * @throws CoreException
     */
    public static void createDeploymentMethod(ICompilationUnit icu, IType type, ImportsManager imports,
            boolean isAddComments, String delimiter, IDeploymentDescriptor deploymentDescriptor,
            IJavaElement sibling, boolean force) throws CoreException {
        String content = null;
        ImportRewrite importsRewrite = null;
        if (icu != null) {
            importsRewrite = StubUtility.createImportRewrite(icu, true);
        }
        String annotation = '@' + addImport(imports, importsRewrite,
                ArquillianUtility.ORG_JBOSS_ARQUILLIAN_CONTAINER_TEST_API_DEPLOYMENT);
        String methodName = CREATE_DEPLOYMENT;
        addImport(imports, importsRewrite, ORG_JBOSS_SHRINKWRAP_API_SHRINK_WRAP);
        addImport(imports, importsRewrite, ORG_JBOSS_SHRINKWRAP_API_ARCHIVE);
        GenStubSettings settings = JUnitStubUtility.getCodeGenerationSettings(type.getJavaProject());
        settings.createComments = isAddComments;

        StringBuffer buffer = new StringBuffer();
        if (settings.createComments) {
            String retTypeSig = Signature.createTypeSignature(ORG_JBOSS_SHRINKWRAP_API_ARCHIVE, true);
            String comment = CodeGeneration.getMethodComment(type.getCompilationUnit(), type.getElementName(),
                    methodName, new String[0], new String[0], retTypeSig, null, delimiter);
            if (comment != null) {
                buffer.append(comment);
            }
        }

        String archiveType = ArquillianConstants.JAR;
        String archiveName = ""; //$NON-NLS-1$
        String deploymentName = null;
        String deploymentOrder = null;
        boolean addBeansXml = true;
        IType[] types = null;

        List<String> resources = new ArrayList<String>();
        List<String> webInfResources = new ArrayList<String>();
        if (deploymentDescriptor != null) {
            methodName = deploymentDescriptor.getMethodName();
            archiveType = deploymentDescriptor.getArchiveType();
            archiveName = deploymentDescriptor.getArchiveName();
            addBeansXml = deploymentDescriptor.addBeansXml();
            deploymentName = deploymentDescriptor.getDeploymentName();
            deploymentOrder = deploymentDescriptor.getDeploymentOrder();
            types = deploymentDescriptor.getTypes();
            ProjectResource[] allResources = deploymentDescriptor.getResources();
            for (ProjectResource resource : allResources) {
                if (ArquillianConstants.WAR.equals(archiveType) && resource.isDeployAsWebInfResource()) {
                    webInfResources.add(resource.getPath().toString());
                } else {
                    resources.add(resource.getPath().toString());
                }
            }
        }

        buffer.append(annotation);
        if ((deploymentName != null && !deploymentName.isEmpty())
                || (deploymentOrder != null && !deploymentOrder.isEmpty())) {
            buffer.append("("); //$NON-NLS-1$
            if ((deploymentName != null && !deploymentName.isEmpty())) {
                buffer.append("name = \""); //$NON-NLS-1$
                buffer.append(deploymentName);
                buffer.append("\""); //$NON-NLS-1$
                if (deploymentOrder != null && !deploymentOrder.isEmpty()) {
                    buffer.append(" , "); //$NON-NLS-1$
                }
            }
            if (deploymentOrder != null && !deploymentOrder.isEmpty()) {
                buffer.append("order = "); //$NON-NLS-1$
                buffer.append(deploymentOrder);
            }

            buffer.append(")"); //$NON-NLS-1$
        }
        buffer.append(delimiter);

        buffer.append("public static Archive<?> "); //$NON-NLS-1$

        buffer.append(methodName);
        buffer.append("()"); //$NON-NLS-1$
        buffer.append(" {").append(delimiter); //$NON-NLS-1$
        if (ArquillianConstants.JAR.equals(archiveType)) {
            addImport(imports, importsRewrite, ArquillianUtility.ORG_JBOSS_SHRINKWRAP_API_SPEC_JAVA_ARCHIVE);
            buffer.append("JavaArchive archive = ShrinkWrap.create(JavaArchive.class"); //$NON-NLS-1$
        }
        if (ArquillianConstants.WAR.equals(archiveType)) {
            addImport(imports, importsRewrite, ArquillianUtility.ORG_JBOSS_SHRINKWRAP_API_SPEC_WEB_ARCHIVE);
            buffer.append("WebArchive archive = ShrinkWrap.create(WebArchive.class"); //$NON-NLS-1$
        }
        if (ArquillianConstants.EAR.equals(archiveType)) {
            addImport(imports, importsRewrite, "org.jboss.shrinkwrap.api.spec.EnterpriseArchive"); //$NON-NLS-1$
            buffer.append("EnterpriseArchive archive = ShrinkWrap.create(EnterpriseArchive.class"); //$NON-NLS-1$
        }
        if (ArquillianConstants.RAR.equals(archiveType)) {
            addImport(imports, importsRewrite, "org.jboss.shrinkwrap.api.spec.ResourceAdapterArchive"); //$NON-NLS-1$
            buffer.append("ResourceAdapterArchive archive = ShrinkWrap.create(ResourceAdapterArchive.class"); //$NON-NLS-1$
        }
        if (archiveName != null && !archiveName.isEmpty()) {
            if (archiveName.indexOf(PERIOD) == -1) {
                archiveName = archiveName + PERIOD + archiveType;
            }
            buffer.append(", "); //$NON-NLS-1$
            buffer.append("\""); //$NON-NLS-1$
            buffer.append(archiveName);
            buffer.append("\""); //$NON-NLS-1$
        }
        buffer.append(")"); //$NON-NLS-1$

        if (types != null && types.length > 0) {
            buffer.append(delimiter);
            buffer.append(".addClasses( "); //$NON-NLS-1$
            boolean first = true;
            for (IType t : types) {
                if (!first) {
                    buffer.append(" , "); //$NON-NLS-1$
                } else {
                    first = false;
                }
                String typeName = t.getFullyQualifiedName().replaceAll("\\$", ".");
                int lastPeriod = typeName.lastIndexOf(PERIOD);
                String className = typeName;
                if (lastPeriod >= 0 && lastPeriod < typeName.length()) {
                    className = typeName.substring(lastPeriod + 1, typeName.length());
                    addImport(imports, importsRewrite, typeName);
                }
                buffer.append(className);
                buffer.append(".class"); //$NON-NLS-1$
            }
            buffer.append(" )"); //$NON-NLS-1$
        }

        for (String resource : resources) {
            buffer.append(delimiter);
            buffer.append(".addAsResource( "); //$NON-NLS-1$
            buffer.append("\""); //$NON-NLS-1$
            buffer.append(resource);
            buffer.append("\""); //$NON-NLS-1$
            buffer.append(" )"); //$NON-NLS-1$
        }
        for (String resource : webInfResources) {
            buffer.append(delimiter);
            buffer.append(".addAsWebInfResource( "); //$NON-NLS-1$
            buffer.append("\""); //$NON-NLS-1$
            buffer.append(resource);
            buffer.append("\""); //$NON-NLS-1$
            buffer.append(" )"); //$NON-NLS-1$
        }

        if (addBeansXml && !ArquillianConstants.EAR.equals(archiveType)) {
            addImport(imports, importsRewrite, "org.jboss.shrinkwrap.api.asset.EmptyAsset"); //$NON-NLS-1$
            buffer.append(delimiter);
            if (ArquillianConstants.WAR.equals(archiveType)) {
                buffer.append(".addAsWebInfResource(EmptyAsset.INSTANCE, \"beans.xml\")"); //$NON-NLS-1$
            } else {
                buffer.append(".addAsManifestResource(EmptyAsset.INSTANCE, \"beans.xml\")"); //$NON-NLS-1$
            }
        }

        buffer.append(";").append(delimiter); //$NON-NLS-1$
        buffer.append("// System.out.println(archive.toString(true));").append( //$NON-NLS-1$
                delimiter);
        buffer.append("return archive;").append(delimiter); //$NON-NLS-1$
        buffer.append("}"); //$NON-NLS-1$
        buffer.append(delimiter);
        content = buffer.toString();

        if (icu == null) {
            type.createMethod(content, sibling, force, null);
        } else {
            TextEdit edit = importsRewrite.rewriteImports(null);
            JavaModelUtil.applyEdit(importsRewrite.getCompilationUnit(), edit, false, null);
            IMethod createdMethod = type.createMethod(content, sibling, force, null);
            ISourceRange range = createdMethod.getSourceRange();

            IBuffer buf = icu.getBuffer();
            String originalContent = buf.getText(range.getOffset(), range.getLength());
            int indent = StubUtility.getIndentUsed(type) + 1;
            String formattedContent = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS,
                    originalContent, indent, delimiter, type.getJavaProject());
            //formattedContent = Strings
            //      .trimLeadingTabsAndSpaces(formattedContent);
            while (formattedContent.length() > 0) {
                char ch = formattedContent.charAt(0);
                if (ScannerHelper.isWhitespace(ch)) {
                    formattedContent = formattedContent.substring(1);
                } else {
                    break;
                }
            }
            buf.replace(range.getOffset(), range.getLength(), formattedContent);

            icu.reconcile(ICompilationUnit.NO_AST, false, null, null);

            icu.commitWorkingCopy(false, null);

        }
    }

    private static String addImport(ImportsManager imports, ImportRewrite importsRewrite, String qtn) {
        if (imports != null) {
            return imports.addImport(qtn);
        }
        if (importsRewrite != null) {
            return importsRewrite.addImport(qtn);
        }
        return null;
    }

    public static ICompilationUnit getActiveCompilationUnit() {
        IWorkbenchPage page = getActivePage();
        if (page == null) {
            return null;
        }
        IEditorPart editor = page.getActiveEditor();
        if (editor instanceof CompilationUnitEditor) {
            CompilationUnitEditor cue = (CompilationUnitEditor) editor;
            return SelectionConverter.getInputAsCompilationUnit(cue);
        }
        return null;
    }

    public static Set<ArquillianProperty> getArquillianProperties(ILaunchConfiguration configuration) {
        Set<ArquillianProperty> properties = new TreeSet<ArquillianProperty>();
        try {
            IJavaProject javaProject = ArquillianUtility.getJavaProject(configuration);
            if (javaProject == null) {
                return properties;
            }
            if (!ArquillianSearchEngine.hasArquillianType(javaProject)) {
                return properties;
            }
            String arguments = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""); //$NON-NLS-1$
            String args = VariablesPlugin.getDefault().getStringVariableManager()
                    .performStringSubstitution(arguments);
            Properties vmProperties = getVMProperties(args);
            String configurationName = vmProperties.getProperty(ARQUILLIAN_LAUNCH);

            Properties arquillianXmlProperties = null;
            try {
                arquillianXmlProperties = getArquillianXmlProperties(javaProject, configurationName);
            } catch (Exception e) {
                ArquillianUIActivator.log(e);
            }
            String qualifier = arquillianXmlProperties.getProperty(QUALIFIER, null);
            if (qualifier == null) {
                qualifier = UNKNOWN;
                //            IFile file = getFile(javaProject, ARQUILLIAN_XML);
                //            if (file == null) {
                //               file = getNewFile(javaProject, ARQUILLIAN_XML);
                //               String s = "<arquillian xmlns=\"http://jboss.org/schema/arquillian\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" //$NON-NLS-1$
                //                          + "            xsi:schemaLocation=\"http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd\">\n" //$NON-NLS-1$
                //                          + "</arquillian>"; //$NON-NLS-1$
                //               file.create(new ByteArrayInputStream(s.getBytes()), true,null);
                //            }
                //            InputStream is = null;
                //            try {
                //               is = file.getContents();
                //               org.jboss.forge.parser.xml.Node xml = XMLParser.parse(is);
                //               
                //               xml.getOrCreate("container@qualifier=" + qualifier + "&default=true"); //$NON-NLS-1$ //$NON-NLS-2$
                //                  
                //               String content = XMLParser.toXMLString(xml);
                //               ByteArrayInputStream input = new ByteArrayInputStream(content.getBytes());
                //               file.setContents(input, IResource.FORCE, null);
                //            } catch (XMLParserException e) {
                //               ArquillianCoreActivator.log(e);
                //            } finally {
                //               close(is);
                //            }
            }
            arquillianXmlProperties.remove(QUALIFIER);
            if (UNKNOWN.equals(qualifier)) {
                qualifier = JBOSSTOOLS_QUALIFIER;
                StringBuffer buf = new StringBuffer();
                buf.append(ARQ_PREFIX);
                buf.append(PERIOD);
                buf.append(CONTAINER);
                buf.append(PERIOD);
                buf.append(qualifier);
                buf.append(PERIOD);
                buf.append(DEFAULT);
                ArquillianProperty property = new ArquillianProperty(buf.toString(), "", ARQUILLIAN_PROPERTIES, //$NON-NLS-1$
                        true);
                property.setChanged(true);
                properties.add(property);
            }
            addContainerProperties(javaProject, properties, qualifier);

            Enumeration<Object> keys = arquillianXmlProperties.keys();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                String value = arquillianXmlProperties.getProperty(key);
                ArquillianProperty property = new ArquillianProperty(key, value, ARQUILLIAN_XML, false);
                properties.remove(property);
                properties.add(property);
            }
            String fileName = vmProperties.getProperty(ARQUILLIAN_PROPERTIES, ARQUILLIAN_PROPERTIES);
            Properties arquillianProperties = getArquillianProperties(javaProject, fileName);
            keys = arquillianProperties.keys();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                if (key != null && key.startsWith(ARQ_PREFIX + "." + CONTAINER) && key.endsWith(DEFAULT)) {
                    String[] elements = key.split(".");
                    if (elements.length == 4) {
                        continue;
                    }
                }
                String value = arquillianProperties.getProperty(key);
                ArquillianProperty property = new ArquillianProperty(key, value, ARQUILLIAN_PROPERTIES, false);
                properties.remove(property);
                ;
                properties.add(property);
            }
        } catch (CoreException e) {
            ArquillianUIActivator.log(e);
        }
        return properties;
    }

    private static void addContainerProperties(IJavaProject javaProject, Set<ArquillianProperty> properties,
            String qualifier) {
        IStatus status = ArquillianSearchEngine.validateDeployableContainer(javaProject);
        if (!status.isOK()) {
            return;
        }
        try {
            IType type = javaProject.findType(ArquillianSearchEngine.CONTAINER_DEPLOYABLE_CONTAINER);
            if (type == null) {
                status = new Status(IStatus.ERROR, ArquillianUIActivator.PLUGIN_ID,
                        "Cannot find 'org.jboss.arquillian.container.spi.client.container.DeployableContainer' on project build path. Arquillian tests can only be run if DeployableContainer is on the build path.");
                ArquillianUIActivator.getDefault().getLog().log(status);
            }
            ITypeHierarchy hierarchy = type.newTypeHierarchy(new NullProgressMonitor());
            IType[] subTypes = hierarchy.getAllSubtypes(type);
            for (IType subType : subTypes) {
                if (ArquillianSearchEngine.isNonAbstractClass(subType)) {
                    Object containerObject = null;
                    try {
                        containerObject = ArquillianUtility.newInstance(javaProject,
                                subType.getFullyQualifiedName());
                    } catch (ClassNotFoundException e) {
                        ArquillianUIActivator.log(e);
                        return;
                    } catch (InstantiationException e) {
                        ArquillianUIActivator.log(e);
                        return;
                    } catch (IllegalAccessException e) {
                        ArquillianUIActivator.log(e);
                        return;
                    } catch (NoClassDefFoundError e) {
                        ArquillianUIActivator.log(e);
                        return;
                    }

                    ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();

                    ClassLoader loader = ArquillianCoreActivator.getDefault().getClassLoader(javaProject);

                    Thread.currentThread().setContextClassLoader(loader);
                    try {
                        Class<?> clazz = containerObject.getClass();
                        Method configurationMethod = clazz.getDeclaredMethod("getConfigurationClass", //$NON-NLS-1$
                                new Class[0]);
                        Class<?> configuration = (Class<?>) configurationMethod.invoke(containerObject,
                                new Object[0]);

                        Object configurationObject = ArquillianUtility.newInstance(javaProject,
                                configuration.getName());
                        Method[] methods = configuration.getMethods();
                        for (Method method : methods) {
                            String methodName = method.getName();
                            if (methodName.matches("^set[A-Z].*") //$NON-NLS-1$
                                    && method.getReturnType().equals(Void.TYPE)
                                    && method.getParameterTypes().length == 1) {
                                method.setAccessible(true);
                                String name = methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
                                String getterName = "get" + methodName.substring(3); //$NON-NLS-1$
                                String value = null;
                                try {
                                    Method getter = configuration.getMethod(getterName, new Class[0]);
                                    Object valueObject = getter.invoke(configurationObject, new Object[0]);
                                    if (valueObject != null) {
                                        value = valueObject.toString();
                                    }
                                } catch (Exception e) {
                                    //ArquillianUIActivator.log(e);
                                    // FIXME
                                }
                                if (value == null) {
                                    value = "";
                                }
                                String propertyName = getContainerConfigurationPropertyName(qualifier, name);
                                ArquillianProperty property = new ArquillianProperty(propertyName, value, CONTAINER,
                                        true);

                                properties.add(property);
                            }
                        }
                    } catch (Exception e) {
                        ArquillianUIActivator.log(e);
                    } finally {
                        Thread.currentThread().setContextClassLoader(currentLoader);
                    }
                    break;
                }
            }

        } catch (JavaModelException e) {
            ArquillianUIActivator.log(e);
        }

    }

    private static Properties getArquillianProperties(IJavaProject javaProject, String fileName)
            throws JavaModelException {
        IFile file = getFile(javaProject, fileName);
        Properties properties = new Properties();
        if (file != null && file.exists()) {
            InputStream input = null;

            try {
                input = file.getContents();
                properties.load(input);
            } catch (CoreException e) {
                ArquillianUIActivator.log(e);
            } catch (IOException e) {
                ArquillianUIActivator.log(e);
            } finally {
                close(input);
            }
        }
        return properties;
    }

    private static Properties getArquillianXmlProperties(IJavaProject javaProject, String configurationName)
            throws CoreException, ParserConfigurationException, SAXException, IOException {
        Properties properties = new Properties();
        IFile file = getFile(javaProject, ARQUILLIAN_XML);
        if (file != null && file.exists()) {
            InputStream input = null;
            try {
                input = file.getContents(true);
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                Document doc = db.parse(input);
                Element root = doc.getDocumentElement();
                Element container = getDefaultContainer(configurationName, root);
                if (container != null) {
                    String qualifier = container.getAttribute(QUALIFIER);
                    properties.put(QUALIFIER, qualifier);
                    Element configuration = getConfiguration(container);
                    if (configuration != null) {
                        NodeList configurationList = configuration.getChildNodes();
                        for (int i = 0; i < configurationList.getLength(); i++) {
                            Node node = configurationList.item(i);
                            if ((node instanceof Element) && PROPERTY.equals(node.getNodeName())) {
                                Element property = (Element) node;
                                String name = property.getAttribute(NAME);
                                String propertyName = getContainerConfigurationPropertyName(qualifier, name);
                                String value = property.getTextContent();
                                if (value != null) {
                                    value = value.trim();
                                    properties.put(propertyName, value);
                                }
                            }
                        }
                    }
                }
            } catch (DOMException e) {
                ArquillianUIActivator.log(e);
            } finally {
                close(input);
            }

        }
        return properties;
    }

    private static String getContainerConfigurationPropertyName(String qualifier, String name) {
        StringBuffer buf = new StringBuffer();
        buf.append(ARQ_PREFIX);
        buf.append(PERIOD);
        buf.append(CONTAINER);
        buf.append(PERIOD);
        if (!UNKNOWN.equals(qualifier)) {
            buf.append(qualifier);
            buf.append(PERIOD);
        }
        buf.append(CONFIGURATION);
        buf.append(PERIOD);
        buf.append(name);
        return buf.toString();
    }

    private static IFile getFile(IJavaProject javaProject, String fileName) throws JavaModelException {
        IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
        for (IClasspathEntry entry : rawClasspath) {
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                IPackageFragmentRoot[] roots = javaProject.findPackageFragmentRoots(entry);
                if (roots == null) {
                    continue;
                }
                for (IPackageFragmentRoot root : roots) {
                    Object[] resources = root.getNonJavaResources();
                    int segments = root.getPath().segmentCount();
                    for (Object resource : resources) {
                        if (resource instanceof IFile) {
                            IFile file = (IFile) resource;
                            IPath filePath = file.getProjectRelativePath();
                            IPath relativePath = filePath.removeFirstSegments(segments - 1);
                            if (fileName.equals(relativePath.toString())) {
                                return file;
                            }
                        }
                    }

                }
            }
        }
        return null;
    }

    private static void close(InputStream input) {
        if (input != null) {
            try {
                input.close();
            } catch (Exception e) {
                // ignore
            }
        }
    }

    private static void close(OutputStream output) {
        if (output != null) {
            try {
                output.close();
            } catch (Exception e) {
                // ignore
            }
        }
    }

    private static Element getConfiguration(Element container) {
        Element configuration = null;
        NodeList containerList = container.getChildNodes();
        for (int i = 0; i < containerList.getLength(); i++) {
            Node node = containerList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;
                if (CONFIGURATION.equals(element.getNodeName())) {
                    configuration = element;
                    break;
                }
            }
        }
        return configuration;
    }

    private static Element getDefaultContainer(String configurationName, Element root) {
        NodeList containers = root.getElementsByTagName(CONTAINER);
        for (int i = 0; i < containers.getLength(); i++) {
            Node containerNode = containers.item(i);
            if (containerNode instanceof Element) {
                Element container = (Element) containerNode;
                if (configurationName != null && !configurationName.isEmpty()) {
                    String qualifier = container.getAttribute(QUALIFIER);
                    if (configurationName.equals(qualifier)) {
                        return container;
                    }
                } else {
                    String defaultString = container.getAttribute(DEFAULT); //$NON-NLS-1$
                    if ("true".equals(defaultString)) { //$NON-NLS-1$
                        return container;
                    }
                }
            }
        }
        return null;
    }

    private static Properties getVMProperties(String vmArgs) {
        Properties properties = new Properties();
        if (vmArgs != null) {
            String[] arguments = vmArgs.split(" ");
            if (arguments != null) {
                for (String arg : arguments) {
                    arg = arg.trim();
                    if (arg.startsWith("-Darq")) {
                        String[] props = arg.split("=");
                        if (props != null && props.length == 2) {
                            String name = props[0].substring(2);
                            String value = props[1];
                            properties.put(name, value);
                        }
                    }
                }
            }
        }
        return properties;
    }

    public static void save(Set<ArquillianProperty> arquillianProperties, ILaunchConfiguration configuration)
            throws CoreException {
        if (arquillianProperties == null || configuration == null) {
            return;
        }
        IJavaProject javaProject = ArquillianUtility.getJavaProject(configuration);
        if (javaProject == null) {
            return;
        }
        IFile file = getFile(javaProject, ARQUILLIAN_PROPERTIES);
        if (file == null) {
            file = getNewFile(javaProject, ARQUILLIAN_PROPERTIES);
        }
        if (!file.exists()) {
            createEmptyFile(file);
        }
        InputStream input = null;
        Properties properties = new Properties();
        input = file.getContents();
        try {
            properties.load(input);
        } catch (IOException e) {
            throw new CoreException(new Status(Status.ERROR, ArquillianUIActivator.PLUGIN_ID, e.getMessage(), e));
        } finally {
            if (input != null) {
                close(input);
            }
        }
        boolean changed = false;
        for (ArquillianProperty arquillianProperty : arquillianProperties) {
            // FIXME
            if (arquillianProperty.isChanged() && ARQUILLIAN_PROPERTIES.equals(arquillianProperty.getSource())) {
                properties.put(arquillianProperty.getName(), arquillianProperty.getValue());
                changed = true;
            }
        }
        if (changed) {
            ByteArrayOutputStream out = null;
            ByteArrayInputStream in = null;

            try {
                out = new ByteArrayOutputStream();
                properties.store(out, "Created by JBoss Tools");
                String outputString = out.toString();
                in = new ByteArrayInputStream(out.toByteArray());
                file.setContents(in, true, true, null);
            } catch (IOException e) {
                throw new CoreException(
                        new Status(Status.ERROR, ArquillianUIActivator.PLUGIN_ID, e.getMessage(), e));
            } finally {
                close(in);
                close(out);
            }
        }
    }

    private static IFile getNewFile(IJavaProject javaProject, String arquillianProperties) throws CoreException {
        IProject project = javaProject.getProject();
        if (project.hasNature(IMavenConstants.NATURE_ID)) {
            IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().create(project,
                    new NullProgressMonitor());
            MavenProject mavenProject = facade.getMavenProject(new NullProgressMonitor());
            Build build = mavenProject.getBuild();
            String testDirectory = null;
            List<Resource> testResources = build.getTestResources();
            if (testResources != null && testResources.size() > 0) {
                testDirectory = testResources.get(0).getDirectory();
            } else {
                testDirectory = build.getTestSourceDirectory();
            }
            File testDir = new File(testDirectory);
            if (testDir.isDirectory()) {
                File arquillianFile = new File(testDir, arquillianProperties);
                IPath path = new Path(arquillianFile.getAbsolutePath());
                IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
                if (!iFile.getParent().exists()) {
                    IPath projectPath = javaProject.getProject().getLocation();
                    IPath iFilePath = iFile.getLocation();
                    if (iFilePath.toString().startsWith(projectPath.toString())) {
                        String s = iFilePath.toString().substring(projectPath.toString().length());
                        path = new Path(s);
                        return javaProject.getProject().getFile(path);
                    }
                }
                return iFile;
            }
        }
        IPath path = null;
        IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
        for (IClasspathEntry entry : rawClasspath) {
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                IPackageFragmentRoot[] roots = javaProject.findPackageFragmentRoots(entry);
                if (roots == null) {
                    continue;
                }
                for (IPackageFragmentRoot root : roots) {
                    path = root.getPath();
                    break;
                }
            }
        }
        if (path == null) {
            throw new CoreException(new Status(IStatus.ERROR, ArquillianUIActivator.PLUGIN_ID, "Invalid project"));
        }
        IFolder folder = javaProject.getProject().getFolder(path);
        if (!folder.exists()) {
            IPath projectPath = javaProject.getPath();
            path = path.makeRelativeTo(projectPath);
            folder = javaProject.getProject().getFolder(path);
        }
        return folder.getFile(arquillianProperties);
    }

    private static void createEmptyFile(IFile file) throws CoreException {
        InputStream input = null;
        try {
            input = new ByteArrayInputStream("".getBytes()); //$NON-NLS-1$
            file.create(input, true, null);
        } catch (Exception e) {
            throw new CoreException(new Status(Status.ERROR, ArquillianUIActivator.PLUGIN_ID, e.getMessage(), e));
        } finally {
            if (input != null) {
                close(input);
            }
        }
    }

    public static CheckboxTableViewer createProfilesViewer(Composite parent, List<Container> containers,
            int heightHint) {
        final CheckboxTableViewer viewer = CheckboxTableViewer.newCheckList(parent,
                SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
        gd.heightHint = heightHint;
        viewer.getTable().setLayoutData(gd);

        Table table = viewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        table.setFont(parent.getFont());

        viewer.setContentProvider(new ContainerContentProvider(containers));

        String[] columnHeaders = { "ID", "Name" };

        for (int i = 0; i < columnHeaders.length; i++) {
            TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
            column.setLabelProvider(new ContainerLabelProvider(i));
            column.getColumn().setText(columnHeaders[i]);
            column.getColumn().setResizable(true);
            column.getColumn().setMoveable(true);
            column.setEditingSupport(new ContainerEditingSupport(viewer, i));
        }

        ColumnLayoutData[] containersLayouts = { new ColumnWeightData(200, 200), new ColumnWeightData(150, 150),
                //new ColumnWeightData(50,50)
        };

        TableLayout layout = new AutoResizeTableLayout(table);
        for (int i = 0; i < containersLayouts.length; i++) {
            layout.addColumnData(containersLayouts[i]);
        }

        viewer.getTable().setLayout(layout);

        configureViewer(viewer);

        viewer.setInput(containers);

        return viewer;
    }

    public static void initializeViewer(CheckboxTableViewer viewer, List<Container> containers) {
        List<String> selectedProfiles = ArquillianUtility
                .getProfilesFromPreferences(ArquillianConstants.SELECTED_ARQUILLIAN_PROFILES);
        List<String> activatedProfiles = ArquillianUtility
                .getProfilesFromPreferences(ArquillianConstants.ACTIVATED_ARQUILLIAN_PROFILES);

        for (Container container : containers) {
            container.setActivate(activatedProfiles.contains(container.getId()));
            viewer.setChecked(container, selectedProfiles.contains(container.getId()));
        }
        viewer.refresh();
    }

    static class ContainerContentProvider implements IStructuredContentProvider {
        private List<Container> containers;

        public ContainerContentProvider(List<Container> containers) {
            this.containers = containers;
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }

        public Object[] getElements(Object inputElement) {
            return containers.toArray();
        }

        public void dispose() {
        }
    }

    static class ContainerLabelProvider extends ColumnLabelProvider {

        private int columnIndex;

        public ContainerLabelProvider(int i) {
            this.columnIndex = i;
        }

        public String getText(Object element) {
            if (element instanceof Container) {
                Container container = (Container) element;
                switch (columnIndex) {
                case 0:
                    return container.getId();
                case 1:
                    String name = container.getName();
                    if (name == null) {
                        return null;
                    }
                    return name.replace(Container.ARQUILLIAN_CONTAINER_NAME_START, ""); //$NON-NLS-1$
                }
            }
            return null;
        }

        @Override
        public Image getImage(Object element) {
            return null;
        }
    }

    private static void configureViewer(final CheckboxTableViewer viewer) {
        TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(viewer,
                new FocusCellOwnerDrawHighlighter(viewer));

        ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(viewer) {
            protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
                ViewerCell cell = viewer.getColumnViewerEditor().getFocusCell();
                if (cell != null && cell.getColumnIndex() == 1) {
                    return super.isEditorActivationEvent(event);
                }
                return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
                        || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
                        || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED
                                && event.keyCode == SWT.CR)
                        || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
            }
        };

        TableViewerEditor.create(viewer, focusCellManager, actSupport,
                ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
                        | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
    }

    public static IProject getSelectedProject(ISelection selection) {
        IProject selected = null;
        if (selection instanceof IStructuredSelection) {
            Object object = ((IStructuredSelection) selection).getFirstElement();
            if (object instanceof IResource) {
                return ((IResource) object).getProject();
            } else if (object instanceof IAdaptable) {
                IResource resource = (IResource) ((IAdaptable) object).getAdapter(IResource.class);
                if (resource != null) {
                    return resource.getProject();
                }
            }
            if (object instanceof IEntry) {
                if (((IEntry) object).getJavaProject() != null) {
                    return ((IEntry) object).getJavaProject().getProject();
                } else {
                    if (object instanceof Archive) {
                        Archive archive = (Archive) object;
                        if (archive.getLocation() != null && archive.getLocation().getProjectName() != null) {
                            return ResourcesPlugin.getWorkspace().getRoot()
                                    .getProject(archive.getLocation().getProjectName());
                        }
                    }
                }
            }
        }
        if (selection instanceof ITextSelection) {
            ICompilationUnit cu = ArquillianUIUtil.getActiveCompilationUnit();
            if (cu != null) {
                selected = cu.getJavaProject().getProject();
            }
        }

        return selected;
    }
}