forked from I2P_Developers/i2p.i2p
Fixed a load of issues related to my "sync" approach, and Mac OSX's "async" API.
This commit is contained in:
@ -62,7 +62,7 @@ object RouterLauncherApp extends App {
|
|||||||
val configPath = Option(System.getProperty("i2p.dir.config")).getOrElse(System.getenv("I2PCONFIG"))
|
val configPath = Option(System.getProperty("i2p.dir.config")).getOrElse(System.getenv("I2PCONFIG"))
|
||||||
|
|
||||||
println(s"basePath => ${basePath}\nconfigPath => ${configPath}")
|
println(s"basePath => ${basePath}\nconfigPath => ${configPath}")
|
||||||
|
/*
|
||||||
object ErrorUtils {
|
object ErrorUtils {
|
||||||
def errorMessageInJson(message: String, solution: String) : JObject = JObject(
|
def errorMessageInJson(message: String, solution: String) : JObject = JObject(
|
||||||
List(
|
List(
|
||||||
@ -91,7 +91,7 @@ object RouterLauncherApp extends App {
|
|||||||
if (!new File(basePath).exists()) ErrorUtils.printErrorAndExit("I2P Base path don't exist", "Reinstall the Browser Bundle")
|
if (!new File(basePath).exists()) ErrorUtils.printErrorAndExit("I2P Base path don't exist", "Reinstall the Browser Bundle")
|
||||||
if (!new File(configPath).exists()) ErrorUtils.printErrorAndExit("I2P Config path don't exist", "Delete your config directory for the Browser Bundle")
|
if (!new File(configPath).exists()) ErrorUtils.printErrorAndExit("I2P Config path don't exist", "Delete your config directory for the Browser Bundle")
|
||||||
|
|
||||||
|
*/
|
||||||
val deployer = new DeployProfile(configPath,basePath)
|
val deployer = new DeployProfile(configPath,basePath)
|
||||||
deployer.verifyExistenceOfConfig()
|
deployer.verifyExistenceOfConfig()
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ lazy val browserbundle = (project in file("browserbundle"))
|
|||||||
lazy val macosx = (project in file("macosx"))
|
lazy val macosx = (project in file("macosx"))
|
||||||
.settings(
|
.settings(
|
||||||
commonSettings,
|
commonSettings,
|
||||||
name := "RouterPack.jar",
|
name := "routerLauncher",
|
||||||
mainClass in assembly := Some("net.i2p.launchers.osx.LauncherAppMain")
|
mainClass in assembly := Some("net.i2p.launchers.SimpleOSXLauncher")
|
||||||
).dependsOn(common)
|
).dependsOn(common)
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,21 +21,23 @@ resourceDirectory in Compile := baseDirectory.value / ".." / ".." / "installer"
|
|||||||
// Unmanaged base will be included in a fat jar
|
// Unmanaged base will be included in a fat jar
|
||||||
unmanagedBase in Compile := baseDirectory.value / ".." / ".." / "pkg-temp" / "lib"
|
unmanagedBase in Compile := baseDirectory.value / ".." / ".." / "pkg-temp" / "lib"
|
||||||
|
|
||||||
|
|
||||||
// Unmanaged classpath will be available at compile time
|
// Unmanaged classpath will be available at compile time
|
||||||
unmanagedClasspath in Compile ++= Seq(
|
unmanagedClasspath in Compile ++= Seq(
|
||||||
baseDirectory.value / ".." / ".." / "pkg-temp" / "lib" / "*.jar"
|
baseDirectory.value / ".." / ".." / "pkg-temp" / "lib" / "*.jar"
|
||||||
)
|
)
|
||||||
|
|
||||||
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false, includeDependency = false)
|
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false, includeDependency = false)
|
||||||
|
|
||||||
|
|
||||||
assemblyJarName in assembly := s"launcher.jar"
|
|
||||||
|
|
||||||
assemblyExcludedJars in assembly := {
|
assemblyExcludedJars in assembly := {
|
||||||
val cp = (fullClasspath in assembly).value
|
val cp = (fullClasspath in assembly).value
|
||||||
cp filter { c => jarsForCopy.toList.contains(c.data.getName) }
|
cp filter { c => jarsForCopy.toList.contains(c.data.getName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
assemblyJarName in assembly := s"package.jar"
|
||||||
|
|
||||||
// TODO: MEEH: Add assemblyExcludedJars and load the router from own jar files, to handle upgrades better.
|
// 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.
|
// In fact, most likely the bundle never would need an update except for the router jars/wars.
|
||||||
|
|
||||||
@ -104,3 +106,4 @@ buildAppBundleTask := {
|
|||||||
println(s"Zip placed into bundle :)")
|
println(s"Zip placed into bundle :)")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
@ -9,9 +9,45 @@
|
|||||||
|
|
||||||
#include "StatusItemButton.h"
|
#include "StatusItemButton.h"
|
||||||
#include "JavaHelper.h"
|
#include "JavaHelper.h"
|
||||||
|
#include "RouterTask.h"
|
||||||
|
#include "neither/maybe.hpp"
|
||||||
|
#include "optional.hpp"
|
||||||
|
#include "subprocess.hpp"
|
||||||
|
#include <glob.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace neither;
|
||||||
|
|
||||||
extern JvmListSharedPtr gRawJvmList;
|
extern JvmListSharedPtr gRawJvmList;
|
||||||
|
|
||||||
|
// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
|
||||||
|
maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
|
||||||
|
|
||||||
|
maybeAnRouterRunner getGlobalRouterObject()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
|
||||||
|
return globalRouterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGlobalRouterObject(RouterTask* newRouter)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
|
||||||
|
globalRouterStatus.emplace(newRouter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string> globVector(const std::string& pattern){
|
||||||
|
glob_t glob_result;
|
||||||
|
glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
|
||||||
|
std::vector<std::string> files;
|
||||||
|
for(unsigned int i=0;i<glob_result.gl_pathc;++i){
|
||||||
|
files.push_back(std::string(glob_result.gl_pathv[i]));
|
||||||
|
}
|
||||||
|
globfree(&glob_result);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
@interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate>
|
@interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate>
|
||||||
@property BOOL enableLogging;
|
@property BOOL enableLogging;
|
||||||
@property BOOL enableVerboseLogging;
|
@property BOOL enableVerboseLogging;
|
||||||
@ -55,6 +91,8 @@ extern JvmListSharedPtr gRawJvmList;
|
|||||||
- (void)userChooseJavaHome;
|
- (void)userChooseJavaHome;
|
||||||
- (AppDelegate *)initWithArgc:(int)argc argv:(const char **)argv;
|
- (AppDelegate *)initWithArgc:(int)argc argv:(const char **)argv;
|
||||||
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList;
|
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList;
|
||||||
|
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
|
||||||
|
shouldPresentNotification:(NSUserNotification *)notification;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
<string>I2P</string>
|
<string>I2P</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.0.1</string>
|
<string>0.0.1</string>
|
||||||
|
<key>NSUserNotificationAlertStyle</key>
|
||||||
|
<string>alert</string>
|
||||||
<key>NSAppleScriptEnabled</key>
|
<key>NSAppleScriptEnabled</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CGDisableCoalescedUpdates</key>
|
<key>CGDisableCoalescedUpdates</key>
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <experimental/optional>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <Foundation/Foundation.h>
|
#include <Foundation/Foundation.h>
|
||||||
@ -18,10 +17,19 @@
|
|||||||
#include <CoreFoundation/CFArray.h>
|
#include <CoreFoundation/CFArray.h>
|
||||||
#include <CoreFoundation/CFString.h>
|
#include <CoreFoundation/CFString.h>
|
||||||
|
|
||||||
|
#include "optional.hpp"
|
||||||
#include "strutil.hpp"
|
#include "strutil.hpp"
|
||||||
#include "subprocess.hpp"
|
#include "subprocess.hpp"
|
||||||
|
#include "neither/maybe.hpp"
|
||||||
|
#include "RouterTask.h"
|
||||||
|
|
||||||
using namespace subprocess;
|
using namespace subprocess;
|
||||||
|
using namespace neither;
|
||||||
|
|
||||||
|
using maybeAnRouterRunner = std::experimental::optional<RouterTask*>;
|
||||||
|
|
||||||
|
extern std::mutex globalRouterStatusMutex;
|
||||||
|
extern maybeAnRouterRunner globalRouterStatus;
|
||||||
|
|
||||||
|
|
||||||
#define DEF_MIN_JVM_VER "1.7+"
|
#define DEF_MIN_JVM_VER "1.7+"
|
||||||
@ -133,7 +141,7 @@ static void processJvmPlistEntries (const void* item, void* context) {
|
|||||||
auto d = extractString((CFStringRef)value);
|
auto d = extractString((CFStringRef)value);
|
||||||
currentJvm->JVMPlatformVersion = trim_copy(d);
|
currentJvm->JVMPlatformVersion = trim_copy(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -150,7 +158,7 @@ static void listAllJavaInstallsAvailable()
|
|||||||
{
|
{
|
||||||
auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"});
|
auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"});
|
||||||
CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data()));
|
CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data()));
|
||||||
|
|
||||||
//CFErrorRef err;
|
//CFErrorRef err;
|
||||||
CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL);
|
CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL);
|
||||||
/*if (err)
|
/*if (err)
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
#include "JavaRunner.h"
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
javaProcess = std::shared_ptr<Popen>(new Popen({javaBin.c_str(), "-version"}, defer_spawn{true}));
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<std::future<int> > JavaRunner::execute()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
|
|
||||||
this->executingFn(this);
|
|
||||||
});
|
|
||||||
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), executingFn);
|
|
||||||
dispatch_block_wait(executingFn, DISPATCH_TIME_FOREVER);
|
|
||||||
|
|
||||||
// Here, the process is done executing.
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
struct CRouterState
|
|
||||||
{
|
|
||||||
enum State {
|
|
||||||
C_STOPPED = 0,
|
|
||||||
C_STARTED,
|
|
||||||
C_RUNNING
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::function<void(void)> fp_t;
|
|
||||||
typedef std::function<void(JavaRunner *ptr)> fp_proc_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* class JavaRunner
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
class JavaRunner
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// copy fn
|
|
||||||
JavaRunner(std::string javaBin, const fp_proc_t& executingFn, const fp_t& cb);
|
|
||||||
~JavaRunner() = default;
|
|
||||||
|
|
||||||
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:
|
|
||||||
const fp_proc_t& executingFn;
|
|
||||||
const fp_t& exitCallbackFn;
|
|
||||||
};
|
|
||||||
|
|
75
launchers/macosx/obj-cpp/RouterTask.h
Normal file
75
launchers/macosx/obj-cpp/RouterTask.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Cocoa/Cocoa.h>
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#include "optional.hpp"
|
||||||
|
#include "subprocess.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
@class RTaskOptions;
|
||||||
|
|
||||||
|
@interface RTaskOptions : NSObject
|
||||||
|
@property (strong) NSString* binPath;
|
||||||
|
@property (strong) NSArray<NSString *>* arguments;
|
||||||
|
@property (strong) NSString* i2pBaseDir;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@class RouterTask;
|
||||||
|
|
||||||
|
@interface RouterTask : NSObject
|
||||||
|
@property (strong) NSTask* routerTask;
|
||||||
|
@property (strong) NSUserDefaults *userPreferences;
|
||||||
|
@property (strong) NSFileHandle *readLogHandle;
|
||||||
|
@property (strong) NSMutableData *totalLogData;
|
||||||
|
@property (strong) NSPipe *processPipe;
|
||||||
|
@property (strong) NSFileHandle *input;
|
||||||
|
- (instancetype) initWithOptions : (RTaskOptions*) options;
|
||||||
|
- (int) execute;
|
||||||
|
- (int) getPID;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using namespace subprocess;
|
||||||
|
|
||||||
|
class JavaRunner;
|
||||||
|
|
||||||
|
typedef std::function<void(void)> fp_t;
|
||||||
|
typedef std::function<void(JavaRunner *ptr)> fp_proc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* class JavaRunner
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
class JavaRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// copy fn
|
||||||
|
JavaRunner(std::string& javaBin, std::string& arguments, std::string& i2pBaseDir, const fp_proc_t& executingFn, const fp_t& cb);
|
||||||
|
~JavaRunner() = default;
|
||||||
|
|
||||||
|
static const std::vector<NSString*> defaultStartupFlags;
|
||||||
|
static const std::vector<std::string> defaultFlagsForExtractorJob;
|
||||||
|
|
||||||
|
void requestRouterShutdown();
|
||||||
|
|
||||||
|
std::experimental::optional<std::future<int> > execute();
|
||||||
|
std::shared_ptr<Popen> javaProcess;
|
||||||
|
std::string javaBinaryPath;
|
||||||
|
std::string javaRouterArgs;
|
||||||
|
std::string execLine;
|
||||||
|
std::string _i2pBaseDir;
|
||||||
|
private:
|
||||||
|
const fp_proc_t& executingFn;
|
||||||
|
const fp_t& exitCallbackFn;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
141
launchers/macosx/obj-cpp/RouterTask.mm
Normal file
141
launchers/macosx/obj-cpp/RouterTask.mm
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#include "RouterTask.h"
|
||||||
|
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
#include <future>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "optional.hpp"
|
||||||
|
#include "subprocess.hpp"
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
@implementation RTaskOptions
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RouterTask
|
||||||
|
|
||||||
|
- (instancetype) initWithOptions : (RTaskOptions*) options
|
||||||
|
{
|
||||||
|
self.input = [NSFileHandle fileHandleWithStandardInput];
|
||||||
|
self.routerTask = [NSTask new];
|
||||||
|
self.processPipe = [NSPipe new];
|
||||||
|
[self.routerTask setLaunchPath:options.binPath];
|
||||||
|
[self.routerTask setArguments:options.arguments];
|
||||||
|
NSDictionary *envDict = @{
|
||||||
|
@"I2PBASE": options.i2pBaseDir
|
||||||
|
};
|
||||||
|
[self.routerTask setEnvironment: envDict];
|
||||||
|
[self.routerTask setStandardOutput:self.processPipe];
|
||||||
|
[self.routerTask setStandardError:self.processPipe];
|
||||||
|
/*
|
||||||
|
self.readLogHandle = [self.processPipe fileHandleForReading];
|
||||||
|
NSData *inData = nil;
|
||||||
|
self.totalLogData = [[[NSMutableData alloc] init] autorelease];
|
||||||
|
|
||||||
|
while ((inData = [self.readLogHandle availableData]) &&
|
||||||
|
[inData length]) {
|
||||||
|
[self.totalLogData appendData:inData];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) execute
|
||||||
|
{
|
||||||
|
//@try {
|
||||||
|
[self.routerTask launch];
|
||||||
|
[self.input waitForDataInBackgroundAndNotify];
|
||||||
|
[[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
|
||||||
|
object:[self.processPipe fileHandleForReading] queue:nil
|
||||||
|
usingBlock:^(NSNotification *note)
|
||||||
|
{
|
||||||
|
// Read from shell output
|
||||||
|
NSData *outData = [[self.processPipe fileHandleForReading] availableData];
|
||||||
|
NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
|
||||||
|
if ([outStr length] > 1) {
|
||||||
|
NSLog(@"output: %@", outStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue waiting for shell output.
|
||||||
|
[[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||||
|
}];
|
||||||
|
//[self.routerTask waitUntilExit];
|
||||||
|
//NSThread *thr = [[NSThread alloc] initWithTarget:self.routerTask selector:@selector(launch) object:nil];
|
||||||
|
//[self.routerTask waitUntilExit];
|
||||||
|
return 1;
|
||||||
|
/*}
|
||||||
|
@catch (NSException *e)
|
||||||
|
{
|
||||||
|
NSLog(@"Expection occurred %@", [e reason]);
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getPID
|
||||||
|
{
|
||||||
|
return [self.routerTask processIdentifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using namespace subprocess;
|
||||||
|
|
||||||
|
std::mutex globalRouterStatusMutex;
|
||||||
|
|
||||||
|
const std::vector<NSString*> JavaRunner::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"
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<std::string> JavaRunner::defaultFlagsForExtractorJob {
|
||||||
|
"-Xmx512M",
|
||||||
|
"-Xms128m",
|
||||||
|
"-Djava.awt.headless=true"
|
||||||
|
};
|
||||||
|
|
||||||
|
JavaRunner::JavaRunner(std::string& javaBin, std::string& arguments, std::string& i2pBaseDir, const fp_proc_t& execFn, const fp_t& cb)
|
||||||
|
: javaBinaryPath(javaBin), javaRouterArgs(arguments), _i2pBaseDir(i2pBaseDir), executingFn(execFn), exitCallbackFn(cb)
|
||||||
|
{
|
||||||
|
execLine = javaBinaryPath;
|
||||||
|
execLine += " " + std::string(javaRouterArgs.c_str());
|
||||||
|
printf("CLI: %s\n",execLine.c_str());
|
||||||
|
javaProcess = std::shared_ptr<Popen>(new Popen(execLine, environment{{
|
||||||
|
{"I2PBASE", _i2pBaseDir},
|
||||||
|
{"JAVA_OPTS", getenv("JAVA_OPTS")}
|
||||||
|
}}, defer_spawn{true}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JavaRunner::requestRouterShutdown()
|
||||||
|
{
|
||||||
|
// SIGHUP
|
||||||
|
javaProcess->kill(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::experimental::optional<std::future<int> > JavaRunner::execute()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
|
||||||
|
this->executingFn(this);
|
||||||
|
});
|
||||||
|
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), executingFn);
|
||||||
|
dispatch_block_wait(executingFn, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
|
// Here, the process is done executing.
|
||||||
|
|
||||||
|
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 std::experimental::nullopt;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
cxx = clang++
|
cxx = clang++
|
||||||
cflags = -std=c++14 -g -Wall -I./include -I/usr/local/include -I/usr/include -Wno-unused-variable -mmacosx-version-min=10.10
|
cflags = -std=c++14 -g -Wall -I./include -I./include/neither -I/usr/local/include -I/usr/include -Wno-unused-variable -mmacosx-version-min=10.10
|
||||||
ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
|
ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +26,8 @@ rule cleanup
|
|||||||
rule bundledir
|
rule bundledir
|
||||||
command = mkdir -p I2PLauncher.app/Contents/{MacOS,Resources,Frameworks} $
|
command = mkdir -p I2PLauncher.app/Contents/{MacOS,Resources,Frameworks} $
|
||||||
&& cp Info.plist I2PLauncher.app/Contents/Info.plist $
|
&& cp Info.plist I2PLauncher.app/Contents/Info.plist $
|
||||||
&& cp base.zip I2PLauncher.app/Contents/Resources/base.zip
|
&& cp base.zip I2PLauncher.app/Contents/Resources/base.zip $
|
||||||
|
&& cp ../target/scala-2.11/routerLauncher-assembly-0.1.0-SNAPSHOT.jar I2PLauncher.app/Contents/Resources/launcher.jar
|
||||||
|
|
||||||
rule copytobundledir
|
rule copytobundledir
|
||||||
command = cp clauncher I2PLauncher.app/Contents/MacOS/I2PLauncher
|
command = cp clauncher I2PLauncher.app/Contents/MacOS/I2PLauncher
|
||||||
@ -39,14 +40,14 @@ rule builddir
|
|||||||
|
|
||||||
build main.o: cxx main.mm
|
build main.o: cxx main.mm
|
||||||
build StatusItemButton.o: cxx StatusItemButton.mm
|
build StatusItemButton.o: cxx StatusItemButton.mm
|
||||||
build JavaRunner.o: cxx JavaRunner.cpp
|
build RouterTask.o: cxx RouterTask.mm
|
||||||
|
|
||||||
build clean: cleanup
|
build clean: cleanup
|
||||||
|
|
||||||
build bundle: bundledir
|
build bundle: bundledir
|
||||||
build copytobundle: copytobundledir | bundle clauncher
|
build copytobundle: copytobundledir | bundle clauncher
|
||||||
|
|
||||||
build clauncher: link main.o StatusItemButton.o JavaRunner.o
|
build clauncher: link main.o StatusItemButton.o RouterTask.o
|
||||||
|
|
||||||
build appbundle: copyimgtobundle | clauncher bundle copytobundle
|
build appbundle: copyimgtobundle | clauncher bundle copytobundle
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <experimental/optional>
|
#include "optional.hpp"
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <CoreFoundation/CFArray.h>
|
#include <CoreFoundation/CFArray.h>
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <experimental/optional>
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <future>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@ -23,8 +26,10 @@
|
|||||||
|
|
||||||
#include "AppDelegate.h"
|
#include "AppDelegate.h"
|
||||||
#include "StatusItemButton.h"
|
#include "StatusItemButton.h"
|
||||||
#include "JavaRunner.h"
|
#include "RouterTask.h"
|
||||||
#include "JavaHelper.h"
|
#include "JavaHelper.h"
|
||||||
|
#include "fn.h"
|
||||||
|
#include "optional.hpp"
|
||||||
|
|
||||||
#define DEF_I2P_VERSION "0.9.35"
|
#define DEF_I2P_VERSION "0.9.35"
|
||||||
#define APPDOMAIN "net.i2p.launcher"
|
#define APPDOMAIN "net.i2p.launcher"
|
||||||
@ -43,6 +48,55 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) {
|
||||||
|
/*
|
||||||
|
NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);
|
||||||
|
auto launchLambda = [](JavaRunner *javaRun) {
|
||||||
|
javaRun->javaProcess->start_process();
|
||||||
|
auto pid = javaRun->javaProcess->pid();
|
||||||
|
std::cout << "I2P Router process id = " << pid << std::endl;
|
||||||
|
|
||||||
|
// Blocking
|
||||||
|
javaRun->javaProcess->wait();
|
||||||
|
};
|
||||||
|
auto callbackAfterExit = [](){
|
||||||
|
printf("Callback after exit\n");
|
||||||
|
};
|
||||||
|
NSLog(@"Still fine!");
|
||||||
|
|
||||||
|
setGlobalRouterObject(new JavaRunner{ javaBin, arguments, i2pBaseDir, std::move(launchLambda), std::move(callbackAfterExit) });
|
||||||
|
|
||||||
|
NSLog(@"Still fine!");
|
||||||
|
return std::async(std::launch::async, [&]{
|
||||||
|
getGlobalRouterObject().value()->execute();
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
CFShow(arguments);
|
||||||
|
|
||||||
|
@try {
|
||||||
|
RTaskOptions* options = [RTaskOptions alloc];
|
||||||
|
options.binPath = javaBin;
|
||||||
|
options.arguments = arguments;
|
||||||
|
options.i2pBaseDir = i2pBaseDir;
|
||||||
|
auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
|
||||||
|
//auto pid = [instance execute];
|
||||||
|
//NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
|
||||||
|
[instance execute];
|
||||||
|
return std::async(std::launch::async, [&instance]{
|
||||||
|
return 1;//[instance getPID];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@catch (NSException *e)
|
||||||
|
{
|
||||||
|
NSLog(@"Expection occurred %@", [e reason]);
|
||||||
|
return std::async(std::launch::async, [&]{
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@implementation MenuBarCtrl
|
@implementation MenuBarCtrl
|
||||||
|
|
||||||
- (void) statusItemButtonLeftClick: (StatusItemButton *) button
|
- (void) statusItemButtonLeftClick: (StatusItemButton *) button
|
||||||
@ -82,6 +136,11 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
{
|
{
|
||||||
NSLog(@"Clicked stopJavaRouterBtnHandler");
|
NSLog(@"Clicked stopJavaRouterBtnHandler");
|
||||||
|
if (getGlobalRouterObject().has_value())
|
||||||
|
{
|
||||||
|
//getGlobalRouterObject().value()->requestRouterShutdown();
|
||||||
|
NSLog(@"Requested shutdown");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem
|
- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem
|
||||||
@ -172,6 +231,11 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
|
||||||
|
shouldPresentNotification:(NSUserNotification *)notification {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList
|
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList
|
||||||
{
|
{
|
||||||
NSString *appleScriptString = @"set jvmlist to {\"Newest\"";
|
NSString *appleScriptString = @"set jvmlist to {\"Newest\"";
|
||||||
@ -224,13 +288,14 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
CFPreferencesSetMultiple((CFDictionaryRef)dict, NULL, CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
CFPreferencesSetMultiple((CFDictionaryRef)dict, NULL, CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||||
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
|
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
|
||||||
//CFPreferencesSetAppValue(@"javaHome", (CFPropertyListRef)cfDefaultHome, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
//CFPreferencesSetAppValue(@"javaHome", (CFPropertyListRef)cfDefaultHome, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||||
|
|
||||||
if (self.enableVerboseLogging) NSLog(@"Default preferences stored!");
|
if (self.enableVerboseLogging) NSLog(@"Default preferences stored!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
// Init application here
|
// Init application here
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
|
||||||
// Start with user preferences
|
// Start with user preferences
|
||||||
self.userPreferences = [NSUserDefaults standardUserDefaults];
|
self.userPreferences = [NSUserDefaults standardUserDefaults];
|
||||||
[self setApplicationDefaultPreferences];
|
[self setApplicationDefaultPreferences];
|
||||||
@ -246,7 +311,6 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"];
|
auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"];
|
||||||
if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref);
|
if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref);
|
||||||
|
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
|
|
||||||
|
|
||||||
// This is the only GUI the user experience on a regular basis.
|
// This is the only GUI the user experience on a regular basis.
|
||||||
self.menuBarCtrl = [[MenuBarCtrl alloc] init];
|
self.menuBarCtrl = [[MenuBarCtrl alloc] init];
|
||||||
@ -255,6 +319,16 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
if (self.enableVerboseLogging) NSLog(@"Appdomain is: %@", appDomain);
|
if (self.enableVerboseLogging) NSLog(@"Appdomain is: %@", appDomain);
|
||||||
|
|
||||||
NSLog(@"We should have started the statusbar object by now...");
|
NSLog(@"We should have started the statusbar object by now...");
|
||||||
|
|
||||||
|
// Figure out base directory
|
||||||
|
const char* pathFromHome = "/Users/%s/Library/I2P";
|
||||||
|
auto username = getenv("USER");
|
||||||
|
char buffer[strlen(pathFromHome)+strlen(username)];
|
||||||
|
sprintf(buffer, pathFromHome, username);
|
||||||
|
std::string i2pBaseDir(buffer);
|
||||||
|
if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer);
|
||||||
|
|
||||||
|
|
||||||
//[statusBarButton setAction:@selector(itemClicked:)];
|
//[statusBarButton setAction:@selector(itemClicked:)];
|
||||||
//dispatch_async(dispatch_get_main_queue(), ^{
|
//dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
//});
|
//});
|
||||||
@ -273,33 +347,121 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
return std::string([val UTF8String]);;
|
return std::string([val UTF8String]);;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto getJavaBin = [&getJavaHomeLambda]() -> std::string {
|
||||||
auto launchLambda = [&pref](JavaRunner *javaRun) {
|
// Get Java home
|
||||||
javaRun->javaProcess->start_process();
|
|
||||||
auto pid = javaRun->javaProcess->pid();
|
|
||||||
std::cout << "I2P Router process id = " << pid << std::endl;
|
|
||||||
|
|
||||||
// Blocking
|
|
||||||
javaRun->javaProcess->wait();
|
|
||||||
};
|
|
||||||
auto callbackAfterExit = [=](){
|
|
||||||
printf("Callback after exit\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Get Java home
|
|
||||||
auto javaHome = getJavaHomeLambda();
|
auto javaHome = getJavaHomeLambda();
|
||||||
trim(javaHome); // Trim to remove endline
|
trim(javaHome); // Trim to remove endline
|
||||||
auto javaBin = std::string(javaHome);
|
auto javaBin = std::string(javaHome);
|
||||||
javaBin += "/bin/java"; // Append java binary to path.
|
javaBin += "/bin/java"; // Append java binary to path.
|
||||||
//printf("hello world: %s\n", javaBin.c_str());
|
return javaBin;
|
||||||
if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
|
};
|
||||||
|
|
||||||
auto r = new JavaRunner{ javaBin, launchLambda, callbackAfterExit };
|
auto buildClassPath = [](std::string basePath) -> std::vector<std::string> {
|
||||||
r->execute();
|
return globVector(basePath+std::string("/lib/*.jar"));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto sendUserNotification = [&](NSString* title, NSString* informativeText) -> void {
|
||||||
|
NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
|
||||||
|
|
||||||
|
userNotification.title = title;
|
||||||
|
userNotification.informativeText = informativeText;
|
||||||
|
userNotification.soundName = NSUserNotificationDefaultSoundName;
|
||||||
|
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Get paths
|
||||||
|
NSBundle *launcherBundle = [NSBundle mainBundle];
|
||||||
|
|
||||||
|
std::string basearg("-Di2p.dir.base=");
|
||||||
|
basearg += i2pBaseDir;
|
||||||
|
|
||||||
|
std::string zippath("-Di2p.base.zip=");
|
||||||
|
zippath += [[launcherBundle pathForResource:@"base" ofType:@"zip"] UTF8String];
|
||||||
|
|
||||||
|
std::string jarfile("-cp ");
|
||||||
|
jarfile += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
|
||||||
|
|
||||||
|
struct stat sb;
|
||||||
|
if ( !(stat(buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) )
|
||||||
|
{
|
||||||
|
// I2P is not extracted.
|
||||||
|
if (self.enableVerboseLogging) printf("I2P Directory don't exists!\n");
|
||||||
|
|
||||||
|
// Create directory
|
||||||
|
mkdir(buffer, S_IRUSR | S_IWUSR | S_IXUSR);
|
||||||
|
|
||||||
|
auto cli = JavaRunner::defaultFlagsForExtractorJob;
|
||||||
|
setenv("I2PBASE", buffer, true);
|
||||||
|
setenv("ZIPPATH", zippath.c_str(), true);
|
||||||
|
//setenv("DYLD_LIBRARY_PATH",".:/usr/lib:/lib:/usr/local/lib", true);
|
||||||
|
|
||||||
|
cli.push_back(basearg);
|
||||||
|
cli.push_back(zippath);
|
||||||
|
cli.push_back(jarfile);
|
||||||
|
cli.push_back("net.i2p.launchers.BaseExtractor");
|
||||||
|
|
||||||
|
//auto charCli = map(cli, [](std::string str){ return str.c_str(); });
|
||||||
|
std::string execStr = getJavaBin();
|
||||||
|
for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
|
||||||
|
|
||||||
|
printf("\n\nTrying cmd: %s\n\n", execStr.c_str());
|
||||||
|
try {
|
||||||
|
sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Please hold on while we extract I2P. You'll get a new message once done!"));
|
||||||
|
int extractStatus = Popen(execStr.c_str(), environment{{
|
||||||
|
{"ZIPPATH", zippath.c_str()},
|
||||||
|
{"I2PBASE", buffer}
|
||||||
|
}}).wait();
|
||||||
|
printf("Extraction exit code %d\n",extractStatus);
|
||||||
|
sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Extraction complete!"));
|
||||||
|
} catch (subprocess::OSError &err) {
|
||||||
|
printf("Something bad happened: %s\n", err.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (self.enableVerboseLogging) printf("I2P directory found!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect base to be extracted by now.
|
||||||
|
|
||||||
|
auto jarList = buildClassPath(std::string(buffer));
|
||||||
|
std::string classpathStrHead = "-classpath";
|
||||||
|
std::string classpathStr = "";
|
||||||
|
classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
|
||||||
|
std::string prefix(i2pBaseDir);
|
||||||
|
prefix += "/lib/";
|
||||||
|
for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
|
||||||
|
//if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto argList = JavaRunner::defaultStartupFlags;
|
||||||
|
|
||||||
|
std::string baseDirArg("-Di2p.dir.base=");
|
||||||
|
baseDirArg += i2pBaseDir;
|
||||||
|
std::string javaLibArg("-Djava.library.path=");
|
||||||
|
javaLibArg += i2pBaseDir;
|
||||||
|
// TODO: pass this to JVM
|
||||||
|
auto java_opts = getenv("JAVA_OPTS");
|
||||||
|
|
||||||
|
argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
|
||||||
|
argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
|
||||||
|
argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
|
||||||
|
argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
|
||||||
|
argList.push_back(@"net.i2p.router.Router");
|
||||||
|
auto javaBin = getJavaBin();
|
||||||
|
|
||||||
|
|
||||||
|
sendUserNotification(@"I2P Launcher", @"I2P Router is starting up!");
|
||||||
|
auto nsJavaBin = [NSString stringWithUTF8String:javaBin.c_str()];
|
||||||
|
auto nsBasePath = [NSString stringWithUTF8String:i2pBaseDir.c_str()];
|
||||||
|
NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
|
||||||
|
startupRouter(nsJavaBin, arrArguments, nsBasePath);
|
||||||
|
//if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
|
||||||
} catch (std::exception &err) {
|
} catch (std::exception &err) {
|
||||||
std::cerr << "Exception: " << err.what() << std::endl;
|
std::cerr << "Exception: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,45 +21,56 @@ import java.util.zip.ZipFile;
|
|||||||
*/
|
*/
|
||||||
public class BaseExtractor extends EnvCheck {
|
public class BaseExtractor extends EnvCheck {
|
||||||
|
|
||||||
private void runExtract(String zipFilename, String destinationPath) {
|
public boolean printDebug = false;
|
||||||
|
|
||||||
|
public void runExtract(String zipFilename) {
|
||||||
|
String destinationPath = this.baseDirPath;
|
||||||
try(ZipFile file = new ZipFile(zipFilename)) {
|
try(ZipFile file = new ZipFile(zipFilename)) {
|
||||||
FileSystem fileSystem = FileSystems.getDefault();
|
FileSystem fileSystem = FileSystems.getDefault();
|
||||||
Enumeration<? extends ZipEntry> entries = file.entries();
|
Enumeration<? extends ZipEntry> entries = file.entries();
|
||||||
Files.createDirectory(fileSystem.getPath(destinationPath));
|
|
||||||
|
try {
|
||||||
|
Files.createDirectory(fileSystem.getPath(destinationPath));
|
||||||
|
} catch (IOException e) {
|
||||||
|
// It's OK to fail here.
|
||||||
|
}
|
||||||
|
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
ZipEntry entry = entries.nextElement();
|
ZipEntry entry = entries.nextElement();
|
||||||
|
if (printDebug) System.out.println("Found entry: "+entry.toString());
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
System.out.println("Creating Directory:" + destinationPath + entry.getName());
|
if (printDebug) System.out.println("Creating Directory:" + destinationPath + "/" + entry.getName());
|
||||||
Files.createDirectories(fileSystem.getPath(destinationPath + entry.getName()));
|
Files.createDirectories(fileSystem.getPath(destinationPath + "/" + entry.getName()));
|
||||||
} else {
|
} else {
|
||||||
InputStream is = file.getInputStream(entry);
|
InputStream is = file.getInputStream(entry);
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
String uncompressedFileName = destinationPath + entry.getName();
|
String uncompressedFileName = destinationPath + "/" + entry.getName();
|
||||||
Path uncompressedFilePath = fileSystem.getPath(uncompressedFileName);
|
Path uncompressedFilePath = fileSystem.getPath(uncompressedFileName);
|
||||||
Files.createFile(uncompressedFilePath);
|
Files.createFile(uncompressedFilePath);
|
||||||
FileOutputStream fileOutput = new FileOutputStream(uncompressedFileName);
|
FileOutputStream fileOutput = new FileOutputStream(uncompressedFileName);
|
||||||
while (bis.available() > 0) fileOutput.write(bis.read());
|
while (bis.available() > 0) fileOutput.write(bis.read());
|
||||||
fileOutput.close();
|
fileOutput.close();
|
||||||
System.out.println("Written :" + entry.getName());
|
if (printDebug) System.out.println("Written :" + entry.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//
|
//
|
||||||
|
System.err.println("Exception in extractor!");
|
||||||
|
System.err.println(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseExtractor(String[] args) {
|
public BaseExtractor(String[] args) {
|
||||||
super(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) {
|
public static void main(String[] args) {
|
||||||
new BaseExtractor(args);
|
System.out.println("Starting extraction");
|
||||||
|
BaseExtractor be = new BaseExtractor(args);
|
||||||
|
String debug = System.getProperty("print.debug");
|
||||||
|
if (debug != null) {
|
||||||
|
be.printDebug = true;
|
||||||
|
}
|
||||||
|
be.runExtract(System.getProperty("i2p.base.zip"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user