diff --git a/src/main/scala/org/rosi_project/model_sync/generator/io/SModelFSWriter.scala b/src/main/scala/org/rosi_project/model_sync/generator/io/SModelFSWriter.scala index bec80311b68bec84dbe8e75897f5177829209466..82c2df943dd69d95def514827ed070028194eb1e 100644 --- a/src/main/scala/org/rosi_project/model_sync/generator/io/SModelFSWriter.scala +++ b/src/main/scala/org/rosi_project/model_sync/generator/io/SModelFSWriter.scala @@ -1,9 +1,9 @@ package org.rosi_project.model_sync.generator.io -import java.io.{FileOutputStream, PrintWriter} +import java.io.{BufferedInputStream, FileInputStream, FileOutputStream, PrintWriter} import java.net.URLClassLoader import java.nio.file.Files -import java.util.jar.{Attributes, JarOutputStream, Manifest} +import java.util.jar.{Attributes, JarEntry, JarOutputStream, Manifest} import org.rosi_project.model_sync.generator.acr.{SAttribute, SClass, SMethod, SType} import org.rosi_project.model_sync.generator.sync_model.{SModel, SModelVisitor} @@ -11,6 +11,7 @@ import org.rosi_project.model_sync.generator.sync_model.{SModel, SModelVisitor} import scala.reflect.io.{File, Path} import scala.tools.nsc.reporters.ConsoleReporter import scala.tools.nsc.{GenericRunnerSettings, Global, Settings} +import scala.util.control.Breaks._ /** * @author Rico Bergmann @@ -26,6 +27,7 @@ class SModelFSWriter extends SModelVisitor { println(s"... Wrote files (sources) $sFilesToCompile") println("... Starting compilation") + // see: https://stackoverflow.com/a/20323371/5161760 val out = new PrintWriter(System.out) val compilationSettings: Settings = new GenericRunnerSettings(out.println) // TODO do we want to reuse the whole classpath? Or just the parts we _actually_ need @@ -39,13 +41,53 @@ class SModelFSWriter extends SModelVisitor { println("... Compilation done") println("... Cleaning up") - sFilesToCompile.foreach{_.delete} + sFilesToCompile.foreach { + _.delete + } println("... Generating JAR") - // see: https://stackoverflow.com/questions/1281229/how-to-use-jaroutputstream-to-create-a-jar-file + // see: https://stackoverflow.com/a/1281295/5161760 val mf = new Manifest mf.getMainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0") val targetJar = new JarOutputStream(new FileOutputStream("model.jar"), mf) + var filesToAdd: List[java.io.File] = baseOutputDir.jfile.listFiles.toList + + while (filesToAdd.nonEmpty) { + val file = filesToAdd.head + var fname = file.getAbsolutePath.replace(baseOutputDir.jfile.getAbsolutePath + File.separator, "").replaceAll("\\\\", "/") + println(s"Adding to JAR: $fname") + if (file.isDirectory) { + if (!fname.endsWith("/")) { + fname += "/" + } + filesToAdd ++= file.listFiles.toList + + val entry = new JarEntry(fname) + entry.setTime(file.lastModified) + targetJar.putNextEntry(entry) + targetJar.closeEntry() + } else { + val entry = new JarEntry(fname) + entry.setTime(file.lastModified) + targetJar.putNextEntry(entry) + + val in = new BufferedInputStream(new FileInputStream(file)) + var buffer = new Array[Byte](1024) + breakable { + while (true) { + val bytesRead = in.read(buffer) + if (bytesRead == -1) { + break + } + targetJar.write(buffer, 0, bytesRead) + } + } + targetJar.closeEntry() + in.close() + } + + filesToAdd = filesToAdd.tail + } // TODO fill the JAR @@ -55,8 +97,11 @@ class SModelFSWriter extends SModelVisitor { override def visit(sClass: SClass): Unit = { println(s"Writing class $sClass") - val classNameWithPath = baseOutputDir.toAbsolute.toString() + pckg2Path(sClass.getPackage) + File.separator + s"${sClass.name}.scala" + val classNameWithPath = baseOutputDir.toAbsolute.toString() + File.separator + pckg2Path(sClass.getPackage) + File.separator + s"${sClass.name}.scala" val writer = new SClassWriter(sClass) + + // TODO create missing directories for packages (if necessary) + val classFile = File(classNameWithPath) classFile.writeAll(writer.stringify) @@ -81,11 +126,15 @@ class SModelFSWriter extends SModelVisitor { val ctxLoader = Thread.currentThread().getContextClassLoader ctxLoader match { case urlCL: URLClassLoader => - urlCL.getURLs.toList.map{_.toString} + urlCL.getURLs.toList.map { + _.toString + } case wrappedCL => wrappedCL.getParent match { case urlCL: URLClassLoader => - urlCL.getURLs.toList.map{_.toString} + urlCL.getURLs.toList.map { + _.toString + } case something => sys.error(s"Could not unwrap class loader: $something") } }