forked from I2P_Developers/i2p.i2p
Moved some logic to C++, which will extract i2p if it's not already,
and then secondly fire up the router in a second java process when extraction is completed. Gonna use "optional" type in C++ to make global variables a bit less painful to use.
This commit is contained in:
@ -6,3 +6,4 @@ However, this is a thin wrapper launching both Mac OS X trayicon and the I2P rou
|
||||
|
||||
More code will be merged in, it's just a f* mess which Meeh needs to clean up and move into repo.
|
||||
|
||||
`./fullBuild.sh` triggers Ant jobs and prepare the base.zip, as well as starting the ninja build.
|
||||
|
@ -8,41 +8,12 @@ lazy val buildAppBundleTask = taskKey[Unit](s"Build an Mac OS X bundle for I2P $
|
||||
lazy val buildDeployZipTask = taskKey[String](s"Build an zipfile with base directory for I2P ${i2pVersion}.")
|
||||
lazy val bundleBuildPath = new File("./output")
|
||||
|
||||
lazy val staticFiles = List(
|
||||
"blocklist.txt",
|
||||
"clients.config",
|
||||
"continents.txt",
|
||||
"countries.txt",
|
||||
"hosts.txt",
|
||||
"geoip.txt",
|
||||
"router.config",
|
||||
"webapps.config"
|
||||
)
|
||||
|
||||
lazy val resDir = new File("./../installer/resources")
|
||||
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") }
|
||||
|
||||
// TODO: Meeh: To be removed - logic is moved to obj-cpp
|
||||
def defaultOSXLauncherShellScript(javaOpts: Seq[String] = Seq.empty): Seq[String] = {
|
||||
val javaOptsString = javaOpts.map(_ + " ").mkString
|
||||
Seq(
|
||||
"#!/usr/bin/env sh",
|
||||
s"""
|
||||
|echo "I2P - Mac OS X Launcher starting up"
|
||||
|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"
|
||||
@ -55,22 +26,10 @@ unmanagedClasspath in Compile ++= Seq(
|
||||
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",
|
||||
"-Di2p.dir.base=$I2P",
|
||||
"-Djava.library.path=$I2P"
|
||||
)))
|
||||
)
|
||||
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false, includeDependency = false)
|
||||
|
||||
|
||||
assemblyJarName in assembly := s"OSXLauncher"
|
||||
assemblyJarName in assembly := s"launcher.jar"
|
||||
|
||||
assemblyExcludedJars in assembly := {
|
||||
val cp = (fullClasspath in assembly).value
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <subprocess.hpp>
|
||||
#include <future>
|
||||
|
||||
using namespace subprocess;
|
||||
using namespace std::experimental;
|
||||
|
||||
JavaRunner::JavaRunner(std::string javaBin, const fp_proc_t& execFn, const fp_t& cb)
|
||||
: javaBinaryPath(javaBin), executingFn(execFn), exitCallbackFn(cb)
|
||||
@ -11,7 +13,7 @@ JavaRunner::JavaRunner(std::string javaBin, const fp_proc_t& execFn, const fp_t&
|
||||
javaProcess = std::shared_ptr<Popen>(new Popen({javaBin.c_str(), "-version"}, defer_spawn{true}));
|
||||
}
|
||||
|
||||
void JavaRunner::execute()
|
||||
optional<std::future<int> > JavaRunner::execute()
|
||||
{
|
||||
try {
|
||||
auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
|
||||
@ -24,7 +26,9 @@ void JavaRunner::execute()
|
||||
|
||||
printf("Finished executingFn - Runs callbackFn\n");
|
||||
this->exitCallbackFn();
|
||||
return std::async(std::launch::async, []{ return 0; });
|
||||
} catch (std::exception* ex) {
|
||||
printf("ERROR: %s\n", ex->what());
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,14 @@
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include <subprocess.hpp>
|
||||
#include <optional.hpp>
|
||||
|
||||
using namespace subprocess;
|
||||
using namespace std::experimental;
|
||||
|
||||
class JavaRunner;
|
||||
|
||||
@ -23,9 +27,9 @@ typedef std::function<void(void)> fp_t;
|
||||
typedef std::function<void(JavaRunner *ptr)> fp_proc_t;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* class JavaRunner
|
||||
*
|
||||
*
|
||||
**/
|
||||
class JavaRunner
|
||||
{
|
||||
@ -34,7 +38,31 @@ public:
|
||||
JavaRunner(std::string javaBin, const fp_proc_t& executingFn, const fp_t& cb);
|
||||
~JavaRunner() = default;
|
||||
|
||||
void execute();
|
||||
const std::list<std::string> defaultStartupFlags {
|
||||
"-Xmx512M",
|
||||
"-Xms128m",
|
||||
"-Djava.awt.headless=true",
|
||||
"-Dwrapper.logfile=/tmp/router.log",
|
||||
"-Dwrapper.logfile.loglevel=DEBUG",
|
||||
"-Dwrapper.java.pidfile=/tmp/routerjvm.pid",
|
||||
"-Dwrapper.console.loglevel=DEBUG",
|
||||
"-Di2p.dir.base=$BASEPATH",
|
||||
"-Djava.library.path=$BASEPATH",
|
||||
"$JAVA_OPTS",
|
||||
"net.i2p.launchers.SimpleOSXLauncher"
|
||||
};
|
||||
|
||||
const std::list<std::string> defaultFlagsForExtractorJob {
|
||||
"-Xmx512M",
|
||||
"-Xms128m",
|
||||
"-Djava.awt.headless=true",
|
||||
"-Di2p.dir.base=$BASEPATH",
|
||||
"-Di2p.dir.zip=$ZIPPATH",
|
||||
"net.i2p.launchers.BaseExtractor",
|
||||
"extract"
|
||||
};
|
||||
|
||||
optional<std::future<int> > execute();
|
||||
std::shared_ptr<Popen> javaProcess;
|
||||
std::string javaBinaryPath;
|
||||
private:
|
||||
|
@ -22,8 +22,11 @@ rule ar
|
||||
rule cleanup
|
||||
command = rm -fr *.o clauncher I2PLauncher.app
|
||||
|
||||
# TODO: There must exists a cleaner way to solve this.
|
||||
rule bundledir
|
||||
command = mkdir -p I2PLauncher.app/Contents/{MacOS,Resources,Frameworks} && cp Info.plist I2PLauncher.app/Contents/Info.plist
|
||||
command = mkdir -p I2PLauncher.app/Contents/{MacOS,Resources,Frameworks} $
|
||||
&& cp Info.plist I2PLauncher.app/Contents/Info.plist $
|
||||
&& cp base.zip I2PLauncher.app/Contents/Resources/base.zip
|
||||
|
||||
rule copytobundledir
|
||||
command = cp clauncher I2PLauncher.app/Contents/MacOS/I2PLauncher
|
||||
@ -31,6 +34,9 @@ rule copytobundledir
|
||||
rule copyimgtobundle
|
||||
command = cp ItoopieTransparent.png I2PLauncher.app/Contents/Resources/ItoopieTransparent.png
|
||||
|
||||
rule builddir
|
||||
command = mkdir -p build
|
||||
|
||||
build main.o: cxx main.mm
|
||||
build StatusItemButton.o: cxx StatusItemButton.mm
|
||||
build JavaRunner.o: cxx JavaRunner.cpp
|
||||
@ -43,4 +49,5 @@ build copytobundle: copytobundledir | bundle clauncher
|
||||
build clauncher: link main.o StatusItemButton.o JavaRunner.o
|
||||
|
||||
build appbundle: copyimgtobundle | clauncher bundle copytobundle
|
||||
#build all: clauncher
|
||||
|
||||
default appbundle
|
||||
|
@ -0,0 +1,65 @@
|
||||
package net.i2p.launchers;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* As the name suggest, it extracts the base path.
|
||||
*
|
||||
* @author Meeh
|
||||
* @since 0.9.35
|
||||
*/
|
||||
public class BaseExtractor extends EnvCheck {
|
||||
|
||||
private void runExtract(String zipFilename, String destinationPath) {
|
||||
try(ZipFile file = new ZipFile(zipFilename)) {
|
||||
FileSystem fileSystem = FileSystems.getDefault();
|
||||
Enumeration<? extends ZipEntry> entries = file.entries();
|
||||
Files.createDirectory(fileSystem.getPath(destinationPath));
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if (entry.isDirectory()) {
|
||||
System.out.println("Creating Directory:" + destinationPath + entry.getName());
|
||||
Files.createDirectories(fileSystem.getPath(destinationPath + entry.getName()));
|
||||
} else {
|
||||
InputStream is = file.getInputStream(entry);
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
String uncompressedFileName = destinationPath + entry.getName();
|
||||
Path uncompressedFilePath = fileSystem.getPath(uncompressedFileName);
|
||||
Files.createFile(uncompressedFilePath);
|
||||
FileOutputStream fileOutput = new FileOutputStream(uncompressedFileName);
|
||||
while (bis.available() > 0) fileOutput.write(bis.read());
|
||||
fileOutput.close();
|
||||
System.out.println("Written :" + entry.getName());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
public BaseExtractor(String[] args) {
|
||||
super(args);
|
||||
|
||||
if (args.length == 2) {
|
||||
if ("extract".equals(args[0])) {
|
||||
// Start extract
|
||||
|
||||
}this.runExtract(System.getProperty("i2p.base.zip"),this.baseDirPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new BaseExtractor(args);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package net.i2p.launchers;
|
||||
|
||||
/**
|
||||
* Both the extractor class and the launcher class needs to be able to verify
|
||||
* the environment (variables) to work. This is a base class implementing it.
|
||||
*
|
||||
* @author Meeh
|
||||
* @since 0.9.35
|
||||
*/
|
||||
public class EnvCheck {
|
||||
|
||||
protected String baseDirPath = null;
|
||||
|
||||
protected boolean isBaseDirectorySet() {
|
||||
baseDirPath = System.getProperty("i2p.base.dir");
|
||||
if (baseDirPath == null) {
|
||||
baseDirPath = System.getenv("I2PBASE");
|
||||
}
|
||||
return (baseDirPath != null);
|
||||
}
|
||||
|
||||
public EnvCheck(String[] args) {
|
||||
if (!isBaseDirectorySet()) {
|
||||
throw new RuntimeException("Can't detect I2P's base directory!");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package net.i2p.launchers;
|
||||
|
||||
import net.i2p.router.Router;
|
||||
|
||||
public class SimpleOSXLauncher extends EnvCheck {
|
||||
|
||||
protected Router i2pRouter;
|
||||
|
||||
/**
|
||||
*
|
||||
* This is bairly a abstraction layer for the Router.
|
||||
* Why? I suspect we will add some spesific osx launcher code at startup
|
||||
* in the jvm somewhere, and this seem like a nice place to not make a mess everywhere.
|
||||
*
|
||||
* @author Meeh
|
||||
* @since 0.9.35
|
||||
*/
|
||||
public SimpleOSXLauncher(String[] args) {
|
||||
super(args);
|
||||
i2pRouter = new Router();
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
new SimpleOSXLauncher(args);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user