示例#1
0
  /**
   * Implementation of {@link ClassLoader#findClass(String)}.
   *
   * @throws ClassNotFoundException
   */
  public Class<?> findClass(String className) throws ClassNotFoundException {

    byte[] ba;
    int size;
    try {

      // Maybe the bytecode is already there, because the class was
      // compiled as a side effect of a preceding
      // compilation.
      JavaFileObject classFileObject =
          this.getJavaFileManager()
              .getJavaFileForInput(StandardLocation.CLASS_OUTPUT, className, Kind.CLASS);

      if (classFileObject == null) {

        // Get the sourceFile.
        JavaFileObject sourceFileObject =
            this.getJavaFileManager()
                .getJavaFileForInput(StandardLocation.SOURCE_PATH, className, Kind.SOURCE);
        if (sourceFileObject == null) {
          throw new DiagnosticException("Source for '" + className + "' not found");
        }

        // Compose the effective compiler options.
        Vector<String> optionList = new Vector<String>();

        IPreferenceStore store = Bio7EditorPlugin.getDefault().getPreferenceStore();
        String version = store.getString("compiler_version");
        boolean debug = store.getBoolean("compiler_debug");
        boolean verbose = store.getBoolean("compiler_verbose");
        boolean warnings = store.getBoolean("compiler_warnings");
        boolean createMarker = store.getBoolean("compiler_marker");
        optionList.addElement("-source");
        optionList.addElement(version);
        optionList.addElement("-target");
        optionList.addElement(version);

        optionList.addElement("-classpath");
        /* Add the Bio7 libs etc. for the compiler! */
        optionList.addElement(new ScanClassPath().scan());
        if (debug) {
          optionList.addElement("-g");
        } else {
          optionList.addElement("-g:none");
        }
        if (verbose) {
          optionList.addElement("-verbose");
        }

        if (warnings == false) {
          optionList.addElement("-nowarn");
        }

        DiagnosticCollector<JavaFileObject> diagnosticsCollector =
            new DiagnosticCollector<JavaFileObject>();

        // Run the compiler.
        boolean success =
            this.compiler
                .getTask(
                    null, // out
                    this.getJavaFileManager(), // fileManager
                    diagnosticsCollector,
                    optionList, // options
                    null, // classes
                    Collections.singleton(sourceFileObject) // compilationUnits
                    )
                .call();

        if (!success) {

          markError(diagnosticsCollector, createMarker);

          throw new ClassNotFoundException(className + ": Compilation failed");
        }

        classFileObject =
            this.getJavaFileManager()
                .getJavaFileForInput(StandardLocation.CLASS_OUTPUT, className, Kind.CLASS);

        if (classFileObject == null) {
          throw new ClassNotFoundException(className + ": Class file not created by compilation");
        }
      }

      if (classFileObject instanceof ByteArrayJavaFileObject) {
        ByteArrayJavaFileObject bajfo = (ByteArrayJavaFileObject) classFileObject;
        ba = bajfo.toByteArray();
        size = ba.length;
      } else {
        ba = new byte[4096];
        size = 0;
        InputStream is = classFileObject.openInputStream();
        try {
          for (; ; ) {
            int res = is.read(ba, size, ba.length - size);
            if (res == -1) break;
            size += res;
            if (size == ba.length) {
              byte[] tmp = new byte[2 * size];
              System.arraycopy(ba, 0, tmp, 0, size);
              ba = tmp;
            }
          }
        } finally {
          is.close();
        }
      }
    } catch (IOException ioe) {
      throw new DiagnosticException(ioe);
    }

    return this.defineClass(
        className,
        ba,
        0,
        size,
        (this.optionalProtectionDomainFactory == null
            ? null
            : this.optionalProtectionDomainFactory.getProtectionDomain(
                getSourceResourceName(className))));
  }
示例#2
0
  /**
   * Save a compiled class and associated classes to a jar file.
   *
   * <p>With a packageName = "" and recursive = false, it will save clazz and any classes compiled
   * from the same source (I think); this is probably what you want.
   *
   * @param packageName package name prefix to search for classes, or "" for all
   * @param clazz a class that has been previously compiled by this bridge
   * @param mainClazz a class that will be installed as the "Main-Class" of a runnable jar
   * @param outStream output stream
   * @param recursive whether to retrieve classes from rest of the the JavaFileManager hierarchy
   * @throws FileNotFoundException
   * @throws IOException
   */
  public void saveToJar(
      String packageName,
      Class<?> clazz,
      Class<?> mainClazz,
      OutputStream outStream,
      boolean recursive)
      throws IOException {
    JavaFileManager manager = fileManagerCache.get(clazz);
    List<JavaFileObject> list = new ArrayList<JavaFileObject>();

    for (JavaFileObject obj :
        manager.list(
            StandardLocation.CLASS_PATH,
            packageName,
            Collections.singleton(JavaFileObject.Kind.CLASS),
            false)) list.add(obj);

    if (list.iterator().hasNext()) {
      Manifest manifest = new Manifest();
      manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");

      if (mainClazz != null) {
        manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainClazz.getName());
      }
      manifest
          .getMainAttributes()
          .put(new Attributes.Name("X-Rascal-Saved-Class"), clazz.getName());
      JarOutputStream target = new JarOutputStream(outStream, manifest);
      JarEntry entry = new JarEntry("META-INF/");
      target.putNextEntry(entry);
      Collection<String> dirs = new ArrayList<String>();

      for (JavaFileObject o : list) {
        String path = o.toUri().getPath().replace(".", "/");
        makeJarDirs(target, dirs, path);
        entry = new JarEntry(path + ".class");
        entry.setTime(o.getLastModified());
        target.putNextEntry(entry);

        try (InputStream stream = o.openInputStream()) {
          byte[] buffer = new byte[8192];
          int c = stream.read(buffer);
          while (c > -1) {
            target.write(buffer, 0, c);
            c = stream.read(buffer);
          }
        }
        target.closeEntry();
      }

      if (mainClazz != null) {
        String name = mainClazz.getName();
        String path = name.replace(".", "/") + ".class";

        String dir = path.substring(0, path.lastIndexOf('/'));
        StringBuilder dirTmp = new StringBuilder(dir.length());
        for (String d : dir.split("/")) {
          dirTmp.append(d);
          dirTmp.append("/");
          String tmp = dirTmp.toString();
          if (!dirs.contains(tmp)) {
            dirs.add(tmp);
            entry = new JarEntry(tmp);
            target.putNextEntry(entry);
          }
        }
        entry = new JarEntry(path);
        target.putNextEntry(entry);

        try (InputStream stream = mainClazz.getClassLoader().getResourceAsStream(path)) {
          byte[] buffer = new byte[8192];
          int c = stream.read(buffer);
          while (c > -1) {
            target.write(buffer, 0, c);
            c = stream.read(buffer);
          }
        }
        target.closeEntry();
      }

      target.close();
    }
  }