Some changes, after much testing I find it best to spawn an sub java

process for I2P rather than trying to load Router via reflection or
anything runtime fancy stuff. Shell script is implemented in SBT now,
and can now link to download JRE script and so on.
This commit is contained in:
meeh
2018-05-02 03:39:14 +00:00
parent c326bb7c6d
commit 70e994fcf3
8 changed files with 115 additions and 38 deletions

View File

@@ -41,8 +41,7 @@ lazy val macosx = (project in file("macosx"))
.settings(
commonSettings,
name := "MacI2PLauncher",
assemblyJarName in assembly := s"${name.value}-${version.value}.jar",
mainClass in assembly := Some("net.i2p.MacOSXRouterLauncherApp")
mainClass in assembly := Some("net.i2p.launchers.osx.LauncherAppMain")
).dependsOn(common)

View File

@@ -0,0 +1 @@
libraryDependencies += "org.xeustechnologies" % "jcl-core" % "2.8"

View File

@@ -1,6 +1,7 @@
package net.i2p.launchers
import java.io.{File, InputStream}
import java.io.{File, IOException, InputStream}
import java.nio.file.FileAlreadyExistsException
/**
@@ -58,10 +59,13 @@ class DeployProfile(val confDir: String, val baseDir: String) {
* @param fStr
* @return Unit
*/
def copyFileResToDisk(fStr: String) = Files.copy(
def copyFileResToDisk(fStr: String) = try { Files.copy(
getClass.getResource("/".concat(fStr)).getContent.asInstanceOf[InputStream],
Paths.get(DeployProfile.pathJoin(confDir, fStr)).normalize()
)
)} catch {
case _:FileAlreadyExistsException => {} // Ignored
case ex:IOException => println(s"Error! Exception ${ex}")
}
/**
@@ -72,10 +76,13 @@ class DeployProfile(val confDir: String, val baseDir: String) {
* @param is
* @return Unit
*/
def copyBaseFileResToDisk(path: String, is: InputStream) = Files.copy(
def copyBaseFileResToDisk(path: String, is: InputStream) = try { Files.copy(
is,
Paths.get(DeployProfile.pathJoin(baseDir, path)).normalize()
)
)} catch {
case _:FileAlreadyExistsException => {} // Ignored
case ex:IOException => println(s"Error! Exception ${ex}")
}
/**
* Filter function for finding missing required files.

View File

@@ -137,8 +137,8 @@ class OSXDeployment extends
}
}
} catch {
case ex:IOException => println(s"Error! Exception ${ex}")
case _:FileAlreadyExistsException => {} // Ignored
case ex:IOException => println(s"Error! Exception ${ex}")
}
}
@@ -166,8 +166,8 @@ class OSXDeployment extends
copyBaseFileResToDisk(file.getPath, getClass.getResourceAsStream("/".concat(file.getName)))
}
} catch {
case ex:IOException => println(s"Error! Exception ${ex}")
case _:FileAlreadyExistsException => {} // Ignored
case ex:IOException => println(s"Error! Exception ${ex}")
}
}
}

View File

@@ -1,6 +1,7 @@
package net.i2p.launchers
import java.net.URL
import java.io.File
/**
* A abstract class is kind of like an java interface.
@@ -9,10 +10,7 @@ import java.net.URL
* @since 0.9.35
*/
abstract class RouterLauncher {
def getClassLoader: ClassLoader
def addJarToClassPath(url: URL): Boolean
def runRouter(basePath: File, args: Array[String]): Unit
def runRouter(args: Array[String]): Unit
}

View File

