Skip to content

Commit

Permalink
Start of Installation process of Daemon
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcus S. Zarra committed Jun 5, 2010
1 parent 737f9f0 commit c311a9f
Show file tree
Hide file tree
Showing 20 changed files with 393 additions and 77 deletions.
3 changes: 3 additions & 0 deletions Daemon/Classes/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@

@interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSStatusItem *statusItem;
}

@property (nonatomic, retain) NSStatusItem *statusItem;

@end
37 changes: 37 additions & 0 deletions Daemon/Classes/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,43 @@ - (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{
[[ZSyncHandler shared] setDelegate:self];
[[ZSyncHandler shared] startBroadcasting];

NSMenu *menu = [[NSMenu alloc] initWithTitle:@"ZSync"];

NSMenuItem *aboutMenu = [[NSMenuItem alloc] initWithTitle:@"About" action:@selector(about:) keyEquivalent:@""];
[menu addItem:aboutMenu];
[aboutMenu release], aboutMenu = nil;

[menu addItem:[NSMenuItem separatorItem]];

NSMenuItem *quitMenu = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(quit:) keyEquivalent:@""];
[menu addItem:quitMenu];
[quitMenu release], quitMenu = nil;

NSImage *statusImage = [NSImage imageNamed:@"menubar.png"];

statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:[statusImage size].width] retain];
[statusItem setMenu:menu];
[statusItem setToolTip:NSLocalizedString(@"ZSync Daemon", @"ZSync menu bar toolitp")];
[statusItem setImage:statusImage];
[statusItem setAction:@selector(statusItemSelected:)];

[menu release], menu = nil;

[[NSApplication sharedApplication] hide:self];
}

- (IBAction)about:(id)sender
{
DLog(@"fired");
}

- (IBAction)quit:(id)sender
{
DLog(@"fired");
[[NSApplication sharedApplication] terminate:self];
}

@synthesize statusItem;

@end
10 changes: 10 additions & 0 deletions Daemon/Classes/ZSyncDaemon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@interface ZSyncDaemon : NSObject
{

}

+ (BOOL)installPluginAtPath:(NSString*)path intoDaemonWithError:(NSError**)error;
+ (BOOL)isDaemonRunning;
+ (void)startDaemon;

@end
222 changes: 222 additions & 0 deletions Daemon/Classes/ZSyncDaemon.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#import "ZSyncDaemon.h"

@implementation ZSyncDaemon

+ (NSString*)basePath
{
//Build our standard install path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
basePath = [basePath stringByAppendingPathComponent:@"ZSyncDaemon"];
return basePath;
}

+ (NSString*)applicationPath
{
NSString *basePath = [self basePath];
return [basePath stringByAppendingPathComponent:@"ZSyncDaemon.app"];
}

+ (BOOL)checkBasePath:(NSString*)basePath error:(NSError**)error;
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath:basePath isDirectory:&isDirectory]) {
return NO;
}
if (!isDirectory) {
NSString *errorDesc = [NSString stringWithFormat:@"Unknown file at base installation path: %@", basePath];
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:errorDesc forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"ZSync" code:1123 userInfo:dictionary];
return NO;
}
return YES;
}

+ (BOOL)checkApplicationPath:(NSString*)applicationPath error:(NSError**)error;
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath:applicationPath isDirectory:&isDirectory]) {
return NO;
}
if (!isDirectory) {
NSString *errorDesc = [NSString stringWithFormat:@"Unknown file at daemon application installation path: %@", applicationPath];
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:errorDesc forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"ZSync" code:1124 userInfo:dictionary];
return NO;
}
return YES;
}

+ (BOOL)isDaemonInstalled:(NSError**)error;
{
NSString *basePath = [self basePath];
if (![self checkBasePath:basePath error:error]) {
if (error) {
return NO;
}
if (![[NSFileManager defaultManager] createDirectoryAtPath:basePath
withIntermediateDirectories:YES
attributes:nil
error:error]) {
return NO;
}
}
NSString *applicationPath = [self applicationPath];
return [self checkApplicationPath:applicationPath error:error];
}

