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
;
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();
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(),
44 String
.valueOf(host
.getPort()), this.escape(workdir
.getAbsolute()));
45 if(log
.isInfoEnabled()) {
46 log
.info(String
.format("Excecute SSH command %s", ssh
));
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
);
56 = "tell application \"" + application
.getName() + "\""
60 + MessageFormat
.format(preferences
.getProperty("terminal.command"), ssh
)
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
))) {
82 escaped
.append("\\").append(c
);
85 return escaped
.toString();