users@glassfish.java.net

[gf-users] glassfish4, javacompiler

From: Nikita <nikita.nn_at_gmail.com>
Date: Tue, 1 Jul 2014 15:32:49 +0400

using glassfish4, jdk1.7, errors in task.call() method,

>compiler.err.cant.resolve.location.args>padm.exforms.MemoryFileManager$JavaSourceFromString[mfm:///CM.java]]]>cannot find symbol
  symbol: method getVal(int,int)
  location: class padm.exforms.CM]
and etc...

in j2se client that code works ok, in glassfish server get errors

example code;

JavaCompiler compiler =
ToolProvider.getSystemJavaCompiler();DiagnosticCollector<JavaFileObject>
diagnostics = new DiagnosticCollector();String className = "CM";
Class<?>_class = getClassFromString(compiler, diagnostics,
Arrays.asList("-g:none", "-classpath",
System.getProperty("java.class.path")), className,
getClassCode(className));


  private Class<?> getClassFromString(JavaCompiler compiler,
DiagnosticListener<JavaFileObject> listener, List<String> flags,
String className, String classCode) {
    MemoryFileManager mfm = new
MemoryFileManager(compiler.getStandardFileManager(listener, null,
null));

    JavaFileObject fileObject =
MemoryFileManager.makeSource(className, classCode);

    CompilationTask task = compiler.getTask(null, mfm, listener,
flags, null, Arrays.asList(fileObject));
    if (task.call()) { //error in this call

      ClassLoader cl = mfm.getClassLoader(StandardLocation.CLASS_OUTPUT);

      try {
        return cl.loadClass(className);
      } catch (ClassNotFoundException e) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "err:" + e);
        return null;
      }
    } else
      return null;
  }


  private String getClassCode(String className) {
    StringBuilder sb = new StringBuilder();
    sb.append("package padm.exforms;"); //also tried without this line
    sb.append("import java.math.*; import java.sql.*; public class ");
    sb.append(className);
    sb.append(" extends ");
    sb.append(ConditionManager.class.getCanonicalName());
    sb.append("{public ");
    sb.append(className);
    sb.append("(){}");}

how to use javacompiler in glassfish4 ? i also tried set class-loader
delegate=false in sun-web.xml, but after that ejb beans don`t work

thanks

p.s MemoryFileManager class;

import java.io.*;import java.net.*;import java.util.*;import
java.util.logging.Level;import java.util.logging.Logger;
import javax.tools.*;import javax.tools.JavaFileObject.Kind;
/**
 * A file manager for compiling strings to byte arrays. This file manager
 * delegates to another file manager to lookup classes on boot class path.
 * <p/>
 * <p>
 * <b>This is NOT part of any supported API. If you write code that depends on
 * this, you do so at your own risk. This code and its internal interfaces are
 * subject to change or deletion without notice.</b>
 * </p>
 *
 * @author Peter von der Ah&eacute;
 */public final class MemoryFileManager extends
ForwardingJavaFileManager<JavaFileManager> {
  /**
   * Maps binary class names to class files stored as byte arrays.
   */
  private Map<String, byte[]> classes;

  /**
   * Creates a JavaFileObject representing the given compilation unit.
   *
   * @param name a NAME representing this source code, for example, the NAME
   * of a class
   * @param code a compilation unit (source code for a Java program)
   * @return a JavaFileObject represtenting the given compilation unit
   */
  public static JavaFileObject makeSource(String name, String code) {
    return new JavaSourceFromString(name, code);
  }

  /**
   * Construct a memory file manager which delegates to the specified file
   * manager for unknown sources.
   *
   * @param fileManager a file manager used to look up class files on class
   * path, etc.
   */
  public MemoryFileManager(JavaFileManager fileManager) {
    super(fileManager);
    classes = new HashMap();
  }

  /**
   * Get a class loader which first search the classes stored by this file
   * mananger.
   *
   * @return a class loader for compiled files
   */
  @Override
  public ClassLoader getClassLoader(Location location) {
    Enumeration<URL> e = null;
    try {
      e = MemoryFileManager.class.getClassLoader().getResources("");
    } catch (IOException e1) {
      Logger.getLogger(getClass().getName()).log(Level.SEVERE, "error:" + e1);
    }
    assert e != null;
    while (e.hasMoreElements()) {
      System.out.println("ClassLoader Resource: " + e.nextElement());
    }
    System.out.println("Class Resource: " +
MemoryFileManager.class.getResource("/"));
    return new ByteArrayClassLoader(classes);
  }

  @Override
  public JavaFileObject getJavaFileForOutput(Location location, String
name, Kind kind, FileObject originatingSource) throws
UnsupportedOperationException {
    if (originatingSource instanceof JavaSourceFromString)
      return new JavaClassInArray(name);
    else
      throw new UnsupportedOperationException();
  }

  protected static URI uriFromString(String uri) {
    try {
      return new URI(uri);
    } catch (URISyntaxException e) {
      throw new IllegalArgumentException(e);
    }
  }

  /**
   * A file object representing a Java class file stored in a byte array.
   */
  private class JavaClassInArray extends SimpleJavaFileObject {

    private String name;

    /**
     * Constructs a JavaClassInArray object.
     *
     * @param name binary NAME of the class to be stored in this file object
     */
    JavaClassInArray(String name) {
      super(uriFromString("mfm:///" + name.replace('.', '/') +
Kind.CLASS.extension), Kind.CLASS);
      this.name = name;
    }

    @Override
    public OutputStream openOutputStream() {
      return new FilterOutputStream(new ByteArrayOutputStream()) {
        @Override
        public void close() throws IOException {
          out.close();
          ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
          classes.put(name, bos.toByteArray());
        }
      };
    }
  }

  /**
   * A file object used to represent source coming from a string.
   */
  private static class JavaSourceFromString extends SimpleJavaFileObject {
    /**
     * The source code of this "file".
     */
    final String code;

    /**
     * Constructs a new JavaSourceFromString.
     *
     * @param name the NAME of the compilation unit represented by this file
     * object
     * @param code the source code for the compilation unit represented by
     * this file object
     */
    JavaSourceFromString(String name, String code) {
      super(uriFromString("mfm:///" + name.replace('.', '/') +
Kind.SOURCE.extension), Kind.SOURCE);
      this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      return code;
    }
  }}