+ (BOOL)installDaemon:(NSError**)error;
{
NSString *myBundlePath = [[NSBundle mainBundle] bundlePath];
NSString *applicationPath = [self applicationPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
return [fileManager copyItemAtPath:myBundlePath toPath:applicationPath error:error];
}

+ (BOOL)stopDaemon:(NSError**)error
{
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
NSString *command = [NSString stringWithFormat:@"tell application \"%@\" to quit", appName];
NSAppleScript *quitScript;
quitScript = [[NSAppleScript alloc] initWithSource:command];
NSDictionary *errorDict = nil;
// TODO: This should be turned into an NSError response
if (![quitScript executeAndReturnError:&errorDict]) {
ALog(@"Failure. What does it look like: %@", errorDict);
[quitScript release], quitScript = nil;
return NO;
}
[quitScript release], quitScript = nil;
return YES;
}

+ (BOOL)updateInstalledApplication:(NSError**)error;
{
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];

if ([self isDaemonRunning] && ![self stopDaemon:error]) return NO;

NSString *myBundlePath = [[NSBundle mainBundle] bundlePath];

NSString *applicationPath = [self applicationPath];
NSString *basePath = [self basePath];
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
if (![workspace performFileOperation:NSWorkspaceRecycleOperation
source:basePath
destination:@""
files:[NSArray arrayWithObject:appName]
tag:NULL]) {
NSString *errorDesc = [NSString stringWithFormat:@"Failed to move old app version to the trash"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:errorDesc forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"ZSync" code:1126 userInfo:dictionary];
return NO;
}

NSFileManager *fileManager = [NSFileManager defaultManager];
return [fileManager copyItemAtPath:myBundlePath toPath:applicationPath error:error];
}

+ (NSString*)pluginPath
{
NSString *basePath = [self basePath];
return [basePath stringByAppendingPathComponent:@"Plugins"];
}

+ (BOOL)isPluginInstalled:(NSString*)path error:(NSError**)error
{
NSString *pluginPath = [self pluginPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath:pluginPath isDirectory:&isDirectory]) {
return NO;
}
if (!isDirectory) {
NSString *errorDesc = [NSString stringWithFormat:@"Unknown file at plugin installation path: %@", pluginPath];
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:errorDesc forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"ZSync" code:1123 userInfo:dictionary];
return NO;
}

NSString *finalPath = [pluginPath stringByAppendingPathComponent:[path lastPathComponent]];
if (![fileManager fileExistsAtPath:finalPath isDirectory:&isDirectory]) {
return NO;
}
return YES;
}

+ (BOOL)installPluginAtPath:(NSString*)path intoDaemonWithError:(NSError**)error;
{
if (![[path pathExtension] isEqualToString:@"zsyncPlugin"]) {
NSString *errorDesc = [NSString stringWithFormat:@"url is not a valid ZSync plugin: %@", path];
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:errorDesc forKey:NSLocalizedDescriptionKey];
*error = [NSError errorWithDomain:@"ZSync" code:1125 userInfo:dictionary];
return NO;
}

BOOL isDaemonInstalled = [self isDaemonInstalled:error];

if (!isDaemonInstalled && *error) {
return NO;
}

if (!isDaemonInstalled) {
if (![self installDaemon:error]) return NO;
} else {
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSInteger currentVersionNumber = [[infoDictionary objectForKey:ZSyncVersionNumber] integerValue];

NSBundle *installed = [NSBundle bundleWithPath:[self applicationPath]];
NSInteger installedVersionNumber = [[[installed infoDictionary] objectForKey:ZSyncVersionNumber] integerValue];

if (installedVersionNumber < currentVersionNumber && ![self updateInstalledApplication:error]) return NO;
}

//Is plugin already installed?
if ([self isPluginInstalled:path error:error]) {
return YES;
}

//Shutdown the daemon to install the plugin
if ([self isDaemonRunning] && ![self stopDaemon:error]) {
return NO;
}

//Install the plugin
NSString *pluginPath = [[self pluginPath] stringByAppendingPathComponent:[path lastPathComponent]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager copyItemAtPath:path toPath:pluginPath error:error]) {
return NO;
}

//Start the daemon back up
[self startDaemon];

return YES;
}

+ (BOOL)isDaemonRunning;
{
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *myBundleID = [infoDictionary objectForKey:@"CFBundleIdentifier"];

NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSArray *apps = [workspace launchedApplications];
for (NSDictionary *appDict in apps) {
NSString *bundleID = [appDict objectForKey:@"NSApplicationBundleIdentifier"];
if ([bundleID isEqualToString:myBundleID]) return YES;
}
return NO;
}

+ (void)startDaemon;
{
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *appName = [infoDictionary objectForKey:@"CFBundleExecutable"];

NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
[workspace launchApplication:appName];
}

@end
2 changes: 2 additions & 0 deletions Daemon/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@
<string>NSApplication</string>
<key>LSUIElement</key>
<true/>
<key>ZSyncVersionNumber</key>
<string>1</string>
</dict>
</plist>
2 changes: 2 additions & 0 deletions Daemon/Prefix.pch
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
#import <CoreData/CoreData.h>
#import "ZSync.h"
#endif

