public Object execEvalShared()

in src/main/java/org/apache/bsf/engines/netrexx/NetRexxEngine.java [247:450]


    public Object execEvalShared (String source, int lineNo, int columnNo,
                              Object oscript,boolean returnsObject)
    throws BSFException
    {
        Object retval=null;
        String classname=null;
        GeneratedFile gf=null;

        // Moved into the exec process; see comment above.
        Class rexxclass=null;

        String basescript=oscript.toString();
        String script=basescript; // May be altered by $$CLASSNAME$$ expansion

        try {
                    // Do we already have a class exactly matching this code?
                    rexxclass=(Class)codeToClass.get(basescript);

                    if(rexxclass!=null)

            {
                            logger.debug("NetRexxEngine: Found pre-compiled class" +
                                                   " for script '" + basescript + "'");
                            classname=rexxclass.getName();
            }
                    else
            {
                            gf=openUniqueFile(tempDir,"BSFNetRexx",".nrx");
                            if(gf==null)
                                throw new BSFException("couldn't create NetRexx scratchfile");

                            // Obtain classname
                            classname=gf.className;

                            // Decide whether to declare a return type
                            String returnsDecl="";
                            if(returnsObject)
                                returnsDecl="returns java.lang.Object";

                            // Write the kluge header to the file.
                            // ***** By doing so we give up the ability to use Property blocks.
                            gf.fos.write(("class "+classname+";\n")
                                         .getBytes());
                            gf.fos.write(
                                         ("method BSFNetRexxEngineEntry(bsf=org.apache.bsf.util.BSFFunctions) "+
                                          " public static "+returnsDecl+";\n")
                                 .getBytes());

                            // Edit the script to replace placeholder with the generated
                            // classname. Note that this occurs _after_ the cache was
                            // checked!
                            int startpoint,endpoint;
                            if((startpoint=script.indexOf(placeholder))>=0)
                {
                                    StringBuffer changed=new StringBuffer();
                                    for(;
                                        startpoint>=0;
                                        startpoint=script.indexOf(placeholder,startpoint))
                    {
                                            changed.setLength(0);   // Reset for 2nd pass or later
                                            if(startpoint>0)
                                                changed.append(script.substring(0,startpoint));
                                            changed.append(classname);
                                            endpoint=startpoint+placeholder.length();
                                            if(endpoint<script.length())
                                                changed.append(script.substring(endpoint));
                                            script=changed.toString();
                    }
                }

                            BSFDeclaredBean tempBean;
                            String          className;

                            for (int i = 0; i < declaredBeans.size (); i++)
                {
                                    tempBean  = (BSFDeclaredBean) declaredBeans.elementAt (i);
                                    className = StringUtils.getClassName (tempBean.type);

                                    gf.fos.write ((tempBean.name + " =" + className + "   bsf.lookupBean(\"" +
                                                   tempBean.name + "\");").getBytes());
                }

                            if(returnsObject)
                                gf.fos.write("return ".getBytes());

                            // Copy the input to the file.
                            // Assumes all available -- probably mistake, but same as
                            // other engines.
                            gf.fos.write(script.getBytes());
                            gf.fos.close();

                            logger.debug("NetRexxEngine: wrote temp file " +
                                                   gf.file.getPath () + ", now compiling");

                            // Compile through Java to .class file
                    String command=gf.file.getPath(); //classname;
                    if (logger.isDebugEnabled()) {
                        command += " -verbose4";
                    } else {
                        command += " -noverbose";
                        command += " -noconsole";
                    }

                    netrexx.lang.Rexx cmdline= new netrexx.lang.Rexx(command);
                    int retValue;

                    // May not be threadsafe. Serialize access on static object:
                    synchronized(serializeCompilation)
                        {
                            // compile to a .java file
                            retValue =
                                COM.ibm.netrexx.process.NetRexxC.main(cmdline,
                                                                      new PrintWriter(System.err));
                        }

                // Check if there were errors while compiling the Rexx code.
                if (retValue == 2)
                {
                  throw new BSFException(BSFException.REASON_EXECUTION_ERROR,
                                         "There were NetRexx errors.");
                }

                // Load class.
                logger.debug("NetRexxEngine: loading class "+classname);
                rexxclass=EngineUtils.loadClass (mgr, classname);

                // Stash class for reuse
                codeToClass.put(basescript,rexxclass);
                        }

            Object[] args={mgrfuncs};
            retval=callStatic(rexxclass, "BSFNetRexxEngineEntry",args);
                }
                catch (BSFException e)
                    {
                        // Just forward the exception on.
                        throw e;
                    }
                catch(Exception e)
                    {
            e.printStackTrace ();
            if (e instanceof InvocationTargetException)
            {
                Throwable t = ((InvocationTargetException)e).getTargetException ();
                t.printStackTrace ();
            }
            throw new BSFException (BSFException.REASON_IO_ERROR,
                                    e.getMessage (), e);
        }
        finally
        {
            // Cleanup: delete the .nrx and .class files
            // (if any) generated by NetRexx Trace requests.

            if(gf!=null && gf.file!=null && gf.file.exists())
                gf.file.delete();  // .nrx file

            if(classname!=null)
            {
                // Generated src
                File file=new File(tempDir+File.separatorChar+classname+".java");
                if(file.exists())
                    file.delete();

                // Generated class
                file=new File(classname+".class");
                if(file.exists())
                    file.delete();

                // Can this be done without disrupting trace?
                file=new File(tempDir+File.separatorChar+classname+".crossref");
                if(file.exists())
                    file.delete();

                // Search for and clean up minor classes, classname$xxx.class
                file=new File(tempDir);
                minorPrefix=classname+"$"; // Indirect arg to filter
                String[] minor_classfiles=
                    file.list(
                        // ANONYMOUS CLASS for filter:
                        new FilenameFilter()
                        {
                            // Starts with classname$ and ends with .class
                            public boolean accept(File dir,String name)
                            {
                                return
                                    (0==name.indexOf(minorPrefix))
                                    &&
                                    (name.lastIndexOf(".class")==name.length()-6)
                                    ;
                            }
                        }
                        );
                if(minor_classfiles!=null)
                    for(int i=minor_classfiles.length;i>0;)
                    {
                        file=new File(minor_classfiles[--i]);
                        file.delete();
                    }
            }
        }

        return retval;
    }