Jump to content

MacroExtension.java

From EDM2
Revision as of 17:25, 22 October 2012 by Martini (talk | contribs) (Created page with "Back to Grinding Java - Dynamic Java <PRE> package macrolanguage; import sun.tools.javac.Main; import java.util.*; import java.lang.*; import java.io.*; import macrolanguage...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Back to Grinding Java - Dynamic Java

package macrolanguage;
import sun.tools.javac.Main;
import java.util.*;
import java.lang.*;
import java.io.*;
import macrolanguage.SimpleStream;

/**
 * To use the MacroExtension you simply add it to your program
 * and add an interface for selecting the macro, then use the simple
 * methods of this class to compile and execute a macro.
 * The class offers several features:
 * 1. Interaction with your application.
 * 2. The full power you had writing the application will be available
 *    to your users.
 * 3. You can add a sandbox to block some functionality.
 * 4. You can ship upgrades/fixes as plugins.
 * 5. Other vendors and users can easily write plugins.
 * 6. Plugins will be fully integrate, cross platform and run in the
 *    same speed as the VM.
 * It is recommended you expose some of your software's internals
 * to your users to make this tool more effective.
**/
class MacroExtension extends ClassLoader
{
  MacroExtension()
  {
    compilerClass = new sun.tools.javac.Main(dataStream,"");
  }

  /**
   * This method accepts a class file as parameter
   * and returns an instance of it.
  **/
  public Object getObject(String fileName)
    throws  java.lang.ClassNotFoundException,
            java.lang.InstantiationException,
            java.lang.IllegalAccessException
  {
    Class classInstance = getClass();
    return(classInstance.forName(fileName).newInstance());
  }

  /**
   * This method accepts a java file as parameter and compiles it.
   * It returns true if compilation was successful and false otherwise.
  **/
  public boolean compile(String fileName)
  {
    String [] stringArr = new String[1];
    stringArr[0] = fileName;
    return(compilerClass.compile(stringArr));
  }

  /**
   * This method returns a vector in which all
   * the compilation errors are stored as strings.
  **/
  public Vector getCompilationErrors()
  {
    return(dataStream.getStringsWritten());
  }

  /**
   * The main method is conveniently located here for testing purposes.
  **/
  public static void main(String argv[])
  {
    MacroExtension m = new MacroExtension();
    m.compile("HelloWorld.java");
    m.loadObject("HelloWorld");
  }

  /**
   * creates an instance of a class by getting its name
   * and returns that instance, or null if none were found.
  **/
  public Object loadObject(String className)
  {
    try
    {
      loadClass(className, true);
      return(getObject(className));
    }
    catch(java.lang.ClassNotFoundException e)
    {
      System.out.println("Class not found exception: " + e.getMessage());
    }
    catch(java.lang.InstantiationException e)
    {
      System.out.println("Instantiation exception: " + e.getMessage());
    }
    catch(java.lang.IllegalAccessException e)
    {
      System.out.println("Illegal access exception : " + e.getMessage());
    }
    catch(Exception e)
    {
      System.out.println("An exception was thrown: " + e.getMessage());
    }
    return(null);
  }


  protected Class loadClass(String className, boolean callReslove)
  {
    Class returnValue = (Class) classCache.get(className);

    if(returnValue != null)
      return(returnValue);

    String classFullName;

    try
    {
      File classFile;
      if (!className.endsWith(".class"))
        classFullName = className + ".class";
      else
      {
        className = className.substring(0, className.length() - 5);
        System.out.println("Class name is: " + className);
        classFullName = className + ".class";
      }

      classFile = new File(classFullName);

      FileInputStream inFile = new FileInputStream(classFile);
      byte[] classData = new byte[(int)classFile.length()];

      inFile.read(classData);

      inFile.close();

      returnValue = defineClass(className, classData, 0, classData.length);

      classCache.put(className, returnValue);
    }
    catch(IOException ioerr)
    {
      try
      {
        returnValue = findSystemClass(className);
        return(returnValue);
      }
      catch (Exception anyException)
      {
        System.out.println("File access error: " + anyException.getMessage());
        return(null);
      }
    }

    if(callReslove)
    {
      resolveClass(returnValue);
    }

    return(returnValue);
  }

  /**
   * Notice the long name. It's here to avoid namespace
   * problems with another Main
   **/
  private sun.tools.javac.Main compilerClass;
  private SimpleStream dataStream = new SimpleStream();
  private Hashtable classCache = new Hashtable();
}