#define ZSyncVersionNumber @"ZSyncVersionNumber"
19 changes: 19 additions & 0 deletions Daemon/ZSyncDaemon.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

/* Begin PBXBuildFile section */
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
B63F9C2211B2EA2800811EB1 /* menubar.png in Resources */ = {isa = PBXBuildFile; fileRef = B63F9C2111B2EA2800811EB1 /* menubar.png */; };
B63F9CAC11B2EF6700811EB1 /* ZSyncDaemon.m in Sources */ = {isa = PBXBuildFile; fileRef = B63F9CAB11B2EF6700811EB1 /* ZSyncDaemon.m */; };
B64FE70410EE728F00B15A8F /* clientDescription.plist in Resources */ = {isa = PBXBuildFile; fileRef = B64FE70310EE728F00B15A8F /* clientDescription.plist */; };
B64FE7C910EEA24500B15A8F /* DataModel.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = B64FE7C810EEA24500B15A8F /* DataModel.xcdatamodel */; };
B64FE94010EF35DF00B15A8F /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B64FE93F10EF35DF00B15A8F /* libz.dylib */; };
Expand All @@ -31,6 +33,9 @@
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107320486CEB800E47090 /* ZSyncDaemon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZSyncDaemon.app; sourceTree = BUILT_PRODUCTS_DIR; };
B63F9C2111B2EA2800811EB1 /* menubar.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menubar.png; sourceTree = "<group>"; };
B63F9CAA11B2EF6700811EB1 /* ZSyncDaemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZSyncDaemon.h; sourceTree = "<group>"; };
B63F9CAB11B2EF6700811EB1 /* ZSyncDaemon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZSyncDaemon.m; sourceTree = "<group>"; };
B64FE70310EE728F00B15A8F /* clientDescription.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = clientDescription.plist; sourceTree = "<group>"; };
B64FE7C810EEA24500B15A8F /* DataModel.xcdatamodel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.xcdatamodel; path = DataModel.xcdatamodel; sourceTree = "<group>"; };
B64FE93F10EF35DF00B15A8F /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -121,6 +126,7 @@
29B97314FDCFA39411CA2CEA /* Daemon */ = {
isa = PBXGroup;
children = (
B63F9C2011B2EA1300811EB1 /* Images */,
B6EC175910F5033E0051FD2E /* GoogleToolboxSubset */,
B691FB9810ED879D00207210 /* SharedCode */,
B691FB8210ED875800207210 /* DesktopCode */,
Expand Down Expand Up @@ -164,6 +170,15 @@
name = Frameworks;
sourceTree = "<group>";
};
B63F9C2011B2EA1300811EB1 /* Images */ = {
isa = PBXGroup;
children = (
B63F9C2111B2EA2800811EB1 /* menubar.png */,
);
name = Images;
path = ../Images;
sourceTree = "<group>";
};
B64FE7C710EEA24500B15A8F /* DataModel */ = {
isa = PBXGroup;
children = (
Expand All @@ -178,6 +193,8 @@
children = (
B691FB3A10ED855F00207210 /* AppDelegate.h */,
B691FB3B10ED855F00207210 /* AppDelegate.m */,
B63F9CAA11B2EF6700811EB1 /* ZSyncDaemon.h */,
B63F9CAB11B2EF6700811EB1 /* ZSyncDaemon.m */,
);
path = Classes;
sourceTree = "<group>";
Expand Down Expand Up @@ -290,6 +307,7 @@
B691FB4510ED855F00207210 /* MainMenu.xib in Resources */,
B691FB8C10ED875800207210 /* PairingWindow.xib in Resources */,
B64FE70410EE728F00B15A8F /* clientDescription.plist in Resources */,
B63F9C2211B2EA2800811EB1 /* menubar.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -308,6 +326,7 @@
B64FE7C910EEA24500B15A8F /* DataModel.xcdatamodel in Sources */,
B6EC175D10F5033E0051FD2E /* GTMNSData+zlib.m in Sources */,
B67ED12E1103765600314759 /* ZSyncConnectionDelegate.m in Sources */,
B63F9CAC11B2EF6700811EB1 /* ZSyncDaemon.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion DesktopCode/PairingCodeWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ - (void)windowDidLoad

- (void) dealloc
{
DLog(@"%s window released cleanly", __PRETTY_FUNCTION__);
DLog(@"window released cleanly");
[codeString release], codeString = nil;
[super dealloc];
}
Expand Down
Loading

0 comments on commit c311a9f

Please sign in to comment.