source: launchers/macosx/JavaHelper.h @ 7615b92

Last change on this file since 7615b92 was 7615b92, checked in by meeh <meeh@…>, 2 years ago

Adding all new code, removed a lot obsolete code and fixed import paths etc.
Mac OS X launcher:

  • UI built on Swift
    • Why?
      • Apple seems to on purpose make it harder to get into Objective-C these days
      • Swift is compiled to native code, but has easiness of Javascript in programming
      • Perfect for the OS X UI, many guides & tutorials as well
  • "Backend" in Objective-C++ / C++14
    • Why?
      • Originally written in Objective-C / C++14 with C++17 backports
      • Only for backend because of the time the development takes *

Short summary of features:

  • Java
    • It can detect java from:
      • JAVA_HOME environment variable
      • "Internet Plug-Ins" Apple stuff
      • By the /usr/libexec/java_home binary helper
    • It can unpack a new version of I2P
      • Unpacks to ~/Library/I2P
      • Can check currently unpacked version in ~/Library/I2P via i2p.jar's "net.i2p.CoreVersion?"
  • User Interface (a popover, see https://youtu.be/k8L3lQ5rUq0 for example of this concept)
    • Router control tab view
      • It can start the router
      • It can stop the router
      • It can detect already running router, then avoid fireing up one
      • It can show basic information about the router state & version
    • Log view tab (not yet done)
  • While left-click triggers popover, right-click draws a minimal context menu
  • Property mode set to 100644
File size: 5.2 KB
Line 
1#pragma once
2
3#include <functional>
4#include <memory>
5#include <iostream>
6#include <algorithm>
7#include <cstring>
8#include <sstream>
9#include <list>
10#include <stdlib.h>
11
12#include <Foundation/Foundation.h>
13#include <CoreFoundation/CoreFoundation.h>
14#include <CoreFoundation/CFStream.h>
15#include <CoreFoundation/CFPropertyList.h>
16#include <CoreFoundation/CFDictionary.h>
17#include <CoreFoundation/CFArray.h>
18#include <CoreFoundation/CFString.h>
19
20#include "optional.hpp"
21#include "strutil.hpp"
22#include "subprocess.hpp"
23#include "neither/maybe.hpp"
24#include "RouterTask.h"
25
26using namespace subprocess;
27using namespace neither;
28
29#define DEF_MIN_JVM_VER "1.7+"
30
31class JvmVersion
32{
33public:
34  std::string JVMName;
35  std::string JVMHomePath;
36  std::string JVMPlatformVersion;
37
38  inline const char * ToCString()
39  {
40    std::stringstream ss;
41    ss << "JvmVersion(name=" << JVMName.c_str() << ",version=";
42    ss << JVMPlatformVersion.c_str() << ",home=" << JVMHomePath.c_str() << ")";
43    std::string s = ss.str();
44    return s.c_str();
45  }
46
47  inline bool HasContent()
48  {
49    return (
50      std::strlen(JVMName.c_str()) > 0 &&
51      std::strlen(JVMHomePath.c_str()) > 0 &&
52      std::strlen(JVMPlatformVersion.c_str()) > 0
53    );
54  }
55};
56
57typedef std::shared_ptr<JvmVersion> JvmVersionPtr;
58typedef std::shared_ptr<std::list<JvmVersionPtr> > JvmListPtr;
59typedef std::shared_ptr<std::list<std::shared_ptr<JvmVersion> > > JvmListSharedPtr;
60typedef void(^MenuBarControllerActionBlock)(BOOL active);
61
62extern JvmListSharedPtr gRawJvmList;
63
64class JvmHomeContext : public std::enable_shared_from_this<JvmHomeContext>
65{
66public:
67
68  inline void setJvm(JvmVersionPtr* current)
69  {
70    mCurrent = *current;
71  }
72
73  inline JvmListPtr getJvmList()
74  {
75    return gRawJvmList;
76  }
77
78  inline std::shared_ptr<JvmHomeContext> getContext()
79  {
80    return shared_from_this();
81  }
82
83  inline std::string getJavaHome()
84  {
85    if (mCurrent)
86    {
87      return mCurrent->JVMHomePath;
88    }
89    return gRawJvmList->back()->JVMHomePath;
90  }
91private:
92  JvmVersionPtr mCurrent;
93};
94
95static void processJvmEntry (const void* key, const void* value, void* context) {
96  //CFShow(key);
97  //CFShow(value);
98
99  // The reason for using strprintf is to "force" a copy of the values,
100  // since local variables gets deleted once this function returns.
101  auto currentJvm = reinterpret_cast<JvmVersion*>(context);
102  if (CFEqual((CFStringRef)key,CFSTR("JVMName"))) {
103    auto strVal = extractString((CFStringRef)value);
104    currentJvm->JVMName = strprintf("%s",strVal.c_str());
105  }
106  if (CFEqual((CFStringRef)key,CFSTR("JVMHomePath"))) {
107    auto strVal = extractString((CFStringRef)value);
108    currentJvm->JVMHomePath = strprintf("%s",strVal.c_str());
109  }
110  if (CFEqual((CFStringRef)key,CFSTR("JVMPlatformVersion"))) {
111    auto strVal = extractString((CFStringRef)value);
112    currentJvm->JVMPlatformVersion = strprintf("%s",strVal.c_str());
113  }
114}
115
116static void processJvmPlistEntries (const void* item, void* context) {
117  CFDictionaryRef dict = CFDictionaryCreateCopy(kCFAllocatorDefault, (CFDictionaryRef)item);
118
119  JvmVersionPtr currentJvmPtr = std::shared_ptr<JvmVersion>(new JvmVersion());
120  struct CFunctional
121  {
122    static void applier(const void* key, const void* value, void* context){
123      // The reason for using strprintf is to "force" a copy of the values,
124      // since local variables gets deleted once this function returns.
125      auto currentJvm = static_cast<JvmVersion*>(context);
126      if (CFEqual((CFStringRef)key,CFSTR("JVMName"))) {
127        auto d = extractString((CFStringRef)value);
128        currentJvm->JVMName = trim_copy(d);
129      }
130      if (CFEqual((CFStringRef)key,CFSTR("JVMHomePath"))) {
131        auto d = extractString((CFStringRef)value);
132        currentJvm->JVMHomePath = trim_copy(d);
133      }
134      if (CFEqual((CFStringRef)key,CFSTR("JVMPlatformVersion"))) {
135        auto d = extractString((CFStringRef)value);
136        currentJvm->JVMPlatformVersion = trim_copy(d);
137      }
138
139    }
140  };
141
142  CFDictionaryApplyFunction(dict, CFunctional::applier, (void*)currentJvmPtr.get());
143
144  if (currentJvmPtr->HasContent())
145  {
146    printf("Found JVM: %s\n\n", currentJvmPtr->ToCString());
147    gRawJvmList->push_back(currentJvmPtr);
148  }
149}
150
151static void listAllJavaInstallsAvailable()
152{
153  auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"});
154  CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data()));
155
156  //CFErrorRef err;
157  CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL);
158  /*if (err)
159  {
160    NSError *error = (__bridge NSError *)err;
161    NSLog(@"Failed to read property list: %@", error);
162    [NSApp presentError: error];
163    return nullptr;
164  }*/
165
166
167  //auto typeId = CFCopyTypeIDDescription(CFGetTypeID(propertyList));
168  //auto test = CFCopyDescription(propertyList);
169  //std::cout << "test: " << [test UTF8String] << " Type: " << [typeId UTF8String] << " num: " << jCount << std::endl;
170
171  // Count number of entries in the property array list.
172  // This is used to set max CRange for CFArrayApplyFunction.
173  auto jCount = CFArrayGetCount((CFArrayRef)propertyList);
174
175  CFArrayApplyFunction((CFArrayRef)propertyList, CFRangeMake(0, jCount), processJvmPlistEntries, NULL);
176  //CFShow(propertyList);
177}
Note: See TracBrowser for help on using the repository browser.