KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bsf > engines > activescript > ActiveScriptEngine


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2002 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if
20  * any, must include the following acknowlegement:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowlegement may appear in the software itself,
24  * if and wherever such third-party acknowlegements normally appear.
25  *
26  * 4. The names "Apache BSF", "Apache", and "Apache Software Foundation"
27  * must not be used to endorse or promote products derived from
28  * this software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache"
32  * nor may "Apache" appear in their names without prior written
33  * permission of the Apache Group.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many individuals
50  * on behalf of the Apache Software Foundation and was originally created by
51  * Sanjiva Weerawarana and others at International Business Machines
52  * Corporation. For more information on the Apache Software Foundation,
53  * please see <http://www.apache.org/>.
54  */

55
56 package org.apache.bsf.engines.activescript;
57
58 import java.util.*;
59 import java.io.*;
60 import java.lang.reflect.*;
61
62 import org.apache.bsf.*;
63 import org.apache.bsf.util.*;
64
65
66
67 /**
68  * This is the interface to active scripting engines from the Bean
69  * Scripting Framework. This code uses John Ponzo's IBM Active Scripting
70  * Toolkit to tie in active scripting engines to BSF.
71  * This class implements Runnable to create a thread. This thread is to
72  * exclusively access the scripting engine. All methods from this class to
73  * the engines is proxied over to the engine thread for execution. Why?
74  * Because, MS engines are implemented to only be accessed from ONE thread.
75  *
76  * @author Sanjiva Weerawarana
77  */