@@ -6,6 +6,7 @@ import java.io.File
lazy val i2pVersion = "0.9.34"
lazy val cleanAllTask = taskKey[Unit]("Clean up and remove the OSX bundle")
lazy val buildAppBundleTask = taskKey[Unit](s"Build an Mac OS X bundle for I2P ${i2pVersion}.")
lazy val bundleBuildPath = file("./output")
@@ -21,28 +22,63 @@ lazy val staticFiles = List(
)
lazy val resDir = new File("./../installer/resources")
lazy val i2pBuildDir = new File("./../build")
lazy val warsForCopy = i2pBuildDir.list.filter { f => f.endsWith(".war") }
lazy val jarsForCopy = i2pBuildDir.list.filter { f => f.endsWith(".jar") }
lazy val i2pBuildDir = new File("./../pkg-temp")
lazy val warsForCopy = new File(i2pBuildDir, "webapps").list.filter { f => f.endsWith(".war") }
lazy val jarsForCopy = new File(i2pBuildDir, "lib").list.filter { f => f.endsWith(".jar") }
def defaultOSXLauncherShellScript(javaOpts: Seq[String] = Seq.empty): Seq[String] = {
val javaOptsString = javaOpts.map(_ + " ").mkString
Seq(
"#!/usr/bin/env sh",
s"""
|echo "Yo"
|export I2P=$$HOME/Library/I2P
|for jar in `ls $${I2P}/lib/*.jar`; do
| if [ ! -z $$CP ]; then
| CP=$${CP}:$${jar};
| else
| CP=$${jar}
| fi
|done
|export CLASSPATH=$$CP
|exec java -jar $javaOptsString$$JAVA_OPTS "$$0" "$$@"""".stripMargin,
"")
}
// Pointing the resources directory to the "installer" directory
resourceDirectory in Compile := baseDirectory.value / ".." / ".." / "installer" / "resources"
// Unmanaged base will be included in a fat jar
unmanagedBase in Compile := baseDirectory.value / ".." / ".." / "build"
unmanagedBase in Compile := baseDirectory.value / ".." / ".." / "pkg-temp" / "lib"
// Unmanaged classpath will be available at compile time
unmanagedClasspath in Compile ++= Seq(
baseDirectory.value / ".." / ".." / "build" / "*.jar"
baseDirectory.value / ".." / ".." / "pkg-temp" / "lib" / "*.jar"
)
assemblyOption in assembly := (assemblyOption in assembly).value.copy(
prependShellScript = Some(defaultOSXLauncherShellScript(
Seq(
"-Xmx512M",
"-Xms128m",
"-Dwrapper.logfile=/tmp/router.log",
"-Dwrapper.logfile.loglevel=DEBUG",
"-Dwrapper.java.pidfile=/tmp/routerjvm.pid",
"-Dwrapper.console.loglevel=DEBUG",
"-Djava.awt.headless=true",
"-Di2p.dir.base=$I2P",
"-Djava.library.path=$I2P"
)))
)
//assemblyOption in assembly := (assemblyOption in assembly).value.copy(prependShellScript = Some(defaultShellScript))
assemblyJarName in assembly := s"OSXLauncher"
assemblyExcludedJars in assembly := {
val cp = (fullClasspath in assembly).value
cp filter { c => jarsForCopy.toList.contains(c.data.getName) }
}
// TODO: MEEH: Add assemblyExcludedJars and load the router from own jar files, to handle upgrades better.
// In fact, most likely the bundle never would need an update except for the router jars/wars.
@@ -51,6 +87,11 @@ convertToICNSTask := {
println("TODO")
}
cleanAllTask := {
clean.value
IO.delete(bundleBuildPath)
}
buildAppBundleTask := {
println(s"Building Mac OS X bundle for I2P version ${i2pVersion}.")
bundleBuildPath.mkdir()
@@ -80,7 +121,7 @@ buildAppBundleTask := {
* and into the bundle so the launcher will know where to find i2p.
*
*/
dirsToCopy.map { d => IO.copyDirectory( new File(resDir, d), new File(paths.get("i2pbaseBunldePath").get, d) ) }
warsForCopy.map { w => IO.copyFile( new File(i2pBuildDir, w), new File(paths.get("webappsBunldePath").get, w) ) }
jarsForCopy.map { j => IO.copyFile( new File(i2pBuildDir, j), new File(paths.get("i2pJarsBunldePath").get, j) ) }
dirsToCopy.map { d => IO.copyDirectory( new File(resDir, d), new File(paths.get("i2pbaseBunldePath").get, d) ) }
warsForCopy.map { w => IO.copyFile( new File(new File(i2pBuildDir, "webapps"), w), new File(paths.get("webappsBunldePath").get, w) ) }
jarsForCopy.map { j => IO.copyFile( new File(new File(i2pBuildDir, "lib"), j), new File(paths.get("i2pJarsBunldePath").get, j) ) }
}

View File

@@ -1,9 +1,8 @@
package net.i2p
package net.i2p.launchers.osx
import java.io.File
import collection.JavaConverters._
import net.i2p.launchers.{OSXDefaults, OSXDeployment}
import net.i2p.launchers.{DeployProfile, OSXDefaults, OSXDeployment}
/**
*
@@ -33,23 +32,18 @@ import net.i2p.launchers.{OSXDefaults, OSXDeployment}
* @version 0.0.1
* @since 0.9.35
*/
object MacOSXRouterLauncherApp extends App {
object LauncherAppMain extends App {
val i2pBaseDir = OSXDefaults.getOSXBaseDirectory
new OSXDeployment()
// Change directory to base dir
System.setProperty("user.dir", i2pBaseDir.getAbsolutePath)
val i2pJarDir = new File(i2pBaseDir.getAbsolutePath, "lib")
i2pJarDir.list().toList.map { jar => {
val jarFile = new File(i2pJarDir, jar)
println(s"Loading jar: ${jarFile.toURI.toURL} => ${MacOSXRouterLauncher.addJarToClassPath(jarFile.toURI.toURL)}")
} }
MacOSXRouterLauncher.runRouter(args)
//net.i2p.Router.main(args)
try {
MacOSXRouterLauncher.runRouter(i2pBaseDir, args)
} finally {
System.out.println("Exit.")
}
}

View File

@@ -0,0 +1,37 @@
package net.i2p.launchers.osx
import java.io.File
import scala.sys.process.Process
import net.i2p.launchers.RouterLauncher
/**
*
*
* @author Meeh
* @since 0.9.35
*/
object MacOSXRouterLauncher extends RouterLauncher {
override def runRouter(args: Array[String]): Unit = {}
def runRouter(basePath: File, args: Array[String]): Unit = {
lazy val javaOpts = Seq(
"-Xmx512M",
"-Xms128m",
"-Dwrapper.logfile=/tmp/router.log",
"-Dwrapper.logfile.loglevel=DEBUG",
"-Dwrapper.java.pidfile=/tmp/routerjvm.pid",
"-Dwrapper.console.loglevel=DEBUG",
s"-Di2p.dir.base=${basePath}",
s"-Djava.library.path=${basePath}"
)
val javaOptsString = javaOpts.map(_ + " ").mkString
val cli = s"""java -cp "${new File(basePath, "lib").listFiles().map{f => f.toPath.toString.concat(":")}.mkString}." ${javaOptsString} net.i2p.router.Router"""
println(s"CLI => ${cli}")
val pb = Process(cli)
// Use "run" to let it fork in behind
val exitCode = pb.!
}
}