📄 osxconnector.java
字号:
package com.skype.connector.osx;
import java.io.File;
import java.lang.reflect.Method;
import com.skype.connector.Connector;
import com.skype.connector.ConnectorUtils;
/**
* Implementation of the connector for OS X.
* @author Bart Lamot
*
*/
public final class OSXConnector extends Connector implements Runnable {
/** The singleton instance. */
private static OSXConnector _instance = null;
/** Thread synchronisation lock. */
private static final Object lock = new Object();
/** Thread synchronisation lock flag. */
private static boolean lockWait = false;
/** Don't reinit the native code over and over. */
private boolean inited;
/** Name of the library. */
private static final String LIBNAME = "JSA";
/** Filename of the OS X jnilib. */
private static final String LIBFILENAME = "libJSA.jnilib";
/**
* Constructor. It loads the native library, if it can't be loaded the
* status is set to NOT_AVAILABLE.
*
*/
private OSXConnector() {
if (!ConnectorUtils.checkLibraryInPath(LIBFILENAME) || !checkInstalledFramework()) {
ConnectorUtils.extractFromJarToTemp(LIBFILENAME);
installFramework();
}
try {
System.loadLibrary(LIBNAME);
} catch (Throwable e) {
try {
System.load(System.getProperty("java.io.tmpdir") + File.separatorChar + LIBFILENAME);
} catch (Throwable e2) {
System.err.println("Could not load the library");
if (!ConnectorUtils.checkLibraryInPath(LIBFILENAME)) {
System.err.println(LIBFILENAME + " is not in java.library.path");
}
if (!checkInstalledFramework()) {
System.err.println("Please install Skype.framework at /Library/Frameworks/Skype.framework");
}
// Sorry could not load.
setStatus(com.skype.connector.Connector.Status.NOT_AVAILABLE);
fireMessageReceived("ConnectorStatusChanged");
}
}
}
/**
* Checks if the library file can be found in the library path.
*
* @return true if the file is found.
*/
private boolean checkInstalledFramework() {
File frameworkLocationHome = new File("~/Library/Frameworks/Skype.framework");
File frameworkLocationSystem = new File("/Library/Frameworks/Skype.framework");
if (frameworkLocationHome.exists() || frameworkLocationSystem.exists()) {
return true;
}
return false;
}
/**
* Install the Skype.framework from the jarfile. create directories and
* extract framework files for jar.
*/
private void installFramework() {
// First check if Framework is in jarfile. Lets not create directories
// if nothing can be found.
if (ConnectorUtils.isInJar("A/Skype")) {
//The framework is in the jarfile.
//Clean up old one.
File frameworkLocation = new File("~/Library/Frameworks/Skype.framework");
if (frameworkLocation.exists()) {
ConnectorUtils.deleteDir(frameworkLocation);
}
frameworkLocation = new File("/Library/Frameworks/Skype.framework");
if (frameworkLocation.exists()) {
ConnectorUtils.deleteDir(frameworkLocation);
}
String destinationname;
destinationname = System.getProperty("user.home");
if (!destinationname.endsWith(File.separator)) {
destinationname = destinationname + File.separator;
}
// check for root, root doesn't have a Users home directory.
if (destinationname.endsWith("root/")) {
destinationname = "/";
}
destinationname = destinationname + "Library/Frameworks/";
// Make Framework directories
File frameworkDirectory = new File(destinationname + "Skype.framework/Versions/A/.tmp");
frameworkDirectory.mkdirs();
frameworkDirectory = new File(destinationname + "Skype.framework/Versions/Current/.tmp");
frameworkDirectory.mkdirs();
ConnectorUtils.extractFromJar("A/Skype", "Skype", destinationname + "Skype.framework/Versions/A");
ConnectorUtils.extractFromJar("A/Skype", "Skype", destinationname + "Skype.framework/Versions/Current");
ConnectorUtils.extractFromJar("A/Skype", "Skype", destinationname + "Skype.framework");
}
}
/**
* Return the singleton instance of this connector.
*
* @return singleton instance.
*/
public static OSXConnector getInstance() {
// System.out.println("OSXConnector.getInstance()");
if (_instance == null) {
_instance = new OSXConnector();
}
return _instance;
}
/**
* Send a command to the Skype API.
*
* @param command
* the command to send.
*/
protected void sendCommand(String command) {
// System.out.println((new
// StringBuilder()).append("OSXConnector.sendCommand(").append(command).append(")
// start").toString());
sendSkypeMessage(command);
// System.out.println((new
// StringBuilder()).append("OSXConnector.sendCommand(").append(command).append(")
// end").toString());
}
/**
* Disconnect from the Skype API and clean up the native implementation.
*/
protected void disposeImpl() {
// System.out.println("OSXConnector.disposeImpl() start");
setConnectedStatus(5);
disposeNative();
_instance = null;
// System.out.println("OSXConnector.disposeImpl() end");
}
/**
* Wait for the connection to get initialized.
*
* @param timeout Wait for this amout of millisecs to initialize.
* @return Status after connecting.
*/
protected com.skype.connector.Connector.Status connect(int timeout) {
// System.out.println((new
// StringBuilder()).append("OSXConnector.connectImpl(").append(timeout).append(")
// start").toString());
if (_instance.getStatus() != com.skype.connector.Connector.Status.ATTACHED) {
synchronized (lock) {
try {
lockWait = true;
lock.wait(timeout);
} catch (InterruptedException e) {
}
}
}
// System.out.println((new
// StringBuilder()).append("OSXConnector.connectImpl(").append(timeout).append(")
// end").toString());
return getStatus();
}
/**
* This method checks if SWT is available in the classpath.
* @return true if SWT is found.
*/
private static boolean isSWTAvailable() {
try {
Class.forName("org.eclipse.swt.SWT");
} catch(ClassNotFoundException e) {
return false;
}
return true;
}
/**
* Initialize the connection to Skype API.
*
* @param timeout
* Wait for this amout of millisecs to initialize.
*/
protected void initialize(int timeout) {
// System.out.println((new
// StringBuilder()).append("OSXConnector.initialize(").append(timeout).append(")
// start ***************").toString());
if (!inited) {
inited = true;
//Check if SWT is being used, if not just run the thread, else run it SWT like.
if (isSWTAvailable()) {
// The next line is the actual line needed for SWT to start the Thread.
//Display.getCurrent().asyncExec(this);
//But I don't want SWT in the import statements and in the classpath I will need this whole reflection part.
try {
Class displayClass = Class.forName("org.eclipse.swt.widgets.Display");
Method getCurrentMethod = displayClass.getMethod("getCurrent", null);
Class[] params = new Class[1];
params[0] = Class.forName("java.lang.Runnable");
Method asyncExecMethod = displayClass.getMethod("asyncExec", params);
Object display = getCurrentMethod.invoke(null, null);
Object[] args = new Object[1];
args[0] = this;
asyncExecMethod.invoke(display, args);
} catch(Throwable e) {
//Something went wrong in the fragile reflection, now just try to start the thread the normal way.
//display can be null if SWT is found but not used.
(new Thread(this)).start();
}
} else {
(new Thread(this)).start();
}
setStatus(com.skype.connector.Connector.Status.PENDING_AUTHORIZATION);
fireMessageReceived("ConnectorStatusChanged");
setDebugPrinting(false);
init(getApplicationName());
}
// System.out.println((new
// StringBuilder()).append("OSXConnector.initialize(").append(timeout).append(")
// end ***************").toString());
}
/**
* This method gets called by the native library when a message from Skype
* is received.
*
* @param message
* The received message.
*/
public static synchronized void receiveSkypeMessage(final String message) {
// System.out.println((new
// StringBuilder()).append("OSXConnector.receiveSkypeMessage(").append(message).append(")
// start").toString());
new Thread() {
public void run() {
if (_instance.getStatus() != com.skype.connector.Connector.Status.ATTACHED) {
setConnectedStatus(1);
}
if (lockWait) {
setConnectedStatus(1);
synchronized (lock) {
lock.notifyAll();
}
lockWait = false;
}
if (message != null) {
_instance.fireMessageReceived(message);
}
}
}.start();
// System.out.println((new
// StringBuilder()).append("OSXConnector.receiveSkypeMessage(").append(message).append(")
// end").toString());
}
/**
* This method gets called from the native library when the status is
* changed by Skype API.
*
* @param status
* the new status.
*/
public static void setConnectedStatus(int status) {
// System.out.println((new
// StringBuilder()).append("OSXConnector.setConnectedStatus(").append(status).append(")
// start").toString());
if (lockWait) {
synchronized (lock) {
lock.notifyAll();
lockWait = false;
}
}
switch (status) {
case 0 : // '\0'
_instance.setStatus(com.skype.connector.Connector.Status.PENDING_AUTHORIZATION);
break;
case 1 : // '\001'
_instance.setStatus(com.skype.connector.Connector.Status.ATTACHED);
break;
case 2 : // '\002'
_instance.setStatus(com.skype.connector.Connector.Status.REFUSED);
break;
case 3 : // '\003'
_instance.setStatus(com.skype.connector.Connector.Status.NOT_AVAILABLE);
break;
case 4 : // '\004'
_instance.setStatus(com.skype.connector.Connector.Status.API_AVAILABLE);
break;
case 5 : // '\005'
_instance.setStatus(com.skype.connector.Connector.Status.NOT_RUNNING);
break;
default :
_instance.setStatus(com.skype.connector.Connector.Status.NOT_RUNNING);
break;
}
_instance.fireMessageReceived("ConnectorStatusChanged");
// System.out.println((new
// StringBuilder()).append("OSXConnector.setConnectedStatus(").append(status).append(")
// end").toString());
}
/**
* OS X needs a native event loop to run, this starts it.
*/
public void run() {
startEventLoop();
}
/**
* Native init method.
* @param applicationname The name of the Application.
*/
private synchronized native void init(String applicationname);
/**
* Start the OS X eventloop.
* This method does not return.
*/
private native void startEventLoop();
/**
* Native send message method.
* @param msg The message to send.
*/
private native void sendSkypeMessage(String msg);
/**
* Clean up the native connection.
*
*/
private native void disposeNative();
/**
* Enable debug printing for the native library.
* @param flag True to enable debug printing.
*/
private native void setDebugPrinting(boolean flag);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -