001: package tide.execute;
002:
003: import snow.utils.gui.*; // => needs tide.jar on classpath...
004: import java.awt.BorderLayout;
005: import java.awt.EventQueue;
006: import java.awt.FlowLayout;
007: import java.lang.reflect.*;
008: import java.util.*;
009: import javax.swing.*;
010:
011: /** Utility to start static methods.
012: *
013: * Useful to quick evaluate some static method, not only the "public static void main(String[] args)"
014: * Uses reflection to launch the selected method.
015: * The method must have basic types arguments, for example empty or string, doublt, int, ...
016: * <p>
017: * This starter should be launched from a new JVM with the class path of the project containing the class to launch.
018: * Not to be called in tIDE itself (classes pollution).
019: *
020: * Ex: java -cp=XXX;yyy path/to/StaticStarter path/to/class/to/launch methodName String;String[];int;double a;b;c;d "12";"13"
021: * if the values are not complete, a dialog opens
022: * names may also be empty
023: *
024: * => DO NOT OBFUSCATE !
025: <proguard entry>
026: -keepclasseswithmembers class StaticStarter {
027: public static void main(java.lang.String[]);
028: }
029: -keep class StaticStarter* # also the inner classes!!
030: </proguard entry>
031:
032: IN PROGRESS....
033:
034: */
035: public final class StaticStarter {
036: private StaticStarter() {
037: }
038:
039: private static boolean paramDialog(final String helloText,
040: final List<String> types_list, final List<String> names,
041: final List<String> valuesDef, final List<Object> values) {
042: // if empty, direct call !
043: if (types_list.isEmpty())
044: return true;
045:
046: final JFrame ff = new JFrame();
047: final JDialog f = new JDialog(ff, "Arguments", true);
048:
049: final CloseControlPanel ccp = new CloseControlPanel(f, true,
050: true, "Launch");
051: ccp.getOkButton().setIcon(Icons.sharedSmallStart);
052: JPanel pan = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
053: f.add(new JScrollPane(pan), BorderLayout.CENTER);
054: f.add(ccp, BorderLayout.SOUTH);
055:
056: GridLayout3 gl3 = new GridLayout3(2, pan);
057: if (helloText != null) {
058: gl3.addExplanationArea(helloText);
059: }
060:
061: final List<JTextField> tfis = new ArrayList<JTextField>();
062: boolean firstField = true;
063: for (int i = 0; i < types_list.size(); i++) {
064: String nam = "p" + (i + 1);
065: if (names.size() > i)
066: nam = "" + names.get(i);
067:
068: nam += " [" + types_list.get(i) + "] ";
069:
070: gl3.add(nam);
071: final JTextField tfi = new JTextField(10);
072: if (i == 0) {
073: EventQueue.invokeLater(new Runnable() {
074: public void run() {
075: tfi.requestFocus();
076: tfi.requestFocusInWindow();
077: }
078: });
079: }
080: tfis.add(tfi);
081: gl3.add(tfi);
082:
083: if (valuesDef.size() > i) {
084: tfi.setText("" + valuesDef.get(i));
085: }
086:
087: if (firstField) {
088: firstField = false;
089: tfi.requestFocusInWindow(); // so we can start to type !
090: }
091: }
092:
093: f.pack();
094: f.setLocationRelativeTo(null);
095: f.setVisible(true);
096:
097: if (ccp.getWasCancelled())
098: return false;
099:
100: for (int i = 0; i < types_list.size(); i++) {
101: try {
102: values.add(parse(tfis.get(i).getText(), types_list
103: .get(i)));
104: } catch (Exception e) {
105: e.printStackTrace(); //TODO, show errors, store, ...
106: }
107: }
108:
109: return true;
110: }
111:
112: /** if type ends with [ ], an array is parsed, separated with ","
113: * deeper are not supported now.
114: */
115: private static Object parse(String val, String type)
116: throws Exception {
117: if (type.endsWith("String[]")) {
118: String type0 = type.substring(0, type.length() - 2);
119:
120: String[] spls = val.split(",");
121: String[] res = new String[spls.length];
122: int i = 0;
123: for (String si : spls) {
124: res[i++] = "" + parse(si.trim(), type0);
125: }
126:
127: return res;
128: }
129:
130: // todo: int[], double[], int[][][][] !!
131:
132: if (type.contains("String")) {
133: return val;
134: } else if (type.contains("double")) {
135: return Double.parseDouble(val);
136: } else if (type.contains("int")) {
137: return Integer.parseInt(val);
138: } else if (type.contains("boolean")) {
139: return Boolean.parseBoolean(val);
140: }
141:
142: throw new Exception("Unknown type " + type);
143: //return val;
144: }
145:
146: public static void hello() {
147: System.out.println("Hello");
148: }
149:
150: public static int hello(int a) {
151: JOptionPane.showMessageDialog(null, "HELLO2 " + a);
152: return 123;
153: }
154:
155: public static int hello2(int a, int b, String ss) {
156: JOptionPane.showMessageDialog(null, "HELLO(int,int,String) "
157: + a + " " + b + " " + ss);
158: return 1234;
159: }
160:
161: public static int hello(int a, String[] abcd) {
162: JOptionPane.showMessageDialog(null, "HELLO2 " + a);
163: return 12345;
164: }
165:
166: /** The starter itself has a main method :-).
167: * @param args Arguments are { path/to/the/class/to/launch, methodname, types_list, names_list, values_list
168: *
169: * EXITS THE JVM AT END.
170: */
171: public static void main(final String[] args) throws Exception {
172: System.out.println("StaticStarter: " + Arrays.asList(args));
173: if (args == null || args.length < 2) {
174: System.err.println("Can't static start: bad args: "
175: + Arrays.asList(args));
176: //JOptionPane.showMessageDialog(null, "Can't static start !", "Error", JOptionPane.ERROR_MESSAGE);
177: System.exit(0);
178: return;
179: }
180:
181: String className = args[0]; //"StaticStarter";
182: String methodName = args[1]; //"hello";
183: List<String> types_list = new ArrayList<String>();
184: if (args.length > 2) {
185: types_list.addAll(Arrays.asList(args[2].split(";")));
186: }
187:
188: List<String> types_names = new ArrayList<String>();
189: if (args.length > 3) {
190: types_names.addAll(Arrays.asList(args[3].split(";")));
191: }
192:
193: List<String> types_defVals = new ArrayList<String>();
194: if (args.length > 4) {
195: types_defVals.addAll(Arrays.asList(args[4].split(";")));
196: }
197:
198: // todo: warn if fail (java.lang.ClassNotFoundException)
199: Class cl = Class.forName(className); //
200:
201: Method[] mis = cl.getDeclaredMethods();
202: Method found = null;
203: List<Method> staticCandidates = new ArrayList<Method>();
204: for (final Method mi : mis) {
205: //System.out.println(""+mi); // public static int tide.execute.StaticStarter.hello(int,java.lang.String[])
206: if (Modifier.isStatic(mi.getModifiers())) {
207: staticCandidates.add(mi);
208: } else
209: continue;
210:
211: if (!mi.getName().equals(methodName))
212: continue;
213:
214: // TODO: look at args types
215: final Class<?>[] paramTypes = mi.getParameterTypes();
216: //System.out.println(""+paramTypes.length);
217: if (types_list.size() != paramTypes.length)
218: continue; // ensure correct number of arguments.
219:
220: found = mi;
221: break;
222: }
223:
224: if (found == null) {
225: System.err.println("No method " + methodName + " with "
226: + types_defVals.size() + " params found in\n\n "
227: + className + "\n");
228: System.err
229: .println("There are "
230: + staticCandidates.size()
231: + " static methods that can be called in this class:");
232: for (Method mi : staticCandidates) {
233: System.err.println("" + mi.toGenericString());
234: }
235: //JOptionPane.showMessageDialog(null, "No method "+methodName+" found in\n\n "+className+"\n", "Error", JOptionPane.ERROR_MESSAGE);
236: System.exit(0);
237: return;
238: }
239:
240: if (!Modifier.isStatic(found.getModifiers())) {
241: System.err
242: .println("The method "
243: + methodName
244: + " in\n\n "
245: + className
246: + "\n\nis not static. Cannot launch it with StaticStarter.");
247: //JOptionPane.showMessageDialog(null, "The method "+methodName+" in\n\n "+className+"\n\nis not static. Cannot launch it with StaticStarter.", "Error", JOptionPane.ERROR_MESSAGE);
248: System.exit(0);
249: return;
250: }
251:
252: // TODO: ask types...
253: List<Object> argValues = new ArrayList<Object>();
254: //argValues.add(1);
255: //argValues.add(2);
256:
257: if (paramDialog(
258: "Starting\n\n " + className + "." + methodName,
259: types_list, types_names, types_defVals, argValues)) {
260: try {
261: Object res = found.invoke(null, argValues
262: .toArray(new Object[argValues.size()])); // null first arg => static invoke
263:
264: if (found.getReturnType() != Void.TYPE) {
265:
266: if (res instanceof JComponent) {
267: GUIUtils.displayInFrame(
268: "Static starter result",
269: (JComponent) res, true);
270: } else {
271: System.out
272: .println("Static starter ended, return value["
273: + found.getReturnType()
274: + "] = " + res);
275: }
276:
277: //JOptionPane.showMessageDialog(null, "Return value ["+found.getReturnType()+"]:\n\n"+res, "Evaluation result", JOptionPane.INFORMATION_MESSAGE);
278: } else {
279: System.out.println("Static starter ended");
280: }
281: } catch (Error e) {
282: System.err
283: .println("Error occured during static call on "
284: + found);
285: System.err.println("Values=" + argValues);
286: e.printStackTrace();
287: } catch (Exception e) {
288: System.err
289: .println("Exception occured during static call on "
290: + found);
291: System.err.println("Values=" + argValues);
292: e.printStackTrace();
293: }
294: }
295:
296: System.exit(0);
297:
298: }
299:
300: }
|