Merge pull request #64 in ITERATE/cyberduck from feature/windows/9074 to master
[cyberduck.git] / source / ch / cyberduck / core / ApplescriptTerminalService.java
blobe5b89e907c59b4264171e0c0e3a3d64a7dfb6c9c
1 package ch.cyberduck.core;
3 import ch.cyberduck.binding.foundation.NSAppleScript;
4 import ch.cyberduck.binding.foundation.NSDictionary;
5 import ch.cyberduck.core.exception.AccessDeniedException;
6 import ch.cyberduck.core.exception.LocalAccessDeniedException;
7 import ch.cyberduck.core.local.Application;
8 import ch.cyberduck.core.local.ApplicationFinder;
9 import ch.cyberduck.core.local.ApplicationFinderFactory;
10 import ch.cyberduck.core.preferences.Preferences;
11 import ch.cyberduck.core.preferences.PreferencesFactory;
13 import org.apache.commons.lang3.StringUtils;
14 import org.apache.log4j.Logger;
15 import org.rococoa.ObjCObjectByReference;
17 import java.text.MessageFormat;
19 /**
20 * @version $Id$
22 public class ApplescriptTerminalService implements TerminalService {
23 private static final Logger log = Logger.getLogger(ApplescriptTerminalService.class);
25 private ApplicationFinder finder
26 = ApplicationFinderFactory.get();
28 private Preferences preferences
29 = PreferencesFactory.get();
31 @Override
32 public void open(final Host host, final Path workdir) throws AccessDeniedException {
33 final boolean identity = host.getCredentials().isPublicKeyAuthentication();
34 final Application application
35 = finder.getDescription(preferences.getProperty("terminal.bundle.identifier"));
36 if(!finder.isInstalled(application)) {
37 log.error(String.format("Application with bundle identifier %s is not installed",
38 preferences.getProperty("terminal.bundle.identifier")));
40 String ssh = MessageFormat.format(preferences.getProperty("terminal.command.ssh"),
41 identity ? String.format("-i \"%s\"", host.getCredentials().getIdentity().getAbsolute()) : StringUtils.EMPTY,
42 host.getCredentials().getUsername(),
43 host.getHostname(),
44 String.valueOf(host.getPort()), this.escape(workdir.getAbsolute()));
45 if(log.isInfoEnabled()) {
46 log.info(String.format("Excecute SSH command %s", ssh));
48 // Escape
49 ssh = StringUtils.replace(ssh, "\\", "\\\\");
50 // Escape all " for do script command
51 ssh = StringUtils.replace(ssh, "\"", "\\\"");
52 if(log.isInfoEnabled()) {
53 log.info("Escaped SSH Command for Applescript:" + ssh);
55 String command
56 = "tell application \"" + application.getName() + "\""
57 + "\n"
58 + "activate"
59 + "\n"
60 + MessageFormat.format(preferences.getProperty("terminal.command"), ssh)
61 + "\n"
62 + "end tell";
63 if(log.isInfoEnabled()) {
64 log.info(String.format("Execute AppleScript %s", command));
66 final NSAppleScript as = NSAppleScript.createWithSource(command);
67 final ObjCObjectByReference error = new ObjCObjectByReference();
68 if(null == as.executeAndReturnError(error)) {
69 final NSDictionary d = error.getValueAs(NSDictionary.class);
70 throw new LocalAccessDeniedException(String.format("Failure running script in %s. %s",
71 application.getName(), d.objectForKey("NSAppleScriptErrorBriefMessage")));
75 protected String escape(final String path) {
76 final StringBuilder escaped = new StringBuilder();
77 for(char c : path.toCharArray()) {
78 if(StringUtils.isAlphanumeric(String.valueOf(c))) {
79 escaped.append(c);
81 else {
82 escaped.append("\\").append(c);
85 return escaped.toString();