Changeset 6d0f80f for launchers/macosx


Ignore:
Timestamp:
Jul 13, 2018 6:30:16 AM (2 years ago)
Author:
meeh <meeh@…>
Branches:
master
Children:
818e70d
Parents:
21b3864
Message:

Fixed a load of issues related to my "sync" approach, and Mac OSX's "async" API.

Location:
launchers/macosx
Files:
2 added
2 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • launchers/macosx/build.sbt

    r21b3864 r6d0f80f  
    2222unmanagedBase in Compile := baseDirectory.value / ".." / ".." / "pkg-temp" / "lib"
    2323
     24
    2425// Unmanaged classpath will be available at compile time
    2526unmanagedClasspath in Compile ++= Seq(
    26   baseDirectory.value / ".." / ".." / "pkg-temp" / "lib" / "*.jar"
     27    baseDirectory.value / ".." / ".." / "pkg-temp" / "lib" / "*.jar"
    2728)
    2829
    2930assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false, includeDependency = false)
    3031
     32assemblyExcludedJars in assembly := {
     33    val cp = (fullClasspath in assembly).value
     34    cp filter { c => jarsForCopy.toList.contains(c.data.getName) }
     35}
    3136
    32 assemblyJarName in assembly := s"launcher.jar"
     37/*
    3338
    34 assemblyExcludedJars in assembly := {
    35   val cp = (fullClasspath in assembly).value
    36   cp filter { c => jarsForCopy.toList.contains(c.data.getName) }
    37 }
     39assemblyJarName in assembly := s"package.jar"
    3840
    3941// TODO: MEEH: Add assemblyExcludedJars and load the router from own jar files, to handle upgrades better.
     
    105107
    106108}
     109*/
  • launchers/macosx/obj-cpp/AppDelegate.h

    r21b3864 r6d0f80f  
    1010#include "StatusItemButton.h"
    1111#include "JavaHelper.h"
     12#include "RouterTask.h"
     13#include "neither/maybe.hpp"
     14#include "optional.hpp"
     15#include "subprocess.hpp"
     16#include <glob.h>
     17#include <vector>
     18
     19using namespace neither;
    1220
    1321extern JvmListSharedPtr gRawJvmList;
     22
     23// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
     24maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
     25
     26maybeAnRouterRunner getGlobalRouterObject()
     27{
     28    std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
     29    return globalRouterStatus;
     30}
     31
     32void setGlobalRouterObject(RouterTask* newRouter)
     33{
     34    std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
     35    globalRouterStatus.emplace(newRouter);
     36}
     37
     38
     39
     40std::vector<std::string> globVector(const std::string& pattern){
     41    glob_t glob_result;
     42    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
     43    std::vector<std::string> files;
     44    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
     45        files.push_back(std::string(glob_result.gl_pathv[i]));
     46    }
     47    globfree(&glob_result);
     48    return files;
     49}
    1450
    1551@interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate>
     
    5692- (AppDelegate *)initWithArgc:(int)argc argv:(const char **)argv;
    5793- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList;
     94- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
     95                               shouldPresentNotification:(NSUserNotification *)notification;
    5896@end
    5997
  • launchers/macosx/obj-cpp/Info.plist

    r21b3864 r6d0f80f  
    2727        <key>CFBundleVersion</key>
    2828        <string>0.0.1</string>
     29    <key>NSUserNotificationAlertStyle</key>
     30    <string>alert</string>
    2931        <key>NSAppleScriptEnabled</key>
    3032        <true/>
  • launchers/macosx/obj-cpp/JavaHelper.h

    r21b3864 r6d0f80f  
    88#include <sstream>
    99#include <list>
    10 #include <experimental/optional>
    1110#include <stdlib.h>
    1211
     
    1918#include <CoreFoundation/CFString.h>
    2019
     20#include "optional.hpp"
    2121#include "strutil.hpp"
    2222#include "subprocess.hpp"
     23#include "neither/maybe.hpp"
     24#include "RouterTask.h"
    2325
    2426using namespace subprocess;
     27using namespace neither;
     28
     29using maybeAnRouterRunner = std::experimental::optional<RouterTask*>;
     30
     31extern std::mutex globalRouterStatusMutex;
     32extern maybeAnRouterRunner globalRouterStatus;
    2533
    2634
     
    134142        currentJvm->JVMPlatformVersion = trim_copy(d);
    135143      }
    136      
     144
    137145    }
    138146  };
     
    151159  auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"});
    152160  CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data()));
    153  
     161
    154162  //CFErrorRef err;
    155163  CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL);
  • launchers/macosx/obj-cpp/build.ninja

    r21b3864 r6d0f80f  
    11cxx = clang++
    2 cflags = -std=c++14 -g -Wall -I./include -I/usr/local/include -I/usr/include -Wno-unused-variable -mmacosx-version-min=10.10
     2cflags = -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
    33ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
    44
     
    2727  command = mkdir -p I2PLauncher.app/Contents/{MacOS,Resources,Frameworks} $
    2828    && cp Info.plist I2PLauncher.app/Contents/Info.plist $
    29     && cp base.zip I2PLauncher.app/Contents/Resources/base.zip
     29    && cp base.zip I2PLauncher.app/Contents/Resources/base.zip $
     30    && cp ../target/scala-2.11/routerLauncher-assembly-0.1.0-SNAPSHOT.jar I2PLauncher.app/Contents/Resources/launcher.jar
    3031
    3132rule copytobundledir
     
    4041build main.o: cxx main.mm
    4142build StatusItemButton.o: cxx StatusItemButton.mm
    42 build JavaRunner.o: cxx JavaRunner.cpp
     43build RouterTask.o: cxx RouterTask.mm
    4344
    4445build clean: cleanup
     
    4748build copytobundle: copytobundledir | bundle clauncher
    4849
    49 build clauncher: link main.o StatusItemButton.o JavaRunner.o
     50build clauncher: link main.o StatusItemButton.o RouterTask.o
    5051
    5152build appbundle: copyimgtobundle | clauncher bundle copytobundle
  • launchers/macosx/obj-cpp/include/strutil.hpp

    r21b3864 r6d0f80f  
    99#include <cctype>
    1010#include <locale>
    11 #include <experimental/optional>
     11#include "optional.hpp"
    1212
    1313#include <CoreFoundation/CoreFoundation.h>
  • launchers/macosx/obj-cpp/main.mm

    r21b3864 r6d0f80f  
    55#include <string>
    66#include <list>
    7 #include <experimental/optional>
     7#include <sys/stat.h>
     8#include <stdlib.h>
     9#include <future>
     10#include <vector>
    811
    912#import <Foundation/Foundation.h>
     
    2427#include "AppDelegate.h"
    2528#include "StatusItemButton.h"
    26 #include "JavaRunner.h"
     29#include "RouterTask.h"
    2730#include "JavaHelper.h"
     31#include "fn.h"
     32#include "optional.hpp"
    2833
    2934#define DEF_I2P_VERSION "0.9.35"
     
    4449
    4550
     51std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) {
     52/*
     53  NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);
     54  auto launchLambda = [](JavaRunner *javaRun) {
     55    javaRun->javaProcess->start_process();
     56    auto pid = javaRun->javaProcess->pid();
     57    std::cout << "I2P Router process id = " << pid << std::endl;
     58
     59    // Blocking
     60    javaRun->javaProcess->wait();
     61  };
     62  auto callbackAfterExit = [](){
     63    printf("Callback after exit\n");
     64  };
     65  NSLog(@"Still fine!");
     66
     67  setGlobalRouterObject(new JavaRunner{ javaBin, arguments, i2pBaseDir, std::move(launchLambda), std::move(callbackAfterExit) });
     68
     69  NSLog(@"Still fine!");
     70  return std::async(std::launch::async, [&]{
     71      getGlobalRouterObject().value()->execute();
     72      return 0;
     73    });
     74*/
     75    CFShow(arguments);
     76
     77    @try {
     78        RTaskOptions* options = [RTaskOptions alloc];
     79        options.binPath = javaBin;
     80        options.arguments = arguments;
     81        options.i2pBaseDir = i2pBaseDir;
     82        auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
     83        //auto pid = [instance execute];
     84        //NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
     85        [instance execute];
     86        return std::async(std::launch::async, [&instance]{
     87          return 1;//[instance getPID];
     88        });
     89    }
     90    @catch (NSException *e)
     91        {
     92                NSLog(@"Expection occurred %@", [e reason]);
     93        return std::async(std::launch::async, [&]{
     94          return 0;
     95        });
     96        }
     97}
     98
     99
    46100@implementation MenuBarCtrl
    47101
     
    83137{
    84138  NSLog(@"Clicked stopJavaRouterBtnHandler");
     139  if (getGlobalRouterObject().has_value())
     140  {
     141      //getGlobalRouterObject().value()->requestRouterShutdown();
     142      NSLog(@"Requested shutdown");
     143  }
    85144}
    86145
     
    172231
    173232@implementation AppDelegate
     233
     234- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
     235                               shouldPresentNotification:(NSUserNotification *)notification {
     236    return YES;
     237}
    174238
    175239- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList
     
    225289  CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
    226290  //CFPreferencesSetAppValue(@"javaHome", (CFPropertyListRef)cfDefaultHome, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
    227  
     291
    228292  if (self.enableVerboseLogging) NSLog(@"Default preferences stored!");
    229293}
     
    232296- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    233297  // Init application here
     298  [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
    234299  // Start with user preferences
    235300  self.userPreferences = [NSUserDefaults standardUserDefaults];
     
    247312  if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref);
    248313
    249   [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
    250314
    251315  // This is the only GUI the user experience on a regular basis.
     
    256320
    257321  NSLog(@"We should have started the statusbar object by now...");
     322
     323  // Figure out base directory
     324  const char* pathFromHome = "/Users/%s/Library/I2P";
     325  auto username = getenv("USER");
     326  char buffer[strlen(pathFromHome)+strlen(username)];
     327  sprintf(buffer, pathFromHome, username);
     328  std::string i2pBaseDir(buffer);
     329  if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer);
     330
     331
    258332  //[statusBarButton setAction:@selector(itemClicked:)];
    259333  //dispatch_async(dispatch_get_main_queue(), ^{
     
    274348  };
    275349
    276 
    277   auto launchLambda = [&pref](JavaRunner *javaRun) {
    278     javaRun->javaProcess->start_process();
    279     auto pid = javaRun->javaProcess->pid();
    280     std::cout << "I2P Router process id = " << pid << std::endl;
    281 
    282     // Blocking
    283     javaRun->javaProcess->wait();
    284   };
    285   auto callbackAfterExit = [=](){
    286     printf("Callback after exit\n");
    287   };
    288 
    289   try {
    290 
    291     // Get Java home
     350  auto getJavaBin = [&getJavaHomeLambda]() -> std::string {
     351      // Get Java home
    292352    auto javaHome = getJavaHomeLambda();
    293353    trim(javaHome); // Trim to remove endline
    294354    auto javaBin = std::string(javaHome);
    295355    javaBin += "/bin/java"; // Append java binary to path.
    296     //printf("hello world: %s\n", javaBin.c_str());
    297     if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
    298 
    299     auto r = new JavaRunner{ javaBin, launchLambda, callbackAfterExit };
    300     r->execute();
     356    return javaBin;
     357  };
     358
     359  auto buildClassPath = [](std::string basePath) -> std::vector<std::string> {
     360      return globVector(basePath+std::string("/lib/*.jar"));
     361  };
     362
     363  auto sendUserNotification = [&](NSString* title, NSString* informativeText) -> void {
     364    NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
     365
     366    userNotification.title = title;
     367    userNotification.informativeText = informativeText;
     368    userNotification.soundName = NSUserNotificationDefaultSoundName;
     369
     370    [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
     371  };
     372
     373
     374  // Get paths
     375  NSBundle *launcherBundle = [NSBundle mainBundle];
     376
     377  std::string basearg("-Di2p.dir.base=");
     378  basearg += i2pBaseDir;
     379
     380  std::string zippath("-Di2p.base.zip=");
     381  zippath += [[launcherBundle pathForResource:@"base" ofType:@"zip"] UTF8String];
     382
     383  std::string jarfile("-cp ");
     384  jarfile += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
     385
     386  struct stat sb;
     387  if ( !(stat(buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) )
     388  {
     389    // I2P is not extracted.
     390    if (self.enableVerboseLogging) printf("I2P Directory don't exists!\n");
     391
     392    // Create directory
     393    mkdir(buffer, S_IRUSR | S_IWUSR | S_IXUSR);
     394
     395    auto cli = JavaRunner::defaultFlagsForExtractorJob;
     396    setenv("I2PBASE", buffer, true);
     397    setenv("ZIPPATH", zippath.c_str(), true);
     398    //setenv("DYLD_LIBRARY_PATH",".:/usr/lib:/lib:/usr/local/lib", true);
     399
     400    cli.push_back(basearg);
     401    cli.push_back(zippath);
     402    cli.push_back(jarfile);
     403    cli.push_back("net.i2p.launchers.BaseExtractor");
     404
     405    //auto charCli = map(cli, [](std::string str){ return str.c_str(); });
     406    std::string execStr = getJavaBin();
     407    for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
     408
     409    printf("\n\nTrying cmd: %s\n\n", execStr.c_str());
     410    try {
     411        sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Please hold on while we extract I2P. You'll get a new message once done!"));
     412        int extractStatus = Popen(execStr.c_str(), environment{{
     413            {"ZIPPATH", zippath.c_str()},
     414            {"I2PBASE", buffer}
     415        }}).wait();
     416        printf("Extraction exit code %d\n",extractStatus);
     417        sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Extraction complete!"));
     418    } catch (subprocess::OSError &err) {
     419        printf("Something bad happened: %s\n", err.what());
     420    }
     421
     422  } else {
     423      if (self.enableVerboseLogging) printf("I2P directory found!\n");
     424  }
     425
     426  // Expect base to be extracted by now.
     427
     428  auto jarList = buildClassPath(std::string(buffer));
     429  std::string classpathStrHead = "-classpath";
     430  std::string classpathStr = "";
     431  classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
     432  std::string prefix(i2pBaseDir);
     433  prefix += "/lib/";
     434  for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
     435  //if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
     436
     437
     438
     439  try {
     440    auto argList = JavaRunner::defaultStartupFlags;
     441
     442    std::string baseDirArg("-Di2p.dir.base=");
     443    baseDirArg += i2pBaseDir;
     444    std::string javaLibArg("-Djava.library.path=");
     445    javaLibArg += i2pBaseDir;
     446    // TODO: pass this to JVM
     447    auto java_opts = getenv("JAVA_OPTS");
     448
     449    argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
     450    argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
     451    argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
     452    argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
     453    argList.push_back(@"net.i2p.router.Router");
     454    auto javaBin = getJavaBin();
     455
     456
     457    sendUserNotification(@"I2P Launcher", @"I2P Router is starting up!");
     458    auto nsJavaBin = [NSString stringWithUTF8String:javaBin.c_str()];
     459    auto nsBasePath = [NSString stringWithUTF8String:i2pBaseDir.c_str()];
     460    NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
     461    startupRouter(nsJavaBin, arrArguments, nsBasePath);
     462    //if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
    301463  } catch (std::exception &err) {
    302     std::cerr << "Exception: " << err.what() << std::endl; 
     464    std::cerr << "Exception: " << err.what() << std::endl;
    303465  }
    304466}
  • launchers/macosx/src/main/java/net/i2p/launchers/BaseExtractor.java

    r21b3864 r6d0f80f  
    2222public class BaseExtractor extends EnvCheck {
    2323
    24     private void runExtract(String zipFilename, String destinationPath) {
     24    public boolean printDebug = false;
     25
     26    public void runExtract(String zipFilename) {
     27        String destinationPath = this.baseDirPath;
    2528        try(ZipFile file = new ZipFile(zipFilename)) {
    2629            FileSystem fileSystem = FileSystems.getDefault();
    2730            Enumeration<? extends ZipEntry> entries = file.entries();
    28             Files.createDirectory(fileSystem.getPath(destinationPath));
     31
     32            try {
     33                Files.createDirectory(fileSystem.getPath(destinationPath));
     34            } catch (IOException e) {
     35                // It's OK to fail here.
     36            }
     37
    2938            while (entries.hasMoreElements()) {
    3039                ZipEntry entry = entries.nextElement();
     40                if (printDebug) System.out.println("Found entry: "+entry.toString());
    3141                if (entry.isDirectory()) {
    32                     System.out.println("Creating Directory:" + destinationPath + entry.getName());
    33                     Files.createDirectories(fileSystem.getPath(destinationPath + entry.getName()));
     42                    if (printDebug) System.out.println("Creating Directory:" + destinationPath + "/" + entry.getName());
     43                    Files.createDirectories(fileSystem.getPath(destinationPath + "/" + entry.getName()));
    3444                } else {
    3545                    InputStream is = file.getInputStream(entry);
    3646                    BufferedInputStream bis = new BufferedInputStream(is);
    37                     String uncompressedFileName = destinationPath + entry.getName();
     47                    String uncompressedFileName = destinationPath + "/" + entry.getName();
    3848                    Path uncompressedFilePath = fileSystem.getPath(uncompressedFileName);
    3949                    Files.createFile(uncompressedFilePath);
     
    4151                    while (bis.available() > 0) fileOutput.write(bis.read());
    4252                    fileOutput.close();
    43                     System.out.println("Written :" + entry.getName());
     53                    if (printDebug) System.out.println("Written :" + entry.getName());
    4454                }
    4555            }
    4656        } catch (IOException e) {
    4757            //
     58            System.err.println("Exception in extractor!");
     59            System.err.println(e.toString());
    4860        }
    4961    }
     
    5163    public BaseExtractor(String[] args) {
    5264        super(args);
    53 
    54         if (args.length == 2) {
    55             if ("extract".equals(args[0])) {
    56                 // Start extract
    57 
    58             }this.runExtract(System.getProperty("i2p.base.zip"),this.baseDirPath);
    59         }
    6065    }
    6166
    6267    public static void main(String[] args) {
    63         new BaseExtractor(args);
     68        System.out.println("Starting extraction");
     69        BaseExtractor be = new BaseExtractor(args);
     70        String debug = System.getProperty("print.debug");
     71        if (debug != null) {
     72            be.printDebug = true;
     73        }
     74        be.runExtract(System.getProperty("i2p.base.zip"));
    6475    }
    6576}
Note: See TracChangeset for help on using the changeset viewer.