-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGroovyRemoteConsole.groovy
110 lines (94 loc) · 3.67 KB
/
GroovyRemoteConsole.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
@Grab('org.codehaus.groovy.modules.remote:remote-transport-http:0.3')
import groovyx.remote.transport.http.HttpTransport
import groovyx.remote.client.*
import javax.swing.UIManager
import groovy.ui.Console
import org.codehaus.groovy.control.*
import groovy.beans.Bindable
import java.security.*
import org.codehaus.groovy.ast.ClassNode
import javax.swing.JOptionPane
class AppRemoteControl extends RemoteControl {
public AppRemoteControl(Transport transport, BytesCachedGroovyClassLoader classLoader) {
super(transport, new RemoteCommandGenerator(classLoader))
}
}
class BytesCachedClassCollector extends GroovyClassLoader.ClassCollector {
def cache = [:]
protected BytesCachedClassCollector(GroovyClassLoader.InnerLoader cl, CompilationUnit unit, SourceUnit su) {
super(cl, unit, su)
}
@Override
protected Class createClass(byte[] code, ClassNode classNode) {
cache[classNode.name] = code
return super.createClass(code, classNode)
}
}
class BytesCachedGroovyClassLoader extends GroovyClassLoader {
def classCollector;
protected GroovyClassLoader.ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
GroovyClassLoader.InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader.InnerLoader>() {
public GroovyClassLoader.InnerLoader run() {
return new GroovyClassLoader.InnerLoader(BytesCachedGroovyClassLoader.this)
}
});
classCollector = new BytesCachedClassCollector(loader, unit, su)
}
}
class RemoteCommandGenerator extends CommandGenerator {
public RemoteCommandGenerator(BytesCachedGroovyClassLoader cl) {
super(cl)
}
protected byte[] getClassBytes(Class closureClass) {
def classBytes = classLoader.classCollector.cache[closureClass.name]
if (classBytes == null) {
throw new IllegalStateException("Could not find class file for class [${closureClass.name}]");
}
classBytes
}
@Override
protected List<byte[]> getSupportingClassesBytes(Class closureClass) {
def className = closureClass.name
classLoader.classCollector.cache.inject([]) { classes, entry ->
if (entry.key != className && entry.key.startsWith(className)) {
classes << entry.value
}
classes
}
}
}
class Model {
@Bindable remoteUrl
}
def model = new Model(remoteUrl:args ? args[0] : 'http://localhost:8080/plugin/groovy-remote/')
def remoteMenu = {
def configPanel = panel {
gridLayout(cols:1, rows:2)
label 'Remote Receiver URL:'
textField(text:bind('remoteUrl', source:model, mutual:true))
}
menu('Remote Control') {
menuItem('Configuration', actionPerformed:{
optionPane(message:configPanel, optionType:JOptionPane.DEFAULT_OPTION).with {
createDialog('Configuration').show()
}
})
}
}
Console.metaClass.newScript = { ClassLoader parent, Binding binding ->
delegate.shell = new GroovyShell(parent, binding)
delegate.shell.metaClass.run = { String scriptText, String fileName, List list ->
def cl = new BytesCachedGroovyClassLoader()
binding.remote = new AppRemoteControl(new HttpTransport(model.remoteUrl), cl)
Script s = (Script) cl.parseClass(scriptText).newInstance()
s.binding = binding
s.run()
}
}
UIManager.lookAndFeel = UIManager.systemLookAndFeelClassName
new Console(Console.class.classLoader.getRootLoader()).run(
Console.frameConsoleDelegates << [menuBarDelegate: {arg->
current.JMenuBar = build(arg)
current.JMenuBar.add(build(remoteMenu))
}
])