Merge pull request #64 in ITERATE/cyberduck from feature/windows/9074 to master
[cyberduck.git] / source / ch / cyberduck / binding / ProxyController.java
blob98ede69913fd554a1f29fae9d9cfb1f12ebf263a
1 package ch.cyberduck.binding;
3 /*
4 * Copyright (c) 2005 David Kocher. All rights reserved.
5 * http://cyberduck.ch/
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * Bug fixes, suggestions and comments should be sent to:
18 * dkocher@cyberduck.ch
21 import ch.cyberduck.binding.foundation.NSNotificationCenter;
22 import ch.cyberduck.binding.foundation.NSObject;
23 import ch.cyberduck.binding.foundation.NSThread;
24 import ch.cyberduck.core.AbstractController;
25 import ch.cyberduck.core.threading.MainAction;
27 import org.apache.log4j.Logger;
28 import org.rococoa.Foundation;
29 import org.rococoa.ID;
30 import org.rococoa.Rococoa;
32 /**
33 * @version $Id$
35 public class ProxyController extends AbstractController {
36 private static Logger log = Logger.getLogger(ProxyController.class);
38 /**
39 * You need to keep a reference to the returned value for as long as it is
40 * active. When it is GCd, it will release the Objective-C proxy.
42 private NSObject proxy;
44 private ID id;
46 public NSObject proxy() {
47 return this.proxy(NSObject.class);
50 protected NSObject proxy(Class<? extends NSObject> type) {
51 if(null == proxy) {
52 proxy = Rococoa.proxy(this, type);
54 return proxy;
57 public ID id() {
58 return this.id(NSObject.class);
61 protected ID id(Class<? extends NSObject> type) {
62 if(null == id) {
63 id = this.proxy(type).id();
65 return id;
68 /**
69 * Free all locked resources by this controller; also remove me from all observables;
70 * marks this controller to be garbage collected as soon as needed
72 @Override
73 public void invalidate() {
74 if(log.isDebugEnabled()) {
75 log.debug(String.format("Invalidate controller %s", this));
77 if(id != null) {
78 NSNotificationCenter.defaultCenter().removeObserver(id);
80 super.invalidate();
83 /**
84 * You can use this method to deliver messages to the main thread of your application. The main thread
85 * encompasses the application’s main run loop, and is where the NSApplication object receives
86 * events. The message in this case is a method of the current object that you want to execute
87 * on the thread.
88 * <p/>
89 * Execute the passed <code>Runnable</code> on the main thread also known as NSRunLoop.DefaultRunLoopMode
91 * @param runnable The <code>Runnable</code> to run
92 * @param wait Block until execution on main thread exits. A Boolean that specifies whether the current
93 * thread blocks until after the specified selector is performed on the receiver on the main thread.
94 * Specify YES to block this thread; otherwise, specify NO to have this method return immediately.
95 * If the current thread is also the main thread, and you specify YES for this parameter,
96 * the message is delivered and processed immediately.
98 @Override
99 public void invoke(final MainAction runnable, final boolean wait) {
100 if(!runnable.isValid()) {
101 return;
103 if(NSThread.isMainThread()) {
104 if(log.isDebugEnabled()) {
105 log.debug(String.format("Already on main thread. Invoke %s directly.", runnable));
107 runnable.run();
108 return;
110 synchronized(runnable.lock()) {
111 if(log.isTraceEnabled()) {
112 log.trace(String.format("Invoke runnable %s on main thread", runnable));
114 try {
115 //Defer to main thread
116 Foundation.runOnMainThread(runnable, wait);
118 catch(Exception e) {
119 log.error(String.format("Exception %s running task on main thread", e.getMessage()), e);