org.grails.ide.eclipse.refactoring.test.GrailsRefactoringTest.java Source code

Java tutorial

Introduction

Here is the source code for org.grails.ide.eclipse.refactoring.test.GrailsRefactoringTest.java

Source

/*******************************************************************************
 * Copyright (c) 2012 VMWare, Inc.
 * 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
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     VMWare, Inc. - initial API and implementation
 *******************************************************************************/
package org.grails.ide.eclipse.refactoring.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.jdt.groovy.model.GroovyNature;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
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.runtime.jobs.Job;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameRequestor;
import org.eclipse.jdt.core.tests.compiler.regression.Requestor;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CheckConditionsOperation;
import org.eclipse.ltk.core.refactoring.CreateChangeOperation;
import org.eclipse.ltk.core.refactoring.IUndoManager;
import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.grails.ide.eclipse.commands.test.AbstractCommandTest;
import org.grails.ide.eclipse.core.GrailsCoreActivator;
import org.grails.ide.eclipse.core.internal.GrailsNature;
import org.grails.ide.eclipse.core.internal.plugins.GrailsCore;
import org.grails.ide.eclipse.core.model.GrailsVersion;
import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition;
import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil;

/**
 * @author Kris De Volder
 * @since 2.7
 */
public abstract class GrailsRefactoringTest extends AbstractCommandTest {

    public static String getContents(IFile file) throws IOException, CoreException {
        return getContents(file.getContents());
    }

    public static String getContents(InputStream in) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        StringBuffer sb = new StringBuffer(300);
        try {
            int read = 0;
            while ((read = br.read()) != -1)
                sb.append((char) read);
        } finally {
            br.close();
        }
        return sb.toString();
    }

    /**
     * Line-based version of junit.framework.Assert.assertEquals(String, String)
     * without considering line delimiters.
     * @param expected the expected value
     * @param actual the actual value
     */
    public static void assertEqualLines(String expected, String actual) {
        assertEquals("", lineStrip(expected.trim()), lineStrip(actual.trim()));
    }

    //   /**
    //    * Line-based version of junit.framework.Assert.assertEquals(String, String, String)
    //    * without considering line delimiters.
    //    * @param message the message
    //    * @param expected the expected value
    //    * @param actual the actual value
    //    */
    //   public static void assertEqualLines(String message, String expected, String actual) {
    ////      String[] expectedLines= Strings.convertIntoLines(expected);
    ////      String[] actualLines= Strings.convertIntoLines(actual);
    ////   
    ////      String expected2= (expectedLines == null ? null : Strings.concatenate(expectedLines, "\n"));
    ////      String actual2= (actualLines == null ? null : Strings.concatenate(actualLines, "\n"));
    //      assertEquals(message, expected., actual2);
    //   }

    /** 
     * Remove trailing white space from all lines in 'content'.
     * Also removes lines that only contain whitespace.
     **/
    private static String lineStrip(String content) {
        Pattern trailingWhiteSpace = Pattern.compile("(\\s)+$", Pattern.MULTILINE);
        Matcher matcher = trailingWhiteSpace.matcher(content);
        return matcher.replaceAll("");
    }

    protected Change undo = null; //Will be set by 'performRefactoring' if an undo is available.

    /**
     * Checks a bunch of stuff about the imported test project.
     * 
     * @throws Throwable
     */
    protected void checkImportedProject() throws Exception {

        //Check project config, like classpath related stuff. 
        // The config may not be right initially... but should eventually become correct as a background
        // refresh dependency job should get scheduled. 
        // ACondition
        new ACondition() {
            @Override
            public boolean test() throws Exception {
                assertJobManagerIdle(); //Wait for jobs... like Refresh dependencies to all complete.
                System.out.println("Checking project config...");
                IJavaProject javaProject = JavaCore.create(project);

                assertDefaultOutputFolder(javaProject);
                assertTrue(project.hasNature(JavaCore.NATURE_ID)); // Should have Java Nature at this point
                assertTrue(GroovyNature.hasGroovyNature(project)); // Should also have Groovy nature
                assertTrue(GrailsNature.isGrailsAppProject(project)); // Should look like a Grails app to grails tooling

                ///////////////////////////////////
                // Check resolved classpath stuff
                IClasspathEntry[] classPath = javaProject.getResolvedClasspath(false);

                // A whole bunch of libraries should be there, check for just a few of those

                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "/jsse.jar", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "grails-core", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "grails-bootstrap", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "groovy-all", classPath);
                //               assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "servlet-api", classPath);

                //            System.out.println(">>>Resolved classpath");
                //            for (IClasspathEntry entry : classPath) {
                //               System.out.println(kindString(entry.getEntryKind())+": "+entry.getPath());
                //            }
                //            System.out.println("<<<Resolved classpath");

                ///////////////////////////////////
                // Check raw classpath stuff
                classPath = javaProject.getRawClasspath();
                //            for (IClasspathEntry classpathEntry : classPath) {
                //               System.out.println(kindString(classpathEntry.getEntryKind())+": "+classpathEntry.getPath());
                //            }

                //The usual source folders:
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "src/java", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "src/groovy", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/conf", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/controllers", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/domain", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/services", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/taglib", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "test/integration", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "test/unit", classPath);

                //The classpath containers for Java and Grails
                assertClassPathEntry(IClasspathEntry.CPE_CONTAINER, "org.eclipse.jdt.launching.JRE_CONTAINER",
                        classPath);
                assertClassPathEntry(IClasspathEntry.CPE_CONTAINER,
                        "org.grails.ide.eclipse.core.CLASSPATH_CONTAINER", classPath);

                //Installed plugins source folders
                assertDefaultPluginSourceFolders(project);

                System.out.println("Checking project config => OK!");
                return true;
            }

        }.waitFor(4 * 60000);
    }

    protected IType getType(String fqName) throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(project);
        IType target = javaProject.findType(fqName);
        assertNotNull("Couldn't find type: " + fqName, target);
        return target;
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    protected void importZippedProject(String projectName) throws Exception {
        final URL zipFileURL = getProjectZip(projectName, GrailsVersion.getDefault());
        importProject(zipFileURL, projectName);
    }

    protected void assertFile(String path, String contents) throws IOException, CoreException {
        IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
        assertEqualLines(contents, getContents(file));
    }

    public void assertFile(String path) {
        IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
        assertTrue(file.exists());
    }

    public void assertFileDeleted(String path) {
        IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
        assertFalse("File exists: " + file, file.exists());
    }

    public static void performDummySearch(IJavaElement element) throws Exception {
        new SearchEngine().searchAllTypeNames(null, SearchPattern.R_EXACT_MATCH, "XXXXXXXXX".toCharArray(), // make sure we search a concrete name. This is faster according to Kent
                SearchPattern.R_EXACT_MATCH, IJavaSearchConstants.CLASS,
                SearchEngine.createJavaSearchScope(new IJavaElement[] { element }), new Requestor(),
                IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);
    }

    private static class Requestor extends TypeNameRequestor {
    }

    public static abstract class RefactoringJob extends Job {

        public RefactoringJob(String name) {
            super(name);
        }

        public RefactoringStatus refactoringStatus;

        protected abstract RefactoringStatus perform(IProgressMonitor mon) throws Throwable;

        @Override
        final protected IStatus run(IProgressMonitor mon) {
            try {
                this.refactoringStatus = perform(mon);
            } catch (Throwable e) {
                return new Status(IStatus.ERROR, GrailsCoreActivator.PLUGIN_ID, "Problem performing refactoring",
                        e);
            }
            if (this.refactoringStatus == null) {
                return new Status(IStatus.ERROR, GrailsCoreActivator.PLUGIN_ID, "Refactoring status was not set");
            } else {
                if (!this.refactoringStatus.isOK()) {
                    GrailsCoreActivator.log(refactoringStatus.toString());
                    return new Status(IStatus.ERROR, GrailsCoreActivator.PLUGIN_ID, refactoringStatus.toString());
                }
            }
            return Status.OK_STATUS;
        }

    }

    protected final RefactoringStatus performRefactoring(final Refactoring ref, final boolean providesUndo,
            final boolean performOnFail) throws Exception {
        performDummySearch(); //Why?
        RefactoringJob job = new RefactoringJob("Perform Refactoring") {

            @Override
            protected RefactoringStatus perform(IProgressMonitor monitor) throws Throwable {
                IUndoManager undoManager = getUndoManager();
                final CreateChangeOperation create = new CreateChangeOperation(
                        new CheckConditionsOperation(ref, CheckConditionsOperation.ALL_CONDITIONS),
                        RefactoringStatus.FATAL);
                final PerformChangeOperation perform = new PerformChangeOperation(create);
                perform.setUndoManager(undoManager, ref.getName());
                IWorkspace workspace = ResourcesPlugin.getWorkspace();
                executePerformOperation(perform, workspace);
                RefactoringStatus status = create.getConditionCheckingStatus();
                if (!status.hasError() && !performOnFail)
                    return status;
                assertTrue("Change wasn't executed", perform.changeExecuted());
                undo = perform.getUndoChange();
                if (providesUndo) {
                    assertNotNull("Undo doesn't exist", undo);
                    assertTrue("Undo manager is empty", undoManager.anythingToUndo());
                } else {
                    assertNull("Undo manager contains undo but shouldn't", undo);
                }
                return status;
            }
        };
        waitForWorkspaceJob(job);
        assertTrue(job.getResult().isOK());
        return job.refactoringStatus;
    }

    private void performDummySearch() throws Exception {
        performDummySearch(JavaCore.create(project));
    }

    protected void undoLastRefactoring() throws CoreException {
        assertNotNull("No undo found", undo);
        undo.perform(new NullProgressMonitor());
    }

    protected IUndoManager getUndoManager() {
        IUndoManager undoManager = RefactoringCore.getUndoManager();
        undoManager.flush();
        return undoManager;
    }

    protected void executePerformOperation(final PerformChangeOperation perform, IWorkspace workspace)
            throws CoreException {
        workspace.run(perform, new NullProgressMonitor());
    }

    protected void deleteResource(String path) throws CoreException {
        IFile rsrc = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
        rsrc.delete(true, new NullProgressMonitor());
    }

}