Source code: com/prolifics/jni/UCIHelper.java
1 /* @(#)UCIHelper.java 77.20 00/07/18 17:48:38" */
2
3 /*************************************************/
4 /* Copyright (c) 2000 */
5 /* by */
6 /* JYACC, Inc., New York NY USA */
7 /* and contributors. */
8 /* Use of this program is governed by the */
9 /* JYACC Public License Version 1.0, a copy of */
10 /* which can be obtained at */
11 /* http://www.possl.org/jyacc-license.html */
12 /*************************************************/
13
14 package com.prolifics.jni;
15
16 import com.prolifics.ejb.*;
17 import java.lang.reflect.*;
18 import java.util.*;
19
20 class InOutParameter
21 {
22 boolean isInOut;
23 boolean isArray;
24 Class wrapper;
25 Class valueType;
26
27 static Hashtable d = new Hashtable();
28
29 private InOutParameter() { }
30 private InOutParameter(Class wrapper)
31 {
32 try {
33 valueType = wrapper.getDeclaredField("value").getType();
34 this.wrapper = wrapper;
35 isArray = valueType.isArray();
36 isInOut = true;
37 d.put(wrapper, this);
38 } catch (NoSuchFieldException e) {
39 }
40 }
41
42 static InOutParameter notInOut = new InOutParameter();
43
44 static {
45 new InOutParameter(SmWSIntHolder.class);
46 new InOutParameter(SmWSBooleanHolder.class);
47 new InOutParameter(SmWSDoubleHolder.class);
48 new InOutParameter(SmWSStringHolder.class);
49 new InOutParameter(SmWSObjectHolder.class);
50 new InOutParameter(SmWSIntArrayHolder.class);
51 new InOutParameter(SmWSBooleanArrayHolder.class);
52 new InOutParameter(SmWSDoubleArrayHolder.class);
53 new InOutParameter(SmWSStringArrayHolder.class);
54 new InOutParameter(SmWSObjectArrayHolder.class);
55 }
56
57 public static InOutParameter forType(Class type)
58 {
59 InOutParameter iop = (InOutParameter)d.get(type);
60 return iop == null ? notInOut : iop;
61 }
62 }
63
64 public class UCIHelper implements Constants
65 {
66 private final boolean enableDebug = false;
67
68 public Object returnValue = null;
69
70 public int lastError = 0;
71 public int lastObjError = 0;
72 public String lastMessage = null;
73
74 private Method resolvedMethod = null;
75 private Constructor resolvedConstructor = null;
76 private String argumentTypes = null;
77 private Class sig[];
78
79 private final Class oneString[] = { String.class };
80
81 private static final Hashtable stringToClass = new Hashtable();
82 static {
83 stringToClass.put("boolean", Boolean.TYPE);
84 stringToClass.put("byte", Byte.TYPE);
85 stringToClass.put("char", Character.TYPE);
86 stringToClass.put("double", Double.TYPE);
87 stringToClass.put("float", Float.TYPE);
88 stringToClass.put("int", Integer.TYPE);
89 stringToClass.put("long", Long.TYPE);
90 stringToClass.put("short", Short.TYPE);
91 }
92
93 private static final Hashtable classToWrapper = new Hashtable();
94 static {
95 classToWrapper.put(Boolean.TYPE, Boolean.class);
96 classToWrapper.put(Byte.TYPE, Byte.class);
97 classToWrapper.put(Character.TYPE, Character.class);
98 classToWrapper.put(Double.TYPE, Double.class);
99 classToWrapper.put(Float.TYPE, Float.class);
100 classToWrapper.put(Integer.TYPE, Integer.class);
101 classToWrapper.put(Long.TYPE, Long.class);
102 classToWrapper.put(Short.TYPE, Short.class);
103 }
104
105 private void
106 setArgumentTypes(Class types[])
107 {
108 StringBuffer s = new StringBuffer(3 * types.length);
109 debug(types);
110 for (int i = types.length - 1; i >= 0; --i)
111 {
112 Class t = types[i];
113 InOutParameter iop = InOutParameter.forType(t);
114 debug(t);
115
116 if (iop.isInOut)
117 {
118 t = iop.valueType;
119 s.append('I'); // InOut scalar
120 }
121 else
122 s.append('-');
123
124 if (t.isArray())
125 {
126 t = t.getComponentType();
127 s.append('A'); // array
128 }
129 else
130 s.append('-');
131
132 if (t.isPrimitive() || t == String.class)
133 s.append('-'); // primitive (or string)
134 else
135 s.append('O'); // object
136 }
137 argumentTypes = s.toString();
138 debug(argumentTypes);
139 }
140
141 public UCIHelper()
142 {
143 debug("UCIHelper constructor called");
144 }
145
146 protected void
147 debug(Object s)
148 {
149 if (enableDebug)
150 System.out.println(s);
151 }
152
153 protected void
154 debug(int s)
155 {
156 if (enableDebug)
157 System.out.println(s);
158 }
159
160 private void
161 marshalArguments(Object cargs,
162 String args[], Object argtype) throws Error, Throwable
163 {
164 debug("marshalArguments(args, argtype)");
165 debug(args);
166 debug(args.length);
167 debug(argtype);
168
169 for (int i = 0; i < args.length; ++i)
170 {
171 Object arg = args[i];
172 Object nobj;
173 Class type;
174 if (argtype.getClass().isArray())
175 type = ((Class [])argtype)[i];
176 else
177 type = (Class)argtype;
178
179 debug(arg);
180 debug(type);
181
182 InOutParameter iop = InOutParameter.forType(type);
183 if (iop.isInOut)
184 type = iop.valueType;
185
186 if (iop.isArray ||
187 arg != null && arg.getClass().isArray())
188 {
189 nobj = null;
190 if (Array.getLength(arg) != 0)
191 {
192 nobj = Array.newInstance(
193 type.getComponentType(),
194 Array.getLength(arg));
195 marshalArguments(
196 nobj,
197 (String [])arg,
198 type.getComponentType());
199 }
200 }
201 else
202 {
203 if (arg != null &&
204 arg.getClass() == String.class)
205 nobj = makeObject(type, (String)arg);
206 else
207 nobj = arg;
208 }
209 if (iop.isInOut)
210 {
211 Object wrapper = iop.wrapper.newInstance();
212 iop.wrapper.getField("value").
213 set(wrapper, nobj);
214 nobj = wrapper;
215 }
216 Array.set(cargs, i, nobj);
217 }
218 }
219
220 private Object
221 resizeArray(Object obj, Object ref)
222 {
223 int nsize = 0;
224 if (ref != null)
225 nsize = Array.getLength(ref);
226 debug("resizing array to " + nsize);
227 return Array.newInstance(obj.getClass().
228 getComponentType(), nsize);
229 }
230
231 private void
232 unmarshalArguments(Object args[], Object cargs,
233 boolean all, boolean isObject) throws Exception
234 {
235 debug("unmarshalling: args.length = " + args.length);
236
237 int atidx = argumentTypes.length();
238 debug ("atidx = " + atidx);
239
240 for (int i = 0; i < args.length; ++i)
241 {
242 Object obj = Array.get(cargs, i);
243 debug ("obj = " + obj);
244
245 atidx -= 3;
246 boolean isInOut = false;
247 boolean isArray = false;
248
249 if (!all)
250 {
251 isInOut = argumentTypes.
252 charAt(atidx) == 'I';
253 isArray = argumentTypes.
254 charAt(atidx + 1) == 'A';
255 isObject = argumentTypes.
256 charAt(atidx + 2) == 'O';
257 }
258
259 if (all || isInOut || isArray)
260 {
261 if (isInOut)
262 {
263 debug ("i = " + i +
264 ", obj = " + obj);
265 obj = obj.getClass().
266 getField("value").get(obj);
267 debug ("i = " + i +
268 ", obj = " + obj);
269 }
270 if (isArray)
271 {
272 debug("recurse");
273 if (isInOut)
274 {
275 args[i] =
276 resizeArray(args[i],
277 obj);
278 }
279 unmarshalArguments((Object[])args[i],
280 obj,
281 true,
282 isObject);
283 debug("back");
284 }
285 else if (isObject)
286 {
287 args[i] = obj;
288 debug("copy out as object args[" +
289 i + "] = " + args[i]);
290 }
291 else
292 {
293 if (obj == null)
294 args[i] = null;
295 else
296 args[i] = obj.toString();
297
298 debug("copy out args[" +
299 i + "] = " + args[i]);
300 }
301 }
302 }
303 }
304
305 private Method
306 getMethod(Class clazz, String name, int count) throws Error
307 {
308 debug("in getMethod");
309 if (sig != null)
310 {
311 try
312 {
313 return clazz.getMethod(name, sig);
314 }
315 catch (NoSuchMethodException e)
316 {
317 throw new Error(PR_E_ERROR, SM_NOFUNC, name);
318 }
319 }
320
321 Method match = null;
322 Method methods[] = clazz.getMethods();
323
324 for (int i = 0; i < methods.length; ++i)
325 {
326 Method m = methods[i];
327 if (m.getName().equals(name) &&
328 m.getParameterTypes().length == count)
329 {
330 debug("found " + m.getName());
331 if (match != null)
332 {
333 throw new Error(PR_E_ERROR,
334 SM_MULTFUNC, name);
335 }
336 match = m;
337 }
338 }
339
340 if (match == null)
341 throw new Error(PR_E_ERROR, SM_NOFUNC, name);
342
343 return match;
344 }
345
346 private Constructor
347 getConstructor(Class clazz, int count) throws Error
348 {
349 debug("getConstructor(" + clazz + ", " + count + ")");
350 if (sig != null)
351 {
352 try
353 {
354 debug(sig);
355 debug(sig.length);
356 return clazz.getConstructor(sig);
357 }
358 catch (NoSuchMethodException e)
359 {
360 throw new Error(PR_E_ERROR,
361 SM_NOFUNC, clazz.getName());
362 }
363 }
364
365 debug(clazz);
366
367 Constructor match = null;
368 Constructor methods[] = clazz.getConstructors();
369
370 for (int i = 0; i < methods.length; ++i)
371 {
372 Constructor m = methods[i];
373 if (m.getParameterTypes().length == count)
374 {
375 if (match != null)
376 {
377 throw new Error(PR_E_ERROR,
378 SM_MULTFUNC, clazz.getName());
379 }
380 match = m;
381 }
382 }
383
384 if (match == null)
385 throw new Error(PR_E_ERROR,
386 SM_NOFUNC, clazz.getName());
387
388 return match;
389 }
390
391 public String
392 resolveMethod(Class clazz, Object object, String name, int count)
393 throws Exception
394 {
395 debug("resolveMethod called (class, object, name, count)");
396 debug(clazz);
397 debug(object);
398 debug(name);
399 debug(count);
400
401 if (name == null)
402 return resolveConstructor(clazz, count);
403
404 try {
405 resolvedMethod = getMethod(clazz, name, count);
406 } catch (Error e) {
407 return null;
408 }
409
410 debug(resolvedMethod);
411
412 if (resolvedMethod == null)
413 return null;
414
415 setArgumentTypes(resolvedMethod.getParameterTypes());
416 debug("returning, loa = " + argumentTypes);
417 return argumentTypes;
418 }
419
420 public int
421 callMethod(Class clazz, Object object, String args[]) throws Throwable
422 {
423 debug("callMethod called (class, object, args)");
424 debug(clazz);
425 debug(object);
426 debug(args);
427
428 if (resolvedConstructor != null)
429 return callConstructor(clazz, args);
430
431 Object oargs[] = null;
432 if (args != null)
433 {
434 oargs = new Object[args.length];
435 try {
436 marshalArguments(oargs, args,
437 resolvedMethod.getParameterTypes());
438 } catch (Error e) {
439 return -1;
440 }
441 debug("before invoke");
442 debug(oargs.getClass());
443 debug(oargs.length);
444 for (int i = 0; i < oargs.length; ++i)
445 debug(oargs[i]);
446 }
447
448 Class t = resolvedMethod.getReturnType();
449 debug("return type is " + t.toString());
450
451 try {
452 returnValue = resolvedMethod.invoke(object, oargs);
453 } catch (InvocationTargetException e1) {
454 throw e1.getTargetException();
455 }
456
457 debug("returnValue is " + returnValue);
458 if (t.isPrimitive() || t == String.class)
459 if (returnValue != null)
460 returnValue = returnValue.toString();
461
462 debug("after invoke");
463 if (args != null)
464 unmarshalArguments(args, oargs, false, false);
465
466 return 0;
467 }
468
469 public String
470 resolveConstructor(Class clazz, int count) throws Exception
471 {
472 debug("resolveConstructor called");
473 debug(clazz);
474 debug(count);
475
476 try {
477 resolvedConstructor = getConstructor(clazz, count);
478 } catch (Error e) {
479 return null;
480 }
481
482 debug(resolvedConstructor);
483 if (resolvedConstructor == null)
484 return null;
485
486 setArgumentTypes(resolvedConstructor.getParameterTypes());
487 return argumentTypes;
488 }
489
490 public int
491 callConstructor(Class clazz, String args[]) throws Throwable
492 {
493 debug("callConstructor called");
494 debug(clazz);
495 debug(args);
496
497 Object oargs[] = new Object[args.length];
498 try {
499 marshalArguments(oargs,
500 args, resolvedConstructor.getParameterTypes());
501 } catch (Error e) {
502 return -1;
503 }
504 returnValue = resolvedConstructor.newInstance(oargs);
505 unmarshalArguments(args, oargs, false, false);
506
507 return 0;
508 }
509
510 private Class
511 wrap(Class dst)
512 {
513 if (!dst.isPrimitive())
514 return dst;
515
516 return (Class)classToWrapper.get(dst);
517 }
518
519 private Object
520 makeObject(Class dst, String s) throws Error, Throwable
521 {
522 try {
523 try {
524 debug(dst);
525 if (dst == s.getClass())
526 return s;
527 dst = wrap(dst);
528 debug(s);
529 return dst.getConstructor(oneString).
530 newInstance(new Object[] { s });
531 } catch (InvocationTargetException e) {
532 throw e.getTargetException();
533 }
534 } catch (NumberFormatException e) {
535 if (dst == Integer.class)
536 {
537 try {
538 return new Integer(Double.valueOf(s).
539 intValue());
540 } catch (NumberFormatException e1) {
541 }
542 }
543 return dst.getConstructor(oneString).
544 newInstance(new Object[] { "0" });
545 } catch (IllegalArgumentException e) {
546 throw new Error(PR_E_ARGS, SM_MISMATCH, dst.getName());
547 } catch (Throwable e) {
548 new Error(PR_E_ARGS, SM_MISMATCH, dst.getName());
549 throw e;
550 }
551 }
552
553 public String
554 getProperty(Object obj, String prop)
555 {
556 debug("getProperty " + obj.getClass() + "->" + prop);
557 Class c;
558 try {
559 c = obj.getClass();
560 } catch (Throwable e) {
561 new Error(PR_E_OBJID, SM_PR_OBJID, null);
562 return null;
563 }
564 try {
565 return c.getField(prop).get(obj).toString();
566 } catch (Throwable e) {
567 new Error(PR_E_PROP, SM_PR_PROP, prop);
568 return null;
569 }
570 }
571
572 public int
573 setProperty(Object obj, String prop, String val)
574 {
575 debug("setProperty " + obj.getClass() + "->" + prop);
576 Class c;
577 try {
578 c = obj.getClass();
579 } catch (Throwable e) {
580 new Error(PR_E_OBJID, SM_PR_OBJID, null);
581 return -1;
582 }
583 java.lang.reflect.Field f;
584 try {
585 f = c.getField(prop);
586 } catch (Throwable e) {
587 new Error(PR_E_PROP, SM_PR_PROP, prop);
588 return -1;
589 }
590 try {
591 Object v = makeObject(f.getType(), val);
592 f.set(obj, v);
593 return 0;
594 } catch (Error e) {
595 return -1;
596 }
597 catch (Throwable e) {
598 new Error(PR_E_PROP_VAL, SM_PR_PROP_VAL, val);
599 return -1;
600 }
601 }
602
603 protected class Error extends Exception
604 {
605 public Error(int objerror, int msgnum, String s)
606 {
607 lastObjError = objerror;
608 lastError = msgnum;
609 lastMessage = s;
610 }
611 };
612
613 public int
614 xlateDescriptor(String prodesc)
615 {
616 Vector vsig = new Vector();
617
618 prodesc = prodesc.trim();
619
620 if (!prodesc.startsWith("("))
621 {
622 new Error(PR_E_ERROR, SM_MISSLEFTPAREN, prodesc);
623 return -1;
624 }
625
626 String buf = "";
627
628 prodesc = prodesc.substring(1).trim();
629 if (!prodesc.startsWith(")"))
630 for (;;)
631 {
632 Class clazz;
633
634 debug("rest of prodesc is '" + prodesc + "'");
635
636 if (!Character.
637 isJavaIdentifierStart(prodesc.charAt(0)))
638 {
639 new Error(PR_E_ERROR, SM_NONAME, prodesc);
640 return -1;
641 }
642
643 while (Character.
644 isJavaIdentifierPart(prodesc.
645 charAt(0)) ||
646 prodesc.startsWith(".") ||
647 prodesc.startsWith("/"))
648 {
649 String h = prodesc.substring(0, 1);
650 if (h.equals("/"))
651 h = ".";
652 buf += h;
653 prodesc = prodesc.substring(1);
654 }
655
656 prodesc = prodesc.trim();
657
658 if (buf == "")
659 break;
660
661 debug("need class " + buf);
662 if ((clazz = (Class)stringToClass.get(buf)) == null)
663 {
664 debug("not primitive");
665 try
666 {
667 clazz = Class.forName(buf);
668 }
669 catch (ClassNotFoundException e)
670 {
671 debug("not qualified");
672 clazz = null;
673 }
674 if (clazz == null) try
675 {
676 debug("qualified?");
677 clazz = Class.forName("java.lang.".
678 concat(buf));
679 }
680 catch (ClassNotFoundException e)
681 {
682 debug("not found!");
683 new Error(PR_E_OBJ_TYPE,
684 JV_NOCLASS, buf);
685 return -1;
686 }
687 }
688
689 if (prodesc.startsWith("["))
690 {
691 // we only support a one-
692 // dimensional arrays
693 prodesc = prodesc.substring(1).trim();
694 if (!prodesc.startsWith("]"))
695 {
696 new Error(PR_E_ARGS,
697 SM_MISKET, prodesc);
698 return -1;
699 }
700 prodesc = prodesc.substring(1);
701 clazz = Array.newInstance(clazz, 0).
702 getClass();
703 }
704
705 debug("got class " + clazz.toString());
706 vsig.addElement(clazz);
707
708 prodesc = prodesc.trim();
709
710 if (!prodesc.startsWith(","))
711 break;
712 }
713
714 if (!prodesc.trim().equals(")"))
715 {
716 if (!prodesc.startsWith(")"))
717 {
718 new Error(PR_E_ARGS, SM_MISSPARENS, prodesc);
719 return -1;
720 }
721 new Error(PR_E_ARGS, SM_EXCESS, prodesc);
722 return -1;
723 }
724
725 sig = new Class[vsig.size()];
726 vsig.copyInto(sig);
727
728 return 0;
729 }
730 };