package net.mms_projects.copy_it.integration;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Date;
import net.mms_projects.copy_it.Activatable;
import net.mms_projects.copy_it.ClipboardManager;
import net.mms_projects.copy_it.DesktopIntegration;
import net.mms_projects.copy_it.EnvironmentIntegration;
import net.mms_projects.copy_it.EnvironmentIntegration.NotificationManager.NotificationUrgency;
import net.mms_projects.copy_it.FunctionalityManager;
import net.mms_projects.copy_it.Messages;
import net.mms_projects.copy_it.PathBuilder;
import net.mms_projects.copy_it.SyncManager;
import net.mms_projects.copy_it.app.CopyItDesktop;
import net.mms_projects.copy_it.integration.notifications.FreedesktopNotificationManager;
import net.mms_projects.copy_it.listeners.EnabledListener;
import net.mms_projects.copy_it.ui.UserInterfaceImplementation;
import org.apache.commons.io.FileUtils;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.DBusSigHandler;
import org.freedesktop.dbus.DBusSignal;
import org.freedesktop.dbus.exceptions.DBusException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UnityIntegration extends EnvironmentIntegration implements
DBusSigHandler {
protected SyncManager syncManager;
protected ClipboardManager clipboardManager;
protected DBusConnection dbusConnection;
private DesktopIntegration integration;
private final Logger log = LoggerFactory.getLogger(this.getClass());
private FunctionalityManager<Activatable> functionality;
private UserInterfaceImplementation uiImplementation;
private EnabledListener pollingListener = new EnabledListener() {
@Override
public void onEnabled() {
integration.set_enabled(true);
}
@Override
public void onDisabled() {
integration.set_enabled(false);
}
};
public UnityIntegration(DBusConnection dbusConnection,
FunctionalityManager<Activatable> functionality,
SyncManager syncManager, ClipboardManager clipboardManager) {
try {
this.setNotificationManager(new FreedesktopNotificationManager(
dbusConnection));
} catch (DBusException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.functionality = functionality;
this.syncManager = syncManager;
this.clipboardManager = clipboardManager;
this.dbusConnection = dbusConnection;
this.functionality.addEnabledListener("polling", this.pollingListener);
/*
* Add FreeDesktop integrations like notifications and writing .desktop
* files and the appropriate icons for the .desktop files
*/
this.addIntegration(new FreeDesktopIntegration(this, dbusConnection));
}
@Override
public void standaloneSetup() {
try {
dbusConnection.addSigHandler(DesktopIntegration.ready.class, this);
dbusConnection.addSigHandler(DesktopIntegration.action_pull.class,
this);
dbusConnection.addSigHandler(DesktopIntegration.action_push.class,
this);
dbusConnection.addSigHandler(
DesktopIntegration.action_open_preferences.class, this);
dbusConnection.addSigHandler(
DesktopIntegration.action_open_about.class, this);
dbusConnection.addSigHandler(DesktopIntegration.action_quit.class,
this);
dbusConnection.addSigHandler(
DesktopIntegration.action_enable_sync.class, this);
dbusConnection.addSigHandler(
DesktopIntegration.action_disable_sync.class, this);
} catch (DBusException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL inputUrl = getClass().getResource("/images/icon-16-mono.png");
File dest = new File(PathBuilder.getCacheDirectory(), "tray_icon.png");
try {
FileUtils.copyURLToFile(inputUrl, dest);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
File script = CopyItDesktop
.exportResource("scripts/desktop-integration.py");
if (script == null) {
script = new File("scripts/desktop-integration.py");
}
String[] command = new String[2];
command[0] = "python";
command[1] = script.getAbsolutePath();
try {
final Process process = Runtime.getRuntime().exec(command);
log.info("Started desktop integration script");
log.debug("Integration script path: " + script.getAbsolutePath());
Thread ouputReadingthread = new ScriptOutputStreamReader(
process.getInputStream());
ouputReadingthread.setDaemon(true);
ouputReadingthread.start();
Thread errorReadingthread = new ScriptErrorStreamReader(
process.getErrorStream());
errorReadingthread.setDaemon(true);
errorReadingthread.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
log.debug("Stopping desktop integration script");
process.destroy();
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void handle(DBusSignal signal) {
if (signal instanceof DesktopIntegration.ready) {
String icon = new File(PathBuilder.getCacheDirectory(),
"tray_icon.png").getAbsolutePath();
try {
integration = this.dbusConnection.getRemoteObject(
"net.mms_projects.copyit.DesktopIntegration", "/",
DesktopIntegration.class);
integration.setup(icon, icon);
integration
.set_enabled(this.functionality.isEnabled("polling"));
} catch (DBusException e) {
log.error("Could not connect to desktop integration script although it reported as ready. Exiting...");
System.exit(1);
}
} else if (signal instanceof DesktopIntegration.action_push) {
String content = clipboardManager.getContent();
syncManager.setRemoteContent(content, new Date());
getNotificationManager().notify(10, NotificationUrgency.NORMAL, "",
"CopyIt",
Messages.getString("text_content_pushed", content));
} else if (signal instanceof DesktopIntegration.action_pull) {
syncManager.requestRemoteContentAsync();
} else if (signal instanceof DesktopIntegration.action_open_preferences) {
this.getUserInterfaceImplementation().getSettingsUserInterface()
.open();
} else if (signal instanceof DesktopIntegration.action_open_about) {
this.getUserInterfaceImplementation().getAboutUserInterface()
.open();
} else if (signal instanceof DesktopIntegration.action_quit) {
this.getUserInterfaceImplementation().close();
} else if (signal instanceof DesktopIntegration.action_enable_sync) {
this.functionality.setEnabled("polling", true);
this.integration.set_enabled(this.functionality
.isEnabled("polling"));
} else if (signal instanceof DesktopIntegration.action_disable_sync) {
this.functionality.setEnabled("polling", false);
this.integration.set_enabled(this.functionality
.isEnabled("polling"));
}
}
private class ScriptOutputStreamReader extends ScriptOutputReadingThread {
public ScriptOutputStreamReader(InputStream stream) {
super(stream);
}
@Override
protected void log(String output) {
log.debug("Integration script returned: {}", output);
}
}
private class ScriptErrorStreamReader extends ScriptOutputReadingThread {
public ScriptErrorStreamReader(InputStream stream) {
super(stream);
}
@Override
protected void log(String output) {
log.warn("Integration script returned: {}", output);
}
}
abstract private class ScriptOutputReadingThread extends Thread {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private InputStream stream;
public ScriptOutputReadingThread(InputStream stream) {
super();
this.stream = stream;
}
@Override
public void run() {
super.run();
BufferedReader inputStream = new BufferedReader(
new InputStreamReader(this.stream));
String line = null;
try {
while ((line = inputStream.readLine()) != null) {
this.log(line);
}
} catch (IOException exception) {
log.warn("Couldn't listen for integration script output",
exception);
}
}
abstract protected void log(String output);
}
}