1 package org.perl.inline.java ; 2 3 import java.util.* ; 4 import java.io.* ; 5 import java.lang.reflect.* ; 6 7 8 /* 9 This is where most of the work of Inline Java is done. Here determine 10 the request type and then we proceed to serve it. 11 */ 12 class InlineJavaProtocol { 13 private InlineJavaServer ijs ; 14 private InlineJavaClass ijc ; 15 private InlineJavaArray ija ; 16 private String cmd ; 17 private String response = null ; 18 19 private final String encoding = "UTF-8" ; 20 21 static private Map member_cache = Collections.synchronizedMap(new HashMap()) ; 22 static private final String report_version = "V2" ; 23 InlineJavaProtocol(InlineJavaServer _ijs, String _cmd)24 InlineJavaProtocol(InlineJavaServer _ijs, String _cmd) { 25 ijs = _ijs ; 26 ijc = new InlineJavaClass(ijs, this) ; 27 ija = new InlineJavaArray(ijc) ; 28 29 cmd = _cmd ; 30 } 31 32 33 /* 34 Starts the analysis of the command line 35 */ Do()36 void Do() throws InlineJavaException { 37 StringTokenizer st = new StringTokenizer(cmd, " ") ; 38 String c = st.nextToken() ; 39 40 if (c.equals("call_method")){ 41 CallJavaMethod(st) ; 42 } 43 else if (c.equals("set_member")){ 44 SetJavaMember(st) ; 45 } 46 else if (c.equals("get_member")){ 47 GetJavaMember(st) ; 48 } 49 else if (c.equals("add_classpath")){ 50 AddClassPath(st) ; 51 } 52 else if (c.equals("server_type")){ 53 ServerType(st) ; 54 } 55 else if (c.equals("report")){ 56 Report(st) ; 57 } 58 else if (c.equals("isa")){ 59 IsA(st) ; 60 } 61 else if (c.equals("create_object")){ 62 CreateJavaObject(st) ; 63 } 64 else if (c.equals("delete_object")){ 65 DeleteJavaObject(st) ; 66 } 67 else if (c.equals("obj_cnt")){ 68 ObjectCount(st) ; 69 } 70 else if (c.equals("cast")){ 71 Cast(st) ; 72 } 73 else if (c.equals("read")){ 74 Read(st) ; 75 } 76 else if (c.equals("make_buffered")){ 77 MakeBuffered(st) ; 78 } 79 else if (c.equals("readline")){ 80 ReadLine(st) ; 81 } 82 else if (c.equals("write")){ 83 Write(st) ; 84 } 85 else if (c.equals("close")){ 86 Close(st) ; 87 } 88 else if (c.equals("die")){ 89 InlineJavaUtils.debug(1, "received a request to die...") ; 90 ijs.Shutdown() ; 91 } 92 else { 93 throw new InlineJavaException("Unknown command " + c) ; 94 } 95 } 96 97 /* 98 Returns a report on the Java classes, listing all public methods 99 and members 100 */ Report(StringTokenizer st)101 void Report(StringTokenizer st) throws InlineJavaException { 102 StringBuffer pw = new StringBuffer(report_version + "\n") ; 103 104 StringTokenizer st2 = new StringTokenizer(st.nextToken(), ":") ; 105 st2.nextToken() ; 106 107 StringTokenizer st3 = new StringTokenizer(Decode(st2.nextToken()), " ") ; 108 109 ArrayList class_list = new ArrayList() ; 110 while (st3.hasMoreTokens()){ 111 String c = st3.nextToken() ; 112 class_list.add(class_list.size(), c) ; 113 } 114 115 for (int i = 0 ; i < class_list.size() ; i++){ 116 String name = (String)class_list.get(i) ; 117 Class c = ijc.ValidateClass(name) ; 118 119 InlineJavaUtils.debug(3, "reporting for " + c) ; 120 121 Class parent = c.getSuperclass() ; 122 String pname = (parent == null ? "null" : parent.getName()) ; 123 pw.append("class " + c.getName() + " " + pname + "\n") ; 124 Constructor constructors[] = c.getConstructors() ; 125 Method methods[] = c.getMethods() ; 126 Field fields[] = c.getFields() ; 127 128 boolean pub = ijc.ClassIsPublic(c) ; 129 if (pub){ 130 // If the class is public and has no constructors, 131 // we provide a default no-arg constructors. 132 if (c.getDeclaredConstructors().length == 0){ 133 String noarg_sign = InlineJavaUtils.CreateSignature(new Class [] {}) ; 134 pw.append("constructor " + noarg_sign + "\n") ; 135 } 136 } 137 138 boolean pn = InlineJavaPerlNatives.class.isAssignableFrom(c) ; 139 for (int j = 0 ; j < constructors.length ; j++){ 140 Constructor x = constructors[j] ; 141 if ((pn)&&(Modifier.isNative(x.getModifiers()))){ 142 continue ; 143 } 144 Class params[] = x.getParameterTypes() ; 145 String sign = InlineJavaUtils.CreateSignature(params) ; 146 Class decl = x.getDeclaringClass() ; 147 pw.append("constructor " + sign + "\n") ; 148 } 149 150 for (int j = 0 ; j < methods.length ; j++){ 151 Method x = methods[j] ; 152 if ((pn)&&(Modifier.isNative(x.getModifiers()))){ 153 continue ; 154 } 155 String stat = (Modifier.isStatic(x.getModifiers()) ? " static " : " instance ") ; 156 String sign = InlineJavaUtils.CreateSignature(x.getParameterTypes()) ; 157 Class decl = x.getDeclaringClass() ; 158 pw.append("method" + stat + decl.getName() + " " + x.getName() + sign + "\n") ; 159 } 160 161 for (int j = 0 ; j < fields.length ; j++){ 162 Field x = fields[(InlineJavaUtils.ReverseMembers() ? (fields.length - 1 - j) : j)] ; 163 String stat = (Modifier.isStatic(x.getModifiers()) ? " static " : " instance ") ; 164 Class decl = x.getDeclaringClass() ; 165 Class type = x.getType() ; 166 pw.append("field" + stat + decl.getName() + " " + x.getName() + " " + type.getName() + "\n") ; 167 } 168 } 169 170 SetResponse(pw.toString()) ; 171 } 172 173 AddClassPath(StringTokenizer st)174 void AddClassPath(StringTokenizer st) throws InlineJavaException { 175 while (st.hasMoreTokens()){ 176 String path = Decode(st.nextToken()) ; 177 InlineJavaServer.GetInstance().GetUserClassLoader().AddClassPath(path) ; 178 } 179 SetResponse(null) ; 180 } 181 182 ServerType(StringTokenizer st)183 void ServerType(StringTokenizer st) throws InlineJavaException { 184 SetResponse(ijs.GetType()) ; 185 } 186 187 IsA(StringTokenizer st)188 void IsA(StringTokenizer st) throws InlineJavaException { 189 String class_name = st.nextToken() ; 190 Class c = ijc.ValidateClass(class_name) ; 191 192 String is_it_a = st.nextToken() ; 193 Class d = ijc.ValidateClass(is_it_a) ; 194 195 SetResponse(new Integer(ijc.DoesExtend(c, d))) ; 196 } 197 198 ObjectCount(StringTokenizer st)199 void ObjectCount(StringTokenizer st) throws InlineJavaException { 200 SetResponse(new Integer(ijs.ObjectCount())) ; 201 } 202 203 204 /* 205 Creates a Java Object with the specified arguments. 206 */ CreateJavaObject(StringTokenizer st)207 void CreateJavaObject(StringTokenizer st) throws InlineJavaException { 208 String class_name = st.nextToken() ; 209 Class c = ijc.ValidateClass(class_name) ; 210 211 if (! ijc.ClassIsArray(c)){ 212 ArrayList f = ValidateMethod(true, c, class_name, st) ; 213 Object p[] = (Object [])f.get(1) ; 214 Class clist[] = (Class [])f.get(2) ; 215 216 try { 217 Object o = CreateObject(c, p, clist) ; 218 SetResponse(o) ; 219 } 220 catch (InlineJavaInvocationTargetException ite){ 221 Throwable t = ite.GetThrowable() ; 222 if (t instanceof InlineJavaException){ 223 InlineJavaException ije = (InlineJavaException)t ; 224 throw ije ; 225 } 226 else{ 227 SetResponse(new InlineJavaThrown(t)) ; 228 } 229 } 230 } 231 else{ 232 // Here we send the type of array we want, but CreateArray 233 // exception the element type. 234 StringBuffer sb = new StringBuffer(class_name) ; 235 // Remove the ['s 236 while (sb.toString().startsWith("[")){ 237 sb.replace(0, 1, "") ; 238 } 239 // remove the L and the ; 240 if (sb.toString().startsWith("L")){ 241 sb.replace(0, 1, "") ; 242 sb.replace(sb.length() - 1, sb.length(), "") ; 243 } 244 245 Class ec = ijc.ValidateClass(sb.toString()) ; 246 247 InlineJavaUtils.debug(4, "array elements: " + ec.getName()) ; 248 Object o = ija.CreateArray(ec, st) ; 249 SetResponse(o) ; 250 } 251 } 252 253 254 /* 255 Calls a Java method 256 */ CallJavaMethod(StringTokenizer st)257 void CallJavaMethod(StringTokenizer st) throws InlineJavaException { 258 int id = Integer.parseInt(st.nextToken()) ; 259 260 String class_name = st.nextToken() ; 261 Object o = null ; 262 if (id > 0){ 263 o = ijs.GetObject(id) ; 264 265 // Use the class sent by Perl (it might be casted) 266 // class_name = o.getClass().getName() ; 267 } 268 269 Class c = ijc.ValidateClass(class_name) ; 270 String method = st.nextToken() ; 271 272 if ((ijc.ClassIsArray(c))&&(method.equals("getLength"))){ 273 int length = Array.getLength(o) ; 274 SetResponse(new Integer(length)) ; 275 } 276 else{ 277 ArrayList f = ValidateMethod(false, c, method, st) ; 278 Method m = (Method)f.get(0) ; 279 String name = m.getName() ; 280 Object p[] = (Object [])f.get(1) ; 281 282 try { 283 Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().invoke(m, o, p) ; 284 SetResponse(ret, AutoCast(ret, m.getReturnType())) ; 285 } 286 catch (IllegalAccessException e){ 287 throw new InlineJavaException("You are not allowed to invoke method " + name + " in class " + class_name + ": " + e.getMessage()) ; 288 } 289 catch (IllegalArgumentException e){ 290 throw new InlineJavaException("Arguments for method " + name + " in class " + class_name + " are incompatible: " + e.getMessage()) ; 291 } 292 catch (InvocationTargetException e){ 293 Throwable t = e.getTargetException() ; 294 String type = t.getClass().getName() ; 295 String msg = t.getMessage() ; 296 InlineJavaUtils.debug(1, "method " + name + " in class " + class_name + " threw exception " + type + ": " + msg) ; 297 if (t instanceof InlineJavaException){ 298 InlineJavaException ije = (InlineJavaException)t ; 299 throw ije ; 300 } 301 else{ 302 SetResponse(new InlineJavaThrown(t)) ; 303 } 304 } 305 } 306 } 307 308 309 /* 310 */ AutoCast(Object o, Class want)311 Class AutoCast(Object o, Class want){ 312 if (o == null){ 313 return null ; 314 } 315 else { 316 Class got = o.getClass() ; 317 if (got.equals(want)){ 318 return null ; 319 } 320 else { 321 boolean _public = (got.getModifiers() & Modifier.PUBLIC) != 0 ; 322 if ((_public)||(got.getPackage() == null)){ 323 return null ; 324 } 325 else { 326 InlineJavaUtils.debug(3, "AutoCast: " + got.getName() + " -> " + want.getName()) ; 327 return want ; 328 } 329 } 330 } 331 } 332 333 334 /* 335 Returns a new reference to the current object, using the provided subtype 336 */ Cast(StringTokenizer st)337 void Cast(StringTokenizer st) throws InlineJavaException { 338 int id = Integer.parseInt(st.nextToken()) ; 339 340 String class_name = st.nextToken() ; 341 Object o = ijs.GetObject(id) ; 342 Class c = ijc.ValidateClass(class_name) ; 343 344 SetResponse(o, c) ; 345 } 346 347 348 /* 349 */ Read(StringTokenizer st)350 void Read(StringTokenizer st) throws InlineJavaException { 351 int id = Integer.parseInt(st.nextToken()) ; 352 int len = Integer.parseInt(st.nextToken()) ; 353 354 Object o = ijs.GetObject(id) ; 355 Object ret = null ; 356 try { 357 ret = InlineJavaHandle.read(o, len) ; 358 } 359 catch (java.io.IOException e){ 360 ret = new InlineJavaThrown(e) ; 361 } 362 363 SetResponse(ret) ; 364 } 365 366 MakeBuffered(StringTokenizer st)367 void MakeBuffered(StringTokenizer st) throws InlineJavaException { 368 int id = Integer.parseInt(st.nextToken()) ; 369 370 Object o = ijs.GetObject(id) ; 371 Object ret = null ; 372 try { 373 ret = InlineJavaHandle.makeBuffered(o) ; 374 if (ret != o){ 375 int buf_id = ijs.PutObject(ret) ; 376 ret = new Integer(buf_id) ; 377 } 378 else { 379 ret = new Integer(id) ; 380 } 381 } 382 catch (java.io.IOException e){ 383 ret = new InlineJavaThrown(e) ; 384 } 385 386 SetResponse(ret) ; 387 } 388 389 ReadLine(StringTokenizer st)390 void ReadLine(StringTokenizer st) throws InlineJavaException { 391 int id = Integer.parseInt(st.nextToken()) ; 392 393 Object o = ijs.GetObject(id) ; 394 Object ret = null ; 395 try { 396 ret = InlineJavaHandle.readLine(o) ; 397 } 398 catch (java.io.IOException e){ 399 ret = new InlineJavaThrown(e) ; 400 } 401 402 SetResponse(ret) ; 403 } 404 405 Write(StringTokenizer st)406 void Write(StringTokenizer st) throws InlineJavaException { 407 int id = Integer.parseInt(st.nextToken()) ; 408 Object arg = ijc.CastArgument(Object.class, st.nextToken()) ; 409 410 Object o = ijs.GetObject(id) ; 411 Object ret = null ; 412 try { 413 int len = InlineJavaHandle.write(o, arg.toString()) ; 414 ret = new Integer(len) ; 415 } 416 catch (java.io.IOException e){ 417 ret = new InlineJavaThrown(e) ; 418 } 419 420 SetResponse(ret) ; 421 } 422 423 Close(StringTokenizer st)424 void Close(StringTokenizer st) throws InlineJavaException { 425 int id = Integer.parseInt(st.nextToken()) ; 426 427 Object o = ijs.GetObject(id) ; 428 Object ret = null ; 429 try { 430 InlineJavaHandle.close(o) ; 431 } 432 catch (java.io.IOException e){ 433 ret = new InlineJavaThrown(e) ; 434 } 435 436 SetResponse(ret) ; 437 } 438 439 440 /* 441 Sets a Java member variable 442 */ SetJavaMember(StringTokenizer st)443 void SetJavaMember(StringTokenizer st) throws InlineJavaException { 444 int id = Integer.parseInt(st.nextToken()) ; 445 446 String class_name = st.nextToken() ; 447 Object o = null ; 448 if (id > 0){ 449 o = ijs.GetObject(id) ; 450 451 // Use the class sent by Perl (it might be casted) 452 // class_name = o.getClass().getName() ; 453 } 454 455 Class c = ijc.ValidateClass(class_name) ; 456 String member = st.nextToken() ; 457 458 if (ijc.ClassIsArray(c)){ 459 int idx = Integer.parseInt(member) ; 460 Class type = ijc.ValidateClass(st.nextToken()) ; 461 String arg = st.nextToken() ; 462 463 String msg = "For array of type " + c.getName() + ", element " + member + ": " ; 464 try { 465 Object elem = ijc.CastArgument(type, arg) ; 466 InlineJavaServer.GetInstance().GetUserClassLoader().array_set(o, idx, elem) ; 467 SetResponse(null) ; 468 } 469 catch (InlineJavaCastException e){ 470 throw new InlineJavaCastException(msg + e.getMessage()) ; 471 } 472 catch (InlineJavaException e){ 473 throw new InlineJavaException(msg + e.getMessage()) ; 474 } 475 } 476 else{ 477 ArrayList fl = ValidateMember(c, member, st) ; 478 Field f = (Field)fl.get(0) ; 479 String name = f.getName() ; 480 Object p = (Object)fl.get(1) ; 481 482 try { 483 InlineJavaServer.GetInstance().GetUserClassLoader().set(f, o, p) ; 484 SetResponse(null) ; 485 } 486 catch (IllegalAccessException e){ 487 throw new InlineJavaException("You are not allowed to set member " + name + " in class " + class_name + ": " + e.getMessage()) ; 488 } 489 catch (IllegalArgumentException e){ 490 throw new InlineJavaException("Argument for member " + name + " in class " + class_name + " is incompatible: " + e.getMessage()) ; 491 } 492 } 493 } 494 495 496 /* 497 Gets a Java member variable 498 */ GetJavaMember(StringTokenizer st)499 void GetJavaMember(StringTokenizer st) throws InlineJavaException { 500 int id = Integer.parseInt(st.nextToken()) ; 501 502 String class_name = st.nextToken() ; 503 Object o = null ; 504 if (id > 0){ 505 o = ijs.GetObject(id) ; 506 507 // Use the class sent by Perl (it might be casted) 508 // class_name = o.getClass().getName() ; 509 } 510 511 Class c = ijc.ValidateClass(class_name) ; 512 String member = st.nextToken() ; 513 514 if (ijc.ClassIsArray(c)){ 515 int idx = Integer.parseInt(member) ; 516 Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().array_get(o, idx) ; 517 Class eclass = ijc.ValidateClass(ijc.CleanClassName(class_name.substring(1))) ; 518 SetResponse(ret, AutoCast(ret, eclass)) ; 519 } 520 else{ 521 ArrayList fl = ValidateMember(c, member, st) ; 522 523 Field f = (Field)fl.get(0) ; 524 String name = f.getName() ; 525 try { 526 Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().get(f, o) ; 527 SetResponse(ret, AutoCast(ret, f.getType())) ; 528 } 529 catch (IllegalAccessException e){ 530 throw new InlineJavaException("You are not allowed to set member " + name + " in class " + class_name + ": " + e.getMessage()) ; 531 } 532 catch (IllegalArgumentException e){ 533 throw new InlineJavaException("Argument for member " + name + " in class " + class_name + " is incompatible: " + e.getMessage()) ; 534 } 535 } 536 } 537 538 539 /* 540 Deletes a Java object 541 */ DeleteJavaObject(StringTokenizer st)542 void DeleteJavaObject(StringTokenizer st) throws InlineJavaException { 543 int id = Integer.parseInt(st.nextToken()) ; 544 545 Object o = ijs.DeleteObject(id) ; 546 547 SetResponse(null) ; 548 } 549 550 551 /* 552 Creates a Java Object with the specified arguments. 553 */ CreateObject(Class p, Object args[], Class proto[])554 Object CreateObject(Class p, Object args[], Class proto[]) throws InlineJavaException { 555 p = ijc.FindWrapper(p) ; 556 557 String name = p.getName() ; 558 Object ret = null ; 559 try { 560 ret = InlineJavaServer.GetInstance().GetUserClassLoader().create(p, args, proto) ; 561 } 562 catch (NoSuchMethodException e){ 563 throw new InlineJavaException("Constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " not found: " + e.getMessage()) ; 564 } 565 catch (InstantiationException e){ 566 throw new InlineJavaException("You are not allowed to instantiate object of class " + name + ": " + e.getMessage()) ; 567 } 568 catch (IllegalAccessException e){ 569 throw new InlineJavaException("You are not allowed to instantiate object of class " + name + " using the constructor with signature " + InlineJavaUtils.CreateSignature(proto) + ": " + e.getMessage()) ; 570 } 571 catch (IllegalArgumentException e){ 572 throw new InlineJavaException("Arguments to constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " are incompatible: " + e.getMessage()) ; 573 } 574 catch (InvocationTargetException e){ 575 Throwable t = e.getTargetException() ; 576 String type = t.getClass().getName() ; 577 String msg = t.getMessage() ; 578 throw new InlineJavaInvocationTargetException( 579 "Constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " threw exception " + type + ": " + msg, 580 t) ; 581 } 582 583 return ret ; 584 } 585 586 587 /* 588 Makes sure a method exists 589 */ ValidateMethod(boolean constructor, Class c, String name, StringTokenizer st)590 ArrayList ValidateMethod(boolean constructor, Class c, String name, StringTokenizer st) throws InlineJavaException { 591 ArrayList ret = new ArrayList() ; 592 593 // Extract signature 594 String signature = st.nextToken() ; 595 596 // Extract the arguments 597 ArrayList args = new ArrayList() ; 598 while (st.hasMoreTokens()){ 599 args.add(args.size(), st.nextToken()) ; 600 } 601 602 String key = c.getName() + "." + name + signature ; 603 ArrayList ml = new ArrayList() ; 604 Class params[] = null ; 605 606 Member cached = (Member)member_cache.get(key) ; 607 if (cached != null){ 608 InlineJavaUtils.debug(3, "method was cached") ; 609 ml.add(ml.size(), cached) ; 610 } 611 else{ 612 Member ma[] = (constructor ? (Member [])c.getConstructors() : (Member [])c.getMethods()) ; 613 for (int i = 0 ; i < ma.length ; i++){ 614 Member m = ma[i] ; 615 616 if (m.getName().equals(name)){ 617 InlineJavaUtils.debug(3, "found a " + name + (constructor ? " constructor" : " method")) ; 618 619 if (constructor){ 620 params = ((Constructor)m).getParameterTypes() ; 621 } 622 else{ 623 params = ((Method)m).getParameterTypes() ; 624 } 625 626 // Now we check if the signatures match 627 String sign = InlineJavaUtils.CreateSignature(params, ",") ; 628 InlineJavaUtils.debug(3, sign + " = " + signature + "?") ; 629 630 if (signature.equals(sign)){ 631 InlineJavaUtils.debug(3, "has matching signature " + sign) ; 632 ml.add(ml.size(), m) ; 633 member_cache.put(key, m) ; 634 break ; 635 } 636 } 637 } 638 } 639 640 // Now we got a list of matching methods (actually 0 or 1). 641 // We have to figure out which one we will call. 642 if (ml.size() == 0){ 643 // Nothing matched. Maybe we got a default constructor 644 if ((constructor)&&(signature.equals("()"))){ 645 ret.add(0, null) ; 646 ret.add(1, new Object [] {}) ; 647 ret.add(2, new Class [] {}) ; 648 } 649 else{ 650 throw new InlineJavaException( 651 (constructor ? "Constructor " : "Method ") + 652 name + " for class " + c.getName() + " with signature " + 653 signature + " not found") ; 654 } 655 } 656 else if (ml.size() == 1){ 657 // Now we need to force the arguments received to match 658 // the methods signature. 659 Member m = (Member)ml.get(0) ; 660 if (constructor){ 661 params = ((Constructor)m).getParameterTypes() ; 662 } 663 else{ 664 params = ((Method)m).getParameterTypes() ; 665 } 666 667 String msg = "In method " + name + " of class " + c.getName() + ": " ; 668 try { 669 ret.add(0, m) ; 670 ret.add(1, ijc.CastArguments(params, args)) ; 671 ret.add(2, params) ; 672 } 673 catch (InlineJavaCastException e){ 674 throw new InlineJavaCastException(msg + e.getMessage()) ; 675 } 676 catch (InlineJavaException e){ 677 throw new InlineJavaException(msg + e.getMessage()) ; 678 } 679 } 680 681 return ret ; 682 } 683 684 685 /* 686 Makes sure a member exists 687 */ ValidateMember(Class c, String name, StringTokenizer st)688 ArrayList ValidateMember(Class c, String name, StringTokenizer st) throws InlineJavaException { 689 ArrayList ret = new ArrayList() ; 690 691 // Extract member type 692 String type = st.nextToken() ; 693 694 // Extract the argument 695 String arg = st.nextToken() ; 696 697 String key = type + " " + c.getName() + "." + name ; 698 ArrayList fl = new ArrayList() ; 699 Class param = null ; 700 701 Member cached = (Member)member_cache.get(key) ; 702 if (cached != null){ 703 InlineJavaUtils.debug(3, "member was cached") ; 704 fl.add(fl.size(), cached) ; 705 } 706 else { 707 Field fa[] = c.getFields() ; 708 for (int i = 0 ; i < fa.length ; i++){ 709 Field f = fa[(InlineJavaUtils.ReverseMembers() ? (fa.length - 1 - i) : i)] ; 710 711 if (f.getName().equals(name)){ 712 InlineJavaUtils.debug(3, "found a " + name + " member") ; 713 714 param = f.getType() ; 715 String t = param.getName() ; 716 if (type.equals(t)){ 717 InlineJavaUtils.debug(3, "has matching type " + t) ; 718 fl.add(fl.size(), f) ; 719 } 720 } 721 } 722 } 723 724 // Now we got a list of matching members. 725 // We have to figure out which one we will call. 726 if (fl.size() == 0){ 727 throw new InlineJavaException( 728 "Member " + name + " of type " + type + " for class " + c.getName() + 729 " not found") ; 730 } 731 else { 732 // Now we need to force the arguments received to match 733 // the methods signature. 734 735 // If we have more that one, we use the last one, which is the most 736 // specialized 737 Field f = (Field)fl.get(fl.size() - 1) ; 738 member_cache.put(key, f) ; 739 param = f.getType() ; 740 741 String msg = "For member " + name + " of class " + c.getName() + ": " ; 742 try { 743 ret.add(0, f) ; 744 ret.add(1, ijc.CastArgument(param, arg)) ; 745 ret.add(2, param) ; 746 } 747 catch (InlineJavaCastException e){ 748 throw new InlineJavaCastException(msg + e.getMessage()) ; 749 } 750 catch (InlineJavaException e){ 751 throw new InlineJavaException(msg + e.getMessage()) ; 752 } 753 } 754 755 return ret ; 756 } 757 758 759 /* 760 This sets the response that will be returned to the Perl 761 script 762 */ SetResponse(Object o)763 void SetResponse(Object o) throws InlineJavaException { 764 SetResponse(o, null) ; 765 } 766 767 SetResponse(Object o, Class p)768 void SetResponse(Object o, Class p) throws InlineJavaException { 769 response = "ok " + SerializeObject(o, p) ; 770 } 771 772 SerializeObject(Object o, Class p)773 String SerializeObject(Object o, Class p) throws InlineJavaException { 774 Class c = (o == null ? null : o.getClass()) ; 775 776 if ((c != null)&&(p != null)){ 777 if (ijc.DoesExtend(c, p) < 0){ 778 throw new InlineJavaException("Can't cast a " + c.getName() + " to a " + p.getName()) ; 779 } 780 else{ 781 c = p ; 782 } 783 } 784 785 if (o == null){ 786 return "undef:" ; 787 } 788 else if ((ijc.ClassIsNumeric(c))||(ijc.ClassIsChar(c))||(ijc.ClassIsString(c))){ 789 if ((ijs.GetNativeDoubles())&&(ijc.ClassIsDouble(c))){ 790 Double d = (Double)o ; 791 long l = Double.doubleToLongBits(d.doubleValue()) ; 792 char ca[] = new char[8] ; 793 for (int i = 0 ; i < 8 ; i++){ 794 ca[i] = (char)((l >> (8 * i)) & 0xFF) ; 795 } 796 return "double:" + Encode(new String(ca)) ; 797 } 798 else { 799 return "scalar:" + Encode(o.toString()) ; 800 } 801 } 802 else if (ijc.ClassIsBool(c)){ 803 String b = o.toString() ; 804 return "scalar:" + Encode((b.equals("true") ? "1" : "0")) ; 805 } 806 else { 807 if (! (o instanceof org.perl.inline.java.InlineJavaPerlObject)){ 808 // Here we need to register the object in order to send 809 // it back to the Perl script. 810 boolean thrown = false ; 811 String type = "object" ; 812 if (o instanceof InlineJavaThrown){ 813 thrown = true ; 814 o = ((InlineJavaThrown)o).GetThrowable() ; 815 c = o.getClass() ; 816 } 817 else if (ijc.ClassIsArray(c)){ 818 type = "array" ; 819 } 820 else if (ijc.ClassIsHandle(c)){ 821 type = "handle" ; 822 } 823 int id = ijs.PutObject(o) ; 824 825 return "java_" + type + ":" + (thrown ? "1" : "0") + ":" + String.valueOf(id) + 826 ":" + c.getName() ; 827 } 828 else { 829 return "perl_object:" + ((InlineJavaPerlObject)o).GetId() + 830 ":" + ((InlineJavaPerlObject)o).GetPkg() ; 831 } 832 } 833 } 834 835 DecodeToByteArray(String s)836 byte[] DecodeToByteArray(String s){ 837 return InlineJavaUtils.DecodeBase64(s.toCharArray()) ; 838 } 839 840 Decode(String s)841 String Decode(String s) throws InlineJavaException { 842 try { 843 if (encoding != null){ 844 return new String(DecodeToByteArray(s), encoding) ; 845 } 846 else { 847 return new String(DecodeToByteArray(s)) ; 848 } 849 } 850 catch (UnsupportedEncodingException e){ 851 throw new InlineJavaException("Unsupported encoding: " + e.getMessage()) ; 852 } 853 } 854 855 EncodeFromByteArray(byte bytes[])856 String EncodeFromByteArray(byte bytes[]){ 857 return new String(InlineJavaUtils.EncodeBase64(bytes)) ; 858 } 859 860 Encode(String s)861 String Encode(String s) throws InlineJavaException { 862 try { 863 if (encoding != null){ 864 return EncodeFromByteArray(s.getBytes(encoding)) ; 865 } 866 else { 867 return EncodeFromByteArray(s.getBytes()) ; 868 } 869 } 870 catch (UnsupportedEncodingException e){ 871 throw new InlineJavaException("Unsupported encoding: " + e.getMessage()) ; 872 } 873 } 874 875 GetResponse()876 String GetResponse(){ 877 return response ; 878 } 879 } 880