alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (BytecodeWriters.scala)

This example Scala source code file (BytecodeWriters.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

abstractfile, abstractfile, array, bytecodewriter, dataoutputstream, directtojarfilewriter, global, io, jar, jclass, jclass, string, string, symbol, symbol, unit

The Scala BytecodeWriters.scala source code

/* NSC -- new Scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  Paul Phillips
 */

package scala.tools.nsc
package backend.jvm

import ch.epfl.lamp.fjbg._
import java.io.{ DataOutputStream, OutputStream }
import scala.tools.nsc.io.{ AbstractFile, Path }
import scala.tools.nsc.util.ScalaClassLoader
import scala.tools.util.Javap
import java.util.jar.{ JarEntry, JarOutputStream }

/** For the last mile: turning generated bytecode in memory into
 *  something you can use.  Has implementations for writing to class
 *  files, jars, and disassembled/javap output.
 */
trait BytecodeWriters {
  val global: Global
  import global._

  private def outputDirectory(sym: Symbol): AbstractFile = (
    settings.outputDirs.outputDirFor {
      atPhase(currentRun.flattenPhase.prev)(sym.sourceFile)
    }
  )  
  private def getFile(base: AbstractFile, cls: JClass, suffix: String): AbstractFile = {
    var dir = base
    val pathParts = cls.getName().split("[./]").toList
    for (part <- pathParts.init) {
      dir = dir.subdirectoryNamed(part)
    }
    dir.fileNamed(pathParts.last + suffix)
  }
  private def getFile(sym: Symbol, cls: JClass, suffix: String): AbstractFile =
    getFile(outputDirectory(sym), cls, suffix)
  
  trait BytecodeWriter {
    def writeClass(label: String, jclass: JClass, sym: Symbol): Unit
    def close(): Unit = ()
  }
  
  class DirectToJarfileWriter(val jarFile: AbstractFile) extends BytecodeWriter {
    private val out = new JarOutputStream(jarFile.bufferedOutput)
    def writeClass(label: String, jclass: JClass, sym: Symbol) {
      val path = jclass.getName + ".class"
      out putNextEntry new JarEntry(path)
      val dataStream = new DataOutputStream(out)
      try jclass writeTo dataStream
      finally dataStream.flush()
      informProgress("added " + label + path + " to jar")
    }
    override def close() = out.close()
  }

  trait JavapBytecodeWriter extends BytecodeWriter {
    val baseDir = Path(settings.Ygenjavap.value)

    def emitJavap(bytes: Array[Byte], javapFile: io.File) {
      val pw    = javapFile.printWriter()
      val javap = new Javap(ScalaClassLoader.getSystemLoader(), pw) {
        override def findBytes(path: String): Array[Byte] = bytes
      }

      try javap(Seq("-verbose", "dummy")) foreach (_.show())
      finally pw.close()
    }
    abstract override def writeClass(label: String, jclass: JClass, sym: Symbol) {
      super.writeClass(label, jclass, sym)

      val bytes     = getFile(sym, jclass, ".class").toByteArray      
      val segments  = jclass.getName().split("[./]")
      val javapFile = segments.foldLeft(baseDir)(_ / _) changeExtension "javap" toFile

      javapFile.parent.createDirectory()
      emitJavap(bytes, javapFile)
    }
  }

  trait ClassBytecodeWriter extends BytecodeWriter {
    def writeClass(label: String, jclass: JClass, sym: Symbol) {
      val outfile   = getFile(sym, jclass, ".class")
      val outstream = new DataOutputStream(outfile.bufferedOutput)

      try jclass writeTo outstream
      finally outstream.close()
      informProgress("wrote '" + label + "' to " + outfile)
    }
  }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala BytecodeWriters.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.