/*******************************************************************************
* Copyright (c) 2012 Pivotal Software, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal Software, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.groovy.debug.core.evaluation;
import groovy.lang.GroovyClassLoader;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.Phases;
import org.codehaus.groovy.control.SourceUnit;
/**
* A classloader for the script to be evaluated that has a different parent
* than the currently running STS instance or the debugged. This way
* classes in the script do not conflict with classes in running STS instance.
* @author Andrew Eisenberg
* @since 2.5.1
*/
public class JDIGroovyClassLoader extends GroovyClassLoader {
private ClassNode theClass;
public JDIGroovyClassLoader() {
super();
}
public JDIGroovyClassLoader(ClassLoader loader) {
super(loader);
}
class JDIClassCollector extends ClassCollector {
protected JDIClassCollector(InnerLoader cl, CompilationUnit unit, SourceUnit su) {
super(cl, unit, su);
}
@SuppressWarnings("rawtypes")
protected Class createClass(byte[] code, ClassNode classNode) {
theClass = classNode;
return super.createClass(code, classNode);
}
}
protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
public InnerLoader run() {
return new InnerLoader(JDIGroovyClassLoader.this);
}
});
return new JDIClassCollector(loader, unit, su);
}
public ClassNode getTheClass() {
return theClass;
}
/**
* Override this method to add a new phase to the compilation
* We need to convert comparator binary expressions to using the JDIComparator instead
* of ScriptByteCodeAdapter.
*/
@Override
protected CompilationUnit createCompilationUnit(
CompilerConfiguration config, CodeSource source) {
CompilationUnit compilationUnit = super.createCompilationUnit(config, source);
compilationUnit.addPhaseOperation(new CompilationUnit.PrimaryClassNodeOperation() {
public void call(SourceUnit source, GeneratorContext context,
ClassNode classNode) throws CompilationFailedException {
new JDIComparator.ComparatorVisitor().visitBlockStatement(classNode.getModule().getStatementBlock());
}
}, Phases.CANONICALIZATION);
return compilationUnit;
}
}