78 public class ActiveScriptEngine extends BSFEngineImpl implements JavaBeanAddEventListener
79 {
80
81  class ArrayInfo
82  {
83   protected Object JavaDoc arrayObject=null;
84   protected boolean investigated= false;
85   public int maxDepth=0;
86   // int curDepth=0;
87
public char type=0;
88   public int maxDimArray[]= null;
89   public int dimOffset[]= null;
90   public String JavaDoc toString()
91   {
92    if(0== maxDepth) return "Not an array";
93    String JavaDoc ret= "type="+type+",maxDepth="+ maxDepth+ "maxDimArray=\n";
94    for(int i=0; i < maxDepth; ++i) ret+= "["+ i+ "]"+"=" + maxDimArray[i] + ";\n";
95    return ret;
96   }
97
98   protected void investigate(Object JavaDoc o, int curDepth)
99   {
100    if(investigated) return;
101    if( null == o) return; //Safety
102

103    ++curDepth;
104    int thisDepth= curDepth;
105    if(thisDepth == maxDepth)
106    { //The reason the last dimension needs to be type specific to avoid getting runtime class cast exceptions on primatives!
107
switch( type)
108      {
109       case 'Z' :
110        {
111         boolean[] larray= (boolean []) o;
112          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
113        }
114       break;
115       case 'B' :
116        {
117         byte[] larray= (byte []) o;
118          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
119        }
120       break;
121       case 'C' :
122        {
123         char[] larray= (char []) o;
124          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
125        }
126       break;
127       case 'S' :
128        {
129         short[] larray= (short []) o;
130          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
131        }
132       break;
133       case 'I' :
134        {
135         int[] larray= (int []) o;
136          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
137        }
138       break;
139       case 'J' :
140        {
141         long[] larray= (long []) o;
142          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
143        }
144       break;
145       case 'F' :
146        {
147         float[] larray= (float []) o;
148          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
149        }
150       break;
151       case 'D' :
152        {
153         double[] larray= (double[]) o;
154          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
155        }
156       break;
157       default:
158        { //Should be an object
159
Object JavaDoc[] larray= (Object JavaDoc []) o;
160          if(larray.length > maxDimArray[thisDepth-1]) maxDimArray[thisDepth-1]= larray.length;
161        }
162       break;
163      }
164    }
165    else
166    { //Still a multi-dim array
167
Object JavaDoc[] larray= (Object JavaDoc []) o;
168       if(larray.length > maxDimArray[curDepth-1]) maxDimArray[curDepth-1]= larray.length;
169
170      for(int i=0; i < larray.length ; ++i)
171      {
172       if(larray[i].getClass().isArray() )
173       {
174         investigate(larray[i], thisDepth);
175       }
176      }
177    }
178    if(1== curDepth) investigated= true;
179   }//Endof investigate
180

181
182   private int setVariantData( Object JavaDoc o, byte v[], int os, int curDepth, int[] index) throws BSFException
183   {
184       ++curDepth;
185       if(curDepth != maxDepth)
186       {
187         Object JavaDoc[] larray= (Object JavaDoc []) o;
188         int i;
189         for( i=0; i< larray.length ; ++i)
190         {
191           if(larray[i] == null)
192           {
193             
194           }
195           else
196           {
197        index[curDepth-1]=i;
198        for(int k= curDepth; k< maxDepth; index[k++]=0);
199            setVariantData( larray[i], v, os , curDepth, index );
200           }
201         }
202       }
203       else
204       {
205         switch( type)
206         {
207          case 'Z' :
208           {
209
210            boolean[] larray= (boolean[]) o;
211            int i;
212        int pos=os;
213        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
214            for( i=0; i < larray.length; ++i)
215            {
216          int fpos= pos+ i*dimOffset[curDepth-1]*16;
217              v[fpos] = 11; //VT_BOOL
218
v[fpos+1] = 0;
219        
220              byte x= (byte)( (larray[i]) ? 0xff: 0);
221              v[fpos+2]= x;
222              v[fpos+3]= x;
223              v[fpos+4]= x;
224              v[fpos+5]= x;
225            }
226            for(; i< maxDimArray[curDepth-1]; ++i )
227            {
228          int fpos= pos+ i*dimOffset[curDepth-1]*16;
229              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
230
}
231        
232           }
233          break;
234          case 'B' :
235           {
236            byte[] larray= (byte[]) o;
237            int i;
238        int pos=os;
239        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
240            for( i=0; i < larray.length; ++i)
241            {
242          int fpos= pos+ i*dimOffset[curDepth-1]*16;
243              v[fpos] = 17; //VT_UI1
244
v[fpos+1] = 0;
245        
246              int x= larray[i];
247              v[fpos+8]= (byte)x;
248              v[fpos+9]= v[fpos+10]= v[fpos+11]= 0;
249            }
250            for(; i< maxDimArray[curDepth-1]; ++i )
251            {
252          int fpos= pos+ i*dimOffset[curDepth-1]*16;
253              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
254

255            }
256           }
257          break;
258          case 'C' :
259           {
260            char[] larray= (char[]) o;
261            int i;
262        int pos=os;
263        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
264            for( i=0; i < larray.length; ++i)
265        {
266           int fpos= pos+ i*dimOffset[curDepth-1]*16;
267           v[fpos] = 17; //VT_UI1
268
v[fpos+1] = 0;
269        
270           byte x= (byte) ((Character JavaDoc)o).charValue();
271           v[fpos+8]= x;
272               v[fpos+9]= v[fpos+10]= v[fpos+11]= 0;
273            }
274            for(; i< maxDimArray[curDepth-1]; ++i )
275            {
276          int fpos= pos+ i*dimOffset[curDepth-1]*16;
277              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
278

279            }
280           }
281          break;
282          case 'S' :
283           {
284            short[] larray= (short[]) o;
285            int i;
286        int pos=os;
287        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
288            for( i=0; i < larray.length; ++i)
289        {
290           int fpos= pos+ i*dimOffset[curDepth-1]*16;
291           v[fpos] = 2; //VT_I2
292
v[fpos+1] = 0;
293        
294           int x= (int)larray[i];
295           v[fpos+8]= (byte)x;
296           v[fpos+9]= (byte)((x>>>8) & 0xff);
297           v[fpos+10]= (byte)((x>>>16) & 0xff);
298           v[fpos+11]= (byte)((x>>>24) & 0xff);
299            }
300            for(; i< maxDimArray[curDepth-1]; ++i )
301            {
302          int fpos= pos+ i*dimOffset[curDepth-1]*16;
303              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
304

305            }
306           }
307          break;
308          case 'I' :
309           {
310            int[] larray= (int[]) o;
311            int i;
312        int pos=os;
313        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
314            for( i=0; i < larray.length; ++i)
315            {
316          int fpos= pos+ i*dimOffset[curDepth-1]*16;
317              v[fpos] = 3; //VT_I4
318
v[fpos+1] = 0;
319        
320               int x= larray[i];
321              v[fpos+8]= (byte)x;
322              v[fpos+9]= (byte)((x>>>8) & 0xff);
323              v[fpos+10]= (byte)((x>>>16) & 0xff);
324              v[fpos+11]= (byte)((x>>>24) & 0xff);
325            }
326            for(; i< maxDimArray[curDepth-1]; ++i )
327            {
328          int fpos= pos+ i*dimOffset[curDepth-1]*16;
329              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
330

331            }
332           }
333          break;
334          case 'J' :
335           {
336            long[] larray= (long[]) o;
337            int i;
338        int pos=os;
339        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
340            for( i=0; i < larray.length; ++i)
341        {
342          int fpos= pos+ i*dimOffset[curDepth-1]*16;
343          v[fpos] = 5; //VT_R8
344
v[fpos+1] = 0;
345
346          long x= Double.doubleToLongBits((double)(larray[i]));
347              v[fpos+8]= (byte)x;
348              v[fpos+9]= (byte)((x>>>8) & 0xff);
349              v[fpos+10]= (byte)((x>>>16) & 0xff);
350              v[fpos+11]= (byte)((x>>>24) & 0xff);
351              v[fpos+12]= (byte)((x>>>32) & 0xff);
352              v[fpos+13]= (byte)((x>>>40) & 0xff);
353              v[fpos+14]= (byte)((x>>>48) & 0xff);
354              v[fpos+15]= (byte)((x>>>56) & 0xff);
355        
356            }
357            for(; i< maxDimArray[curDepth-1]; ++i )
358            {
359          int fpos= pos+ i*dimOffset[curDepth-1]*16;
360              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
361
}
362           }
363          break;
364          case 'F' :
365           {
366            float[] larray= (float[]) o;
367            int i;
368        int pos=os;
369        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
370            for( i=0; i < larray.length; ++i)
371        {
372           int fpos= pos+ i*dimOffset[curDepth-1]*16;
373           v[fpos] = 4; //VT_R4
374
v[fpos+1] = 0;
375        
376           int x= Float.floatToIntBits(larray[i]);
377           v[fpos+8]= (byte)x;
378           v[fpos+9]= (byte)((x>>>8) & 0xff);
379           v[fpos+10]= (byte)((x>>>16) & 0xff);
380           v[fpos+11]= (byte)((x>>>24) & 0xff);
381            }
382            for(; i< maxDimArray[curDepth-1]; ++i )
383            {
384          int fpos= pos+ i*dimOffset[curDepth-1]*16;
385              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
386

387            }
388           }
389          break;
390          case 'D' :
391           {
392            double[] larray= (double[]) o;
393            int i;
394        int pos=os;
395        for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
396            for( i=0; i < larray.length; ++i)
397        {
398           int fpos= pos+ i*dimOffset[curDepth-1]*16;
399           v[fpos] = 5; //VT_R8
400
v[fpos+1] = 0;
401        
402           long x= Double.doubleToLongBits(larray[i]);
403           v[fpos+8]= (byte)x;
404           v[fpos+9]= (byte)((x>>>8) & 0xff);
405           v[fpos+10]= (byte)((x>>>16) & 0xff);
406           v[fpos+11]= (byte)((x>>>24) & 0xff);
407             v[fpos+12]= (byte)((x>>>32) & 0xff);
408                 v[fpos+13]= (byte)((x>>>40) & 0xff);
409                 v[fpos+14]= (byte)((x>>>48) & 0xff);
410           v[fpos+15]= (byte)((x>>>56) & 0xff);
411             }
412             for(; i< maxDimArray[curDepth-1]; ++i )
413             {
414          int fpos= pos+ i*dimOffset[curDepth-1]*16;
415              v[fpos] = v[fpos+1]= 0; //VT_EMPTY
416

417             }
418        }
419          break;
420          default:
421           { //Should be an object array.
422

423              Object JavaDoc[] larray= (Object JavaDoc[]) o;
424              int i;
425              int pos=os;
426              for(int k=0; k < curDepth-1; ++k) pos+= index[k]*dimOffset[k]*16;
427              for( i=0; i < larray.length; ++i)
428              {
429                int fpos= pos+ i*dimOffset[curDepth-1]*16;
430           
431             if(larray[i] == null)
432         {
433                   v[fpos] = 1; //VT_NULL
434
v[fpos+1] = 0;
435         }
436                 else if(larray[i] instanceof java.lang.Boolean JavaDoc)
437                 {
438                  v[fpos] = 11; //VT_BOOL
439
v[fpos+1] = 0;
440                  byte x= (byte)( (((Boolean JavaDoc) larray[i]).booleanValue()) ? 0xff: 0);
441                  v[fpos+8]= x;
442                  v[fpos+9]= x;
443                  v[fpos+10]= x;
444                  v[fpos+11]= x;
445                 }
446                 else if(larray[i] instanceof java.lang.Integer JavaDoc) //VT_R8
447
{
448                  v[fpos] = 3; //VT_I4
449
v[fpos+1] = 0;
450                  int x= ((Integer JavaDoc)larray[i]).intValue();
451                  v[fpos+8]= (byte)x;
452                  v[fpos+9]= (byte)((x>>>8) & 0xff);
453                  v[fpos+10]= (byte)((x>>>16) & 0xff);
454                  v[fpos+11]= (byte)((x>>>24) & 0xff);
455                 }
456                 else if(larray[i] instanceof String JavaDoc)
457         {
458                    byte[] cppref= nativeStingToBString((String JavaDoc) larray[i]);
459
460                       v[fpos] = 8; //VT_BSTR
461
v[fpos+1] = 0;
462          
463                       v[fpos+8]= cppref[0];
464                       v[fpos+9]= cppref[1];
465                       v[fpos+10]= cppref[2];
466                       v[fpos+11]= cppref[3];
467         }
468                 else if(larray[i] instanceof java.lang.Long JavaDoc) //VT_R8
469
{ //COM has no long type so promote it to double which can contain it.
470
v[fpos] = 5; //VT_R8
471
v[fpos+1] = 0;
472                  long x= Double.doubleToLongBits((double)(((Long JavaDoc)larray[i]).longValue()));
473                  v[fpos+8]= (byte)x;
474                  v[fpos+9]= (byte)((x>>>8) & 0xff);
475                  v[fpos+10]= (byte)((x>>>16) & 0xff);
476                  v[fpos+11]= (byte)((x>>>24) & 0xff);
477                  v[fpos+12]= (byte)((x>>>32) & 0xff);
478                  v[fpos+13]= (byte)((x>>>40) & 0xff);
479                  v[fpos+14]= (byte)((x>>>48) & 0xff);
480                  v[fpos+15]= (byte)((x>>>56) & 0xff);
481                 }
482                 else if(larray[i] instanceof java.lang.Short JavaDoc)
483                 {
484                  v[fpos] = 2; //VT_I2
485
v[fpos+1] = 0;
486                  // int x= Float.floatToIntBits((larray[i]));
487
int x= ((Short JavaDoc)larray[i]).intValue();
488                  v[fpos+8]= (byte)x;
489                  v[fpos+9]= (byte)((x>>>8) & 0xff);
490                  v[fpos+10]= (byte)((x>>>16) & 0xff);
491                  v[fpos+11]= (byte)((x>>>24) & 0xff);
492                 }
493                 else if(larray[i] instanceof java.lang.Float JavaDoc)
494                 {
495                  v[fpos] = 4; //VT_R4
496
v[fpos+1] = 0;
497                  int x= Float.floatToIntBits(((Float JavaDoc)larray[i]).floatValue());
498                  v[fpos+8]= (byte)x;
499                  v[fpos+9]= (byte)((x>>>8) & 0xff);
500                  v[fpos+10]= (byte)((x>>>16) & 0xff);
501                  v[fpos+11]= (byte)((x>>>24) & 0xff);
502                 }
503                 else if(larray[i] instanceof java.lang.Double JavaDoc) //VT_R8
504
{
505                  v[fpos] = 5; //VT_R8
506
v[fpos+1] = 0;
507                  long x= Double.doubleToLongBits(((Double JavaDoc)larray[i]).doubleValue());
508                  v[fpos+8]= (byte)x;
509                  v[fpos+9]= (byte)((x>>>8) & 0xff);
510                  v[fpos+10]= (byte)((x>>>16) & 0xff);
511                  v[fpos+11]= (byte)((x>>>24) & 0xff);
512                  v[fpos+12]= (byte)((x>>>32) & 0xff);
513                  v[fpos+13]= (byte)((x>>>40) & 0xff);
514                  v[fpos+14]= (byte)((x>>>48) & 0xff);
515                  v[fpos+15]= (byte)((x>>>56) & 0xff);
516                 }
517                 else if(larray[i] instanceof java.lang.Byte JavaDoc)
518                 {
519                  v[fpos] = 17; //VT_UI1
520
v[fpos+1] = 0;
521                  byte x= ((Byte JavaDoc)larray[i] ).byteValue();
522                  v[fpos+8]= x;
523                 }
524                 else if( larray[i] instanceof java.lang.Character JavaDoc)
525                 {
526                  v[fpos] = 17; //VT_UI1
527
v[fpos+1] = 0;
528                  byte x= (byte) ((Character JavaDoc)larray[i] ).charValue();
529                  v[fpos+8]= x;
530                 }
531                 else if( larray[i] instanceof java.lang.Void JavaDoc)
532                 {
533                  v[fpos] = 1; //VT_NULL
534
v[fpos+1] = 0;
535                 }
536         else
537         { //Really some non-primative rep. object
538

539                   byte[] cppref= null; // nativeObjectToVariant(css, larray[i]);
540

541                   v[fpos] = 9; //VT_DISPATCH
542
v[fpos+1] = 0;
543
544                   if(o instanceof org.apache.bsf.engines.activescript.COMIDispatchBean )
545                   {
546                     cppref = ((org.apache.bsf.engines.activescript.COMIDispatchBean )larray[i]).getIDispatchInterface();
547                   }
548                   else
549                   {
550                     cppref= nativeObjectToVariant(css, larray[i]);
551                   }
552                   System.arraycopy(cppref,0,v,fpos+8, cppref.length);
553         }
554              }
555              for(; i< maxDimArray[curDepth-1]; ++i )
556              {
557           int fpos= pos+ i*dimOffset[curDepth-1]*16;
558               v[fpos] = v[fpos+1]= 0; //VT_EMPTY
559
}
560           }//endof default
561
break;
562         }
563
564         
565       }
566
567     return os;
568   }
569
570   byte [] toVariant()throws BSFException
571   {
572     investigate(arrayObject, 0);
573     int totalDimSize= maxDimArray[0];
574     for(int i=1; i < maxDepth; ++i) totalDimSize *= maxDimArray[i];
575     int mallocSize=16 + // Size of variant.
576
16 + // The size of a safeArray that follows.
577
8*maxDepth+ //The size of SAFEARRAYBOUND by the no of dim.
578
totalDimSize* 16;
579
580     byte[] v= new byte[mallocSize ]; //Size of each data item as a Variant.
581
v[0]= 12; //VT_ARRAY | VT_VARIANT
582
v[1]= 0x20; //VT_ARRAY
583

584        //SAFEARRAY IS PACKED AFTER THE VARIANT
585
v[16]= (byte)maxDepth; //cDims;
586
v[17]= (byte)((maxDepth>>>8) & 0xff);
587
588        v[18]= (byte) 0X92; //fFeatures = FADF_VARIANT
589
v[19]= 0X8;
590        //cbElements= 16 the size of a variant
591
v[20]= 16;
592        v[21]=v[22]=v[23]= 0;
593        //cLocks ??
594
v[24]=v[25]=v[26]=v[27]= 0;
595        int i=0, j=32;
596
597        //rgsabound[] one for each dimension. Has max no of elements for dim followed by staring base of index.
598
for(i=maxDepth-1; i >= 0 ; --i) //Kinda stored backward from what I expected.
599
{
600          v[j++]= (byte)( maxDimArray[i]);
601          v[j++]= (byte)((maxDimArray[i]>>>8) & 0xff);
602          v[j++]= (byte)((maxDimArray[i]>>>16) & 0xff);
603          v[j++]= (byte)((maxDimArray[i]>>>24) & 0xff);
604          
605          v[j++]= 0; //Only support starting address of zero
606
v[j++]= 0;
607          v[j++]= 0;
608          v[j++]= 0;
609        }
610        //pvData addjusted on C++ side.
611
v[28]=v[29]=v[30]=v[31]= 0;
612          v[28]= (byte)(j);
613          v[29]= (byte)((j>>>8) & 0xff);
614          v[30]= (byte)((j>>>16) & 0xff);
615          v[31]= (byte)((j>>>24) & 0xff);
616
617        //THE DATA FOR THE SAFEARRAY IS PACKED AFTER IT
618
//Now for the data which will be a variant for each element. Note strings and true objects will need to be called back.
619
setVariantData( arrayObject, v, j, 0, new int[ maxDepth]);
620
621
622     return v;
623   }
624
625    
626   ArrayInfo( Object JavaDoc o)
627   {
628     if( o.getClass().isArray())
629     {
630      String JavaDoc arrayClass= o.getClass().toString();
631      maxDepth= arrayClass.indexOf('[');
632      if(-1 != maxDepth)
633      {
634        arrayObject= o;
635        arrayClass= arrayClass.substring(maxDepth);
636        for(maxDepth=0; arrayClass.charAt(maxDepth) == '['; ++maxDepth);
637        type= arrayClass.charAt(maxDepth);
638        maxDimArray= new int[maxDepth];
639        dimOffset= new int[maxDepth];
640        investigate(o,0);
641        dimOffset[0]=1;
642        for(int i=1; i < maxDepth; ++i)
643        {
644         dimOffset[i]= dimOffset[i-1] * maxDimArray[i-1];
645        }
646      }
647     
648     }
649   }
650  }
651   static BSFException dllLoadException= null; //Can hold an exception on from the loading of the c++ dll.
652
static final String JavaDoc libName= "bsfactivescriptengine"; //C++ dll name.
653

654   static final String JavaDoc LANG_VBSCRIPT = "vbscript";
655   static final String JavaDoc LANG_PERLSCRIPT = "perlscript";
656   static final String JavaDoc LANG_JSCRIPT = "jscript";
657   
658   static {
659     try
660     {
661       System.loadLibrary (libName);
662     }
663     catch(java.lang.SecurityException JavaDoc e)
664     {
665       dllLoadException= new BSFException(BSFException.REASON_OTHER_ERROR, "SecurityException loading library:" + libName + " " + e.getMessage(),e);
666     }
667     catch(java.lang.UnsatisfiedLinkError JavaDoc e)
668     {
669       dllLoadException= new BSFException(BSFException.REASON_OTHER_ERROR, "UnsatisfiedLinkError loading library:" + libName + " " + e.getMessage(),e);
670     }
671     
672   }
673   byte [] css= null;// c++ active script engine pointer, saved as an object and passed into the
674
BSFManager bsfmgr=null; //Used by other methods during JNI callbacks.
675
private Hashtable evalRet= null; //Used by languages which don't support expressions.
676
protected String JavaDoc lang= null; //The script language this engine is running.
677

678    /**
679     * add an event listener
680     */

681    public void addEventListener( Object JavaDoc bean, String JavaDoc event, String JavaDoc filter, String JavaDoc script) throws BSFException
682    {
683      EngineUtils.addEventListener(bean, event, filter, this, bsfmgr, "ActiveScriptEngine", 0, 0, script);
684    }
685    /**
686    * Binds a method to an integer so it can be later referenced to invoke the method via callMethod.
687    *
688    */

689    public final int bindMember(Object JavaDoc target, String JavaDoc name, short bindType) throws Exception JavaDoc
690    {
691      return JavaBean.bindMember( target.getClass(), name, bindType);
692    }
693   /**
694    * Return an object from an extension.
695    * @param method The name of the method to call.
696    * @param args an array of arguments to be
697    * passed to the extension, which may be either
698    * Vectors of Nodes, or Strings.
699    */

700   public Object JavaDoc call (Object JavaDoc object, String JavaDoc method, Object JavaDoc[] args)
701                                                         throws BSFException {
702     StringBuffer JavaDoc sb = new StringBuffer JavaDoc (300);
703
704     sb.append (object.toString());
705     sb.append (".");
706     sb.append (method);
707     sb.append ("(");
708     if (args != null) {
709       for (int i = 0; i < args.length; i++) {
710     sb.append (args[i].toString ());
711         if (i < args.length-1) {
712           sb.append (",");
713         }
714       }
715     }
716     sb.append (")");
717     return eval ("<internal>", -1, -1, sb.toString ());
718   }
719    /**
720    * This function and (BSFCOM) should be eliminated once support in BSF to call methods with arrays is present.
721    * Java does not support variable number of arguments so the arguments to these are packed in an array in C++ land.
722    * The same holds true for the two functions following this one. ALSO BSFCOM c++ object might be able to be eliminated in
723    * the process.
724    */

725    private final Object JavaDoc callBeanMethod(Object JavaDoc target, String JavaDoc methodName, Object JavaDoc[] args ) throws org.apache.bsf.BSFException
726    {
727       if(target.equals(this) && methodName.equals("callMethodViaBSF")){ return callMethodViaBSF((Object JavaDoc [])args[0]);} //We know this is the only funtion for this method.
728
if(target.equals(this) && methodName.equals("createBean")){ return createBean((Object JavaDoc [])args[0]);} //We know this is the only funtion for this method.
729
return EngineUtils.callBeanMethod(target, methodName, args);
730    }
731    /**
732    * Invokes the method assocaited with methodID on the bean with parameters in the array args.
733    *
734    */

735    public final Object JavaDoc callMethod( Object JavaDoc bean, int methodID, Object JavaDoc[] args) throws Exception JavaDoc
736    {
737         return JavaBean.callMethod(this, bean, methodID, args);
738    }
739    /**
740    *
741    */

742    final Object JavaDoc callMethodViaBSF(Object JavaDoc []args) throws org.apache.bsf.BSFException
743    {
744       Object JavaDoc [] bsfargs= new Object JavaDoc[args.length-2];
745       if(args.length >2)System.arraycopy(args,2,bsfargs,0, args.length-2);
746       return EngineUtils.callBeanMethod(args[0], (String JavaDoc) args[1], bsfargs );
747    }
748    /**
749    * createBean
750    *
751    */

752    public final Object JavaDoc createBean(Object JavaDoc []args) throws org.apache.bsf.BSFException
753    {
754       Object JavaDoc [] bsfargs= new Object JavaDoc[args.length-1];
755       if(args.length >1)System.arraycopy(args,1,bsfargs,0, args.length-1);
756       return EngineUtils.createBean((String JavaDoc) args[0], bsfargs );
757    }
758    public static final Throwable JavaDoc createBSFException( int reason, String JavaDoc msg, Throwable JavaDoc t)
759    {
760      if(t != null) return new BSFException(reason, msg, t);
761      else return new BSFException(reason,msg);
762    }
763   /**
764    * Declare a bean after the engine has been started. Declared beans
765    * are beans that are named and which the engine must make available
766    * to the scripts it runs in the most first class way possible.
767    *
768    * @param bean the bean to declare
769    *
770    * @exception BSFException if the engine cannot do this operation
771    */

772    public final void declareBean (BSFDeclaredBean bean) throws BSFException
773    {
774     if(isVBScript()) exec("<declareBean>", 0, 0, "SET " + bean.name + "=bsf.lookupBean(\"" + bean.name + "\") 'via declareBean");
775     else if(isJScript()) exec("<declareBean>", 0, 0,"var " + bean.name + "=bsf.lookupBean(\"" + bean.name + "\"); //via declareBean");
776     else if(isPerlScript()) exec("<declareBean>", 0, 0, "$"+bean.name + "=$bsf->lookupBean('" + bean.name + "'); #via declareBean");
777     else throw new BSFException(BSFException.REASON_OTHER_ERROR, lang + " does not support declareBean.");
778    }
779   /**
780    * This is used by an application to evaluate a string containing
781    * some expression. ActiveScript engines don't return anything .. so
782    * the return value is awlays null.
783    */

784   public Object JavaDoc eval (String JavaDoc source, int lineNo, int columnNo, Object JavaDoc oscript) throws BSFException
785   {
786
787     if(!isPerlScript()) return nativeEval (css, source, lineNo, columnNo, oscript.toString (), true);
788     else
789     { //ActiveState's Perl implementation does not seem to support this so this was added to make it work.
790
Integer JavaDoc key=new Integer JavaDoc(Thread.currentThread().hashCode());
791        nativeEval (css, "<bsf perl declare>",lineNo, columnNo, "$bsf->setEvalRet(" + oscript.toString () + "); #via eval", false);
792        Object JavaDoc ret= evalRet.get(key);
793        if(ret== evalRet) ret = null;
794        evalRet.put(key, evalRet); //loose reference to whatever.
795
return ret;
796     }
797   }
798   /**
799    * This is used by an application to execute a string containing
800    * a script to execute. ActiveScript engines don't return anything .. so
801    * the return value is awlays null.
802    */

803   public void exec (String JavaDoc source, int lineNo, int columnNo, Object JavaDoc script) throws BSFException
804   {
805     //Run the script throw away any return code.
806
synchronized(this)
807     {
808      if(terminated()) throw new BSFException(BSFException.REASON_OTHER_ERROR, "Exec or eval called after engine termination!");
809     }
810      nativeEval (css, source, lineNo, columnNo, script.toString (), false);
811   }
812    protected void finalize() throws Throwable JavaDoc
813    {
814
815      terminate();
816      super.finalize();
817    }
818   public void initialize (BSFManager mgr, String JavaDoc language, Vector declaredBeans) throws BSFException
819   {
820     if(null != dllLoadException) throw dllLoadException;
821     synchronized(this)
822     {
823      if(null != lang)
824      { //Been called before... this is bad.
825
lang=language;
826       throw new BSFException(BSFException.REASON_OTHER_ERROR, "Engine " + this + " initialized again");
827      }
828      lang= language;
829     }
830
831     super.initialize (mgr, language, declaredBeans);
832     if(isPerlScript()) evalRet= new Hashtable(); //Used by languages which don't support expressions.
833
bsfmgr= mgr; //Save away so we can use duing JNI callback.
834

835
836     nativeInit (lang, null , null ); //Does not return unless exception or this engine is terminated.
837
//Delared beans are not declared using ActiveX Script's AddItem anymore since
838
// this does not allow to undeclare these beans later.
839
if(css == null)
840     { //Double check: nativeInit should have set this field!
841
throw new BSFException(BSFException.REASON_OTHER_ERROR, "Engine " + this
842        + " failed to initialize native interface properly.");
843     }
844
845     //Run a little script that sets up the declared beans.
846
// NOTE: this is done this way as opposed to doing it with MS com addnamedItem because
847
// this allows for undeclare of these beans to work.
848
if( 0 !=declaredBeans.size())
849     {
850       String JavaDoc prefix= "";
851       String JavaDoc bsf= "";
852       String JavaDoc suffix= "";
853       String JavaDoc eos="";
854       String JavaDoc eosLast="";
855      if(isVBScript())
856      {
857        prefix= "SET ";
858        bsf= "=bsf.lookupBean(\"";
859        suffix= "\")";
860        eos=":";
861        eosLast="";
862      }
863      else if(isJScript())
864      {
865        prefix= "var ";
866        bsf= "=bsf.lookupBean(\"";
867        suffix= "\")";
868        eos=";";
869        eosLast=eos;
870      }
871      else if(isPerlScript())
872      {
873        prefix= "$";
874        bsf= "=$bsf->lookupBean('";
875        suffix= "')";
876        eos=";";
877        eosLast=eos;
878      }
879      else throw new BSFException(BSFException.REASON_OTHER_ERROR, lang + " does not support undeclareBean.");
880
881      StringBuffer JavaDoc startup= new StringBuffer JavaDoc("");
882     
883      int numDeclaredBeans= declaredBeans.size();
884      for(int i=0; i < numDeclaredBeans; ++i)
885      {
886        BSFDeclaredBean b=(BSFDeclaredBean)declaredBeans.elementAt(i);
887        startup.append(prefix+ b.name + bsf+ b.name + suffix + (i< (numDeclaredBeans-1)? eos : eosLast));
888      }
889      exec("<declareBean>", 0, 0, startup.toString());
890     }
891     
892
893   }
894   protected final boolean isCaseSensitive() { return isVBScript();}
895   protected final boolean isJScript(){ return lang.equalsIgnoreCase( LANG_JSCRIPT);}
896   protected final boolean isPerlScript(){ return lang.equalsIgnoreCase( LANG_PERLSCRIPT);}
897   /*Unfortunately language identifiers necessary to handle language specific issues.*/
898   protected final boolean isVBScript(){ return lang.equalsIgnoreCase( LANG_VBSCRIPT);}
899    /**
900    * lookupBean
901    */

902    public final Object JavaDoc lookupBean(String JavaDoc name) // throws org.apache.bsf.BSFException
903
{
904      return bsfmgr.lookupBean(name);
905    }
906   private native Object JavaDoc nativeEval(byte[] css, String JavaDoc Source, int lineNo, int columnNo, String JavaDoc script, boolean evaluate) throws BSFException;
907   /*Native COM support routines */ //should go else where but easier here for now... lazy
908
static native void nativeIdispatchAddRef (byte[]IdispatchInterface) throws BSFException;
909   static native void nativeIdispatchDeleteRef (byte[]IdispatchInterface) throws BSFException;
910   /*Native routines*/
911   private native void nativeInit (String JavaDoc lang, String JavaDoc declaredBeanNames, Object JavaDoc[]declaredBeans) throws BSFException; //If all goes well sets css
912
private native byte[] nativeObjectToVariant(byte[] css, Object JavaDoc o) throws BSFException;
913   private native byte[] nativeStingToBString(String JavaDoc s) throws BSFException;
914   private native void nativeTerminate(byte[] css);
915   /**
916    * objectToVariant converts a java object to it's equivalent MS variant
917    * representation. Primitives are converted, objects and strings only have
918    * their types set.
919    *
920    * @param o the object which is to be converted to a variant.
921    * @return a byte array that has the image of a variant. SEE MS docs.
922    *
923    */

924    private final byte[] objectToVariant( Object JavaDoc o) throws BSFException
925    {
926      byte[] v= new byte[16]; //Size of a variant
927

928        if( null== o)
929        { //to be safe.
930
v[0] = 1; //VT_NULL
931
v[1] = 0;
932        }
933        else if(o instanceof java.lang.Boolean JavaDoc) //VT_R8
934
{
935         v[0] = 11; //VT_BOOL
936
v[1] = 0;
937     byte x= (byte)( (((Boolean JavaDoc) o).booleanValue()) ? 0xff: 0);
938     v[8]= x;
939     v[9]= x;
940     v[10]= x;
941     v[11]= x;
942        }
943        else if(o instanceof java.lang.Integer JavaDoc) //VT_R8
944
{
945         v[0] = 3; //VT_I4
946
v[1] = 0;
947     int x= ((Integer JavaDoc)o).intValue();
948     v[8]= (byte)x;
949     v[9]= (byte)((x>>>8) & 0xff);
950     v[10]= (byte)((x>>>16) & 0xff);
951     v[11]= (byte)((x>>>24) & 0xff);
952        }
953        else if( o instanceof java.lang.String JavaDoc)
954        {
955          v[0] = 8; //VT_BSTR
956
v[1] = 0;
957        }
958        else if(o instanceof java.lang.Long JavaDoc) //VT_R8
959
{ //COM has no long type so promote it to double which can contain it.
960
v[0] = 5; //VT_R8
961
v[1] = 0;
962     long x= Double.doubleToLongBits((double)(((Long JavaDoc)o).longValue()));
963     v[8]= (byte)x;
964     v[9]= (byte)((x>>>8) & 0xff);
965     v[10]= (byte)((x>>>16) & 0xff);
966     v[11]= (byte)((x>>>24) & 0xff);
967     v[12]= (byte)((x>>>32) & 0xff);
968     v[13]= (byte)((x>>>40) & 0xff);
969     v[14]= (byte)((x>>>48) & 0xff);
970     v[15]= (byte)((x>>>56) & 0xff);
971        }
972        else if(o instanceof java.lang.Short JavaDoc)
973        {
974         v[0] = 2; //VT_I2
975
v[1] = 0;
976         int x= ((Short JavaDoc)o).intValue();
977     v[8]= (byte)x;
978     v[9]= (byte)((x>>>8) & 0xff);
979     v[10]= (byte)((x>>>16) & 0xff);
980     v[11]= (byte)((x>>>24) & 0xff);
981        }
982        else if(o instanceof java.lang.Float JavaDoc)
983        {
984         v[0] = 4; //VT_R4
985
v[1] = 0;
986     int x= Float.floatToIntBits(((Float JavaDoc)o).floatValue());
987     v[8]= (byte)x;
988     v[9]= (byte)((x>>>8) & 0xff);
989     v[10]= (byte)((x>>>16) & 0xff);
990     v[11]= (byte)((x>>>24) & 0xff);
991        }
992        else if(o instanceof java.lang.Double JavaDoc) //VT_R8
993
{
994         v[0] = 5; //VT_R8
995
v[1] = 0;
996     long x= Double.doubleToLongBits(((Double JavaDoc)o).doubleValue());
997     v[8]= (byte)x;
998     v[9]= (byte)((x>>>8) & 0xff);
999     v[10]= (byte)((x>>>16) & 0xff);
1000    v[11]= (byte)((x>>>24) & 0xff);
1001    v[12]= (byte)((x>>>32) & 0xff);
1002    v[13]= (byte)((x>>>40) & 0xff);
1003    v[14]= (byte)((x>>>48) & 0xff);
1004    v[15]= (byte)((x>>>56) & 0xff);
1005       }
1006       else if(o instanceof java.lang.Byte JavaDoc)
1007       {
1008        v[0] = 17; //VT_UI1
1009
v[1] = 0;
1010    byte x= ((Byte JavaDoc)o).byteValue();
1011    v[8]= x;
1012       }
1013       else if(o instanceof java.lang.Character JavaDoc)
1014       {
1015        v[0] = 17; //VT_UI1
1016
v[1] = 0;
1017    byte x= (byte) ((Character JavaDoc)o).charValue();
1018    v[8]= x;
1019       }
1020       else if(o instanceof java.lang.Void JavaDoc)
1021       {
1022        v[0] = 1; //VT_NULL
1023
v[1] = 0;
1024       }
1025       else if( o.getClass().isArray())
1026       {
1027        ArrayInfo ai= new ArrayInfo(o);
1028    v= ai.toVariant();
1029       }
1030       else
1031       { //Anything else just pray it's an object
1032
v[0] = 9; //VT_DISPATCH for object
1033
v[1] = 0;
1034
1035        byte[] cppref= null;
1036
1037        if(o instanceof org.apache.bsf.engines.activescript.COMIDispatchBean )
1038    {
1039          cppref = ((org.apache.bsf.engines.activescript.COMIDispatchBean )o).getIDispatchInterface();
1040          System.arraycopy(cppref,0,v,8, cppref.length);
1041    }
1042        else if(o instanceof org.apache.bsf.engines.activescript.vbEmpty) //Specific request to return back empty
1043
{
1044          v[0] = 0; //VT_EMPTY
1045
v[1] = 0;
1046    }
1047    else
1048    {
1049          cppref= nativeObjectToVariant(css, o);
1050          System.arraycopy(cppref,0,v,8, cppref.length);
1051    }
1052    
1053       }
1054     return v;
1055   }
1056  public final void setEvalRet( Object JavaDoc ret)
1057  {
1058    evalRet.put( new Integer JavaDoc(Thread.currentThread().hashCode()) , ret != null ? ret : evalRet); //Had some problems setting the value to null.
1059
}
1060   public synchronized void terminate()
1061   {
1062    if(!terminated())
1063    {
1064      byte[] css= this.css;
1065      this.css= null;
1066
1067      bsfmgr=null; //Used by other methods during JNI callbacks.
1068
evalRet= null; //Used by languages which don't support expressions.
1069
lang=null;
1070      nativeTerminate(css); //Let c++ objects cleanup too.
1071
super.terminate();
1072    }
1073   }
1074  private final boolean terminated() {return null== css;} //Indicates object has offically terminated.
1075
/**
1076    * Undeclare a previously declared bean.
1077    *
1078    * @param bean the bean to undeclare
1079    *
1080    * @exception BSFException if the engine cannot do this operation
1081    */

1082   public void undeclareBean (BSFDeclaredBean bean) throws BSFException
1083   {
1084    if(isVBScript()) exec("<undeclareBean>", 0, 0, "SET " + bean.name + "=Nothing 'via undeclareBean");
1085    else if(isJScript()) exec("<undeclareBean>", 0, 0, bean.name + "=null; // via undeclareBean");
1086    else if(isPerlScript()) exec("<undeclareBean>", 0, 0, "undef " + bean.name + " ; #via undeclareBean");
1087    else throw new BSFException(BSFException.REASON_OTHER_ERROR, lang + " does not support undeclareBean.");
1088 
1089   }
1090}
1091
Popular Tags