1 package org.andromda.scriptwrappers;
2
3 import java.lang.reflect.Method;
4 import java.util.Arrays;
5 import java.util.Iterator;
6 import java.util.LinkedHashSet;
7 import java.util.Set;
8 import bsh.EvalError;
9 import bsh.Interpreter;
10 import bsh.Primitive;
11
12
13
14
15
16
17
18
19 public class BshScriptWrapper
20 {
21 private final Interpreter interpreter;
22 private String scriptPath;
23 private Object stub;
24
25
26
27
28
29
30
31
32 public BshScriptWrapper(
33 Object stub,
34 String scriptPath)
35 throws InstantiationError
36 {
37 this.stub = stub;
38 this.scriptPath = scriptPath;
39 this.interpreter = initialize(
40 stub,
41 scriptPath);
42 }
43
44 @SuppressWarnings("unused")
45 private BshScriptWrapper()
46 {
47 this.interpreter = null;
48 }
49
50
51
52
53
54
55
56
57 private final Interpreter initialize(
58 Object stub,
59 String scriptPath)
60 {
61 final Interpreter interpreter = new Interpreter();
62 interpreter.setClassLoader(stub.getClass().getClassLoader());
63 return interpreter;
64 }
65
66
67
68
69
70
71
72
73 public Object invoke(
74 String methodName,
75 Object[] args)
76 {
77 try
78 {
79 try
80 {
81 final Class stubClass = stub.getClass();
82 this.interpreter.source(scriptPath);
83 this.interpreter.set(
84 "instance",
85 interpreter.eval(" new " + stubClass.getName() + "();"));
86 this.interpreter.set(
87 "stub",
88 stub);
89
90
91 this.interpreter.eval(BshScriptWrapper.class.getName() + ".copyProperties(stub, instance);");
92 }
93 catch (final Exception exception)
94 {
95 exception.printStackTrace();
96 throw new InstantiationError("Problems instantiating script '" + scriptPath + "':" + exception);
97 }
98 final StringBuilder arguments = new StringBuilder();
99 if (args != null)
100 {
101 for (int ctr = 1; ctr <= args.length; ctr++)
102 {
103 final String argument = "$" + ctr;
104 this.interpreter.set(
105 argument,
106 args[ctr - 1]);
107 arguments.append(argument);
108 if (ctr != args.length)
109 {
110 arguments.append(", ");
111 }
112 }
113 }
114
115 Object returnValue = this.interpreter.eval("instance." + methodName + '(' + arguments + ");");
116
117 if (returnValue instanceof bsh.Primitive)
118 {
119 returnValue = Primitive.unwrap(returnValue);
120 }
121
122 return returnValue;
123 }
124 catch (EvalError exception)
125 {
126 throw new RuntimeException(exception);
127 }
128 }
129
130
131
132
133
134
135
136
137
138 protected static void copyProperties(
139 final Object from,
140 final Object to)
141 throws Exception
142 {
143 final Set<Method> methods = new LinkedHashSet<Method>();
144 loadSuperMethods(
145 from.getClass(),
146 methods);
147 for (final Iterator iterator = methods.iterator(); iterator.hasNext();)
148 {
149 final Method method = (Method)iterator.next();
150
151 final String methodName = method.getName();
152 final String getPrefix = "get";
153 if (methodName.startsWith(getPrefix) && method.getParameterTypes().length == 0)
154 {
155 String propertyName = methodName.replaceAll(
156 getPrefix,
157 "");
158
159 Method setterMethod = null;
160 try
161 {
162 setterMethod =
163 from.getClass().getMethod(
164 "set" + propertyName,
165 new Class[] {method.getReturnType()});
166 }
167 catch (final Exception exception)
168 {
169
170 }
171 if (setterMethod != null)
172 {
173 method.setAccessible(true);
174 final Object value = method.invoke(from);
175 setterMethod.invoke(
176 to,
177 value);
178 }
179 }
180 }
181 }
182
183
184
185
186
187
188
189
190 private static Set loadSuperMethods(
191 final Class clazz,
192 final Set methods)
193 {
194 if (clazz.getSuperclass() != null)
195 {
196 methods.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredMethods()));
197 methods.addAll(loadSuperMethods(
198 clazz.getSuperclass(),
199 methods));
200 }
201 return methods;
202 }
203 }