Skip to content

Commit

Permalink
use installed java instead of webservice
Browse files Browse the repository at this point in the history
  • Loading branch information
jkeam committed Dec 26, 2017
1 parent 5886177 commit 74caae8
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 101 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ Welcome to Javabytes, a disassembler for your java code. Inspired by a project b

Enter some Java and this application will show you the JVM bytecode that is generated.

Currently only supports [OpenJDK9](http://openjdk.java.net/projects/jdk9/), [OpenJDK8](http://openjdk.java.net/projects/jdk8/), [OpenJDK7](http://openjdk.java.net/projects/jdk7/), and [OpenJDK6](http://openjdk.java.net/projects/jdk6/).
Currently only supports [OpenJDK8](http://openjdk.java.net/projects/jdk8/).

The demo site can be found here at [javabytes.io](http://javabytes.io/).

## Development

### Prereq
1. Java 8
2. Play 2.3.1 or later
2. Scala 1.10
3. Play 2.3.1
4. SBT 0.13

```
brew install typesafe-activator
# also create tmp directory
mkdir -p /tmp/javabytes
```

### Starting the Server
Expand Down
31 changes: 8 additions & 23 deletions app/controllers/Application.scala
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
package controllers

import play.api.mvc._
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.Logger
import models._

object Application extends Controller {

implicit val codeReads: Reads[Code] = (
(JsPath \ "code").read[String] and
(JsPath \ "version").read[String]
)(Code.apply _)

def index = Action {
Ok(views.html.index(""))
}

def submitCode = Action(BodyParsers.parse.json) { request =>
Logger.debug("submit code")

val codeResult = request.body.validate[Code]
codeResult.fold(
errors => {
BadRequest(Json.obj("status" ->"ERROR", "message" -> JsError.toFlatJson(errors)))
},
code => {
val helper = new DisassemblerService()
val diss = helper.disassemble(code.version, code.code)
Ok(diss)
}
)
def submitCode = Action(parse.json) { request =>
(request.body \ "code").asOpt[String].map { code =>
val helper = new Disassembler()
val diss = helper.disassemble(code)
Ok(diss)
}.getOrElse {
BadRequest("Missing parameter [code]")
}
}

}
3 changes: 0 additions & 3 deletions app/models/Code.scala

This file was deleted.

161 changes: 161 additions & 0 deletions app/models/Disassembler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package models
import java.util.UUID
import java.io._
import java.nio.file._
import java.util.regex._
import scala.sys.process._
import scalax.io._

class Disassembler {
val tmpDir = "/tmp/javabytes/"

def disassemble(code:String):String = {
val logger = new Logger()
var error = false
var message = ""

//generate UUID
val rawId = "t" + UUID.randomUUID().toString()
val id = rawId.replaceAll("-", "").replaceAll("/", "").replaceAll("\\\\", "").replaceAll(":", "")

//create tmpDir
val userTmpDirName = tmpDir + id
val userTmpDir = createDir(userTmpDirName)

//try and extract name of class
val className = extractClassname(code)
if (className == "" || className == null) {
message += clean(logger.err, userTmpDirName)
error = true
removeDir(userTmpDir)
return message
}

//create tmp file
val javaFilename = userTmpDirName + "/" + className + ".java"
val classFilename = userTmpDirName + "/" + className + ".class"
val fw = new FileWriter(javaFilename)

//write code out to that file
try {
fw.write(code)
fw.flush()
}
catch {
case e: Exception =>
message += "Unable to create source.<br>"
error = true
}
finally {
fw.close()
}
if (error) return message

//run compiler
try {
val compilationCommand = "javac " + javaFilename
compilationCommand !! logger.log
}
catch {
case e: Exception =>
message += clean(logger.err, userTmpDirName)
error = true
quietRemoveFile(javaFilename, classFilename, userTmpDir)
return message
}

//dissassemble
var decomp = "An unknown error has occurred"
try {
val decompCommand = "javap -c " + classFilename
decomp = decompCommand !! logger.log
decomp = clean(decomp, userTmpDirName)
}
catch {
case e: Exception =>
message += clean(logger.err, userTmpDirName)
error = true
quietRemoveFile(javaFilename, classFilename, userTmpDir)
return message
}

//remove all junk files created
try {
removeFile(javaFilename, classFilename, userTmpDir)
}
catch {
case e: Exception =>
message += "Unable to cleanup.<br>"
error = true
return message
}

if (error) return message
else return decomp
}

def createDir(str:String):Path = {
val folderPath = Paths.get(str)
Files.createDirectories(folderPath)
}

def removeDir(userTmpDir:Path) = {
Files.delete(userTmpDir)
}

def clean(str:StringBuilder, dirPrefix:String):String = {
clean(str.toString(), dirPrefix)
}

def clean(str:String, dirPrefix:String):String = {
var decomp = str.replaceAll("\\{", "{{")
decomp = decomp.replaceAll(dirPrefix+ "/", "")
decomp = decomp.replaceAll("\\}", "}}")
decomp = decomp.replaceAll("\"", "'")
decomp = decomp.replaceAll("\n", "<br>")
decomp = decomp.replaceAll("\t", " ")
decomp = decomp.replaceAll("\u005E", " ")
decomp = decomp.replaceAll("\u2038", " ")
decomp = decomp.replaceAll("\\^", " ")
decomp = decomp.replaceAll("\\s\\s\\s\\s\\s+", "<br>")
decomp = decomp.replaceAll("\u001A", "")
decomp = decomp.replaceAll("^\\s+", "")
decomp
}

def quietRemoveFile(filename:String, classname:String, userTmpDir:Path) = {
try {
val sourceFile = new File(filename)
sourceFile.delete()

val classFile = new File(classname)
classFile.delete()

Files.delete(userTmpDir)
}
catch {
case e: Exception => System.out.println("Couldn't remove file")
}
}

def removeFile(filename:String, classname:String, userTmpDir:Path) = {
val sourceFile = new File(filename)
sourceFile.delete()

val classFile = new File(classname)
classFile.delete()

Files.delete(userTmpDir)
}

def extractClassname(code:String):String = {
val pattern = Pattern.compile("\\s*(public|private)\\s+class\\s+(\\w+)\\s+((extends\\s+\\w+)|(implements\\s+\\w+( ,\\w+)*))?\\s*\\{");
val m = pattern.matcher(code)

if (m.find()) {
m.group(2)
} else {
null
}
}
}
39 changes: 0 additions & 39 deletions app/models/DisassemblerService.scala

This file was deleted.

16 changes: 16 additions & 0 deletions app/models/Logger.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package models
import sys.process._

class Logger {
val out = new StringBuilder
val err = new StringBuilder

val log = ProcessLogger(
(o: String) => out.append(o),
(e: String) => err.append(e)
)

def getLog(): ProcessLogger = {
return log
}
}
13 changes: 1 addition & 12 deletions app/views/index.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,8 @@ <h1>Javabytes</h1>
</div>

<div id="main">
<div class="console-container-full">
<div class="form-group">
<label for="javaVersion" class="control-label">Java Version</label>
<select class="form-control" id="javaVersion">
<option value="java9">9</option>
<option value="java8">8</option>
<option value="java7">7</option>
<option value="java6">6</option>
</select>
</div>
</div>
<div class="console-container">
<label for="inputTextArea" class="control-label">Java Code</label>
<label for="inputTextArea" class="control-label">Java Code (Java8)</label>
<div class="console">
<textarea id="inputTextArea">public class HelloWorld {

Expand Down
14 changes: 0 additions & 14 deletions conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,3 @@ logger.play=INFO

# Logger provided to your application:
logger.application=DEBUG

# API Endpoints
# ~~~~~
dis.api.java6 = "http://java6-diss-service-50afa497.java-diss-stack.9d5c87b3.svc.dockerapp.io:8886"
dis.api.java6 = ${?JAVA6_API}

dis.api.java7 = "http://java7-diss-service-25238b2c.java-diss-stack.af4ebd3d.svc.dockerapp.io:8887"
dis.api.java7 = ${?JAVA7_API}

dis.api.java8 = "http://java8-diss-service-89047c2a.java-diss-stack.28a9377a.svc.dockerapp.io:8888"
dis.api.java8 = ${?JAVA8_API}

dis.api.java9 = "http://java9-diss-service-c75b92c6.java-diss-stack.478e6ab2.svc.dockerapp.io:8889"
dis.api.java9 = ${?JAVA9_API}
11 changes: 3 additions & 8 deletions public/javascripts/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ function Codebytes() {

this.submitCode = function() {
var rawText = inputMirror.getValue();
var version = $('#javaVersion').val();
if (!rawText || !version) {
outputMirror.setValue("Please make sure code and version are not blank.");
return;
}
if (!rawText) return;

$('#disassemble_button').attr('disabled', 'disabled');
outputMirror.setValue("Running...");
Expand All @@ -17,8 +13,7 @@ function Codebytes() {
type: 'POST',
url: '/',
data: JSON.stringify({
"code": rawText,
"version": version
"code": rawText
}),
dataType: 'text',
contentType: 'application/json; charset=utf-8'
Expand All @@ -34,7 +29,7 @@ function Codebytes() {
console.error('Error');
});
};

this.onReady= function() {
inputMirror = CodeMirror.fromTextArea($("#inputTextArea").get(0), {
lineNumbers: true,
Expand Down

0 comments on commit 74caae8

Please sign in to comment.