diff --git a/shell/HTERM.md b/shell/HTERM.md deleted file mode 100644 index f967176f22a..00000000000 --- a/shell/HTERM.md +++ /dev/null @@ -1,197 +0,0 @@ - - -Original link: https://chromium.googlesource.com/apps/libapps/+/HEAD/hterm - -# Embedding hterm - - -This is a quick overview describing how to use hterm in your own application. Please direct any questions to the [chromium-hterm mailing list](https://groups.google.com/a/chromium.org/forum/?fromgroups#!forum/chromium-hterm). - -## Get the code - -The “libapps” git repository contains hterm and its dependencies. Clone this repo into a parent directory of your choice. In this example we'll create `~/src/libapps/`: - -``` -$ mkdir ~/src -$ cd ~/src -$ git clone https://chromium.googlesource.com/apps/libapps -``` - -## Build hterm - -The build process bundles some resources as JavaScript source and concatenates the JavaScript into a single file (`hterm_all.js`). - -``` -$ cd ~/src/libapps -$ ./hterm/bin/mkdist.sh -``` - -The files are all written to `./hterm/dist/js/`. Copy the `hterm_all.js` file into your project. - -## Include hterm in your app - -Include the generated `hterm_all.js` file in your app in an appropriate manner. This step should be self evident. - -## Initialize hterm - -### Terminal node - -You'll want a sacrificial DOM node which will become the terminal widget. It should be a div which is either `position: relative` or `position: absolute`. - -In our example, we'll assume this DOM: - -``` - - - -
- - -``` - -### Runtime storage - -You'll need to choose a storage implementation. This is the backing store that hterm will use to read and write preferences. This should be one of: - -``` -// If you are a cross-browser web app and want to use window.localStorage. -hterm.defaultStorage = new lib.Storage.Local(); - -// If you are a cross-browser web app and want in-memory storage only. -hterm.defaultStorage = new lib.Storage.Memory(); - -// If you are a Chrome app and want sync storage. -hterm.defaultStorage = new lib.Storage.Chrome(chrome.storage.sync); - -// If you are a Chrome app and want local storage. -hterm.defaultStorage = new lib.Storage.Chrome(chrome.storage.local); -``` - -### Framework initialization - -Before using hterm, you'll need to initialize the underlying libdot framework. You do this by calling `lib.init` and passing it your initialization callback. - -``` -function setupHterm() { - ... your hterm initialization logic ... -} - -// This will be whatever normal entry/initialization point your project uses. -window.onload = function() { - lib.init(setupHterm); -}; -``` - -### Terminal initialization - -All of the logic below lives within the `setupHterm` callback. - -Create an instance of `hterm.Terminal`: - -``` -// opt_profileName is the name of the terminal profile to load, or "default" if -// not specified. If you're using one of the persistent storage -// implementations then this will scope all preferences read/writes to this -// name. -const t = new hterm.Terminal(opt_profileName); -``` - -Now write an `onTerminalReady` handler. This will fire once, when the terminal is initialized and ready for use. - -``` -t.onTerminalReady = function() { - // Create a new terminal IO object and give it the foreground. - // (The default IO object just prints warning messages about unhandled - // things to the the JS console.) - const io = t.io.push(); - - io.onVTKeystroke = (str) => { - // Do something useful with str here. - // For example, Secure Shell forwards the string onto the NaCl plugin. - }; - - io.sendString = (str) => { - // Just like a keystroke, except str was generated by the terminal itself. - // For example, when the user pastes a string. - // Most likely you'll do the same thing as onVTKeystroke. - }; - - io.onTerminalResize = (columns, rows) => { - // React to size changes here. - // Secure Shell pokes at NaCl, which eventually results in - // some ioctls on the host. - }; - - // You can call io.push() to foreground a fresh io context, which can - // be uses to give control of the terminal to something else. When that - // thing is complete, should call io.pop() to restore control to the - // previous io object. -}; -``` - -After you've registered your onTerminalReady handler you can connect the terminal to the sacrificial DOM node. - -``` -t.decorate(document.querySelector('#terminal')); -``` - -### Keyboard setup - -After you call the `decorate` helper, you'll usually call `installKeyboard` to capture all keyboard input when the terminal is focused. This allows us to react to keyboard shortcuts and such. - -``` -t.installKeyboard(); -``` - -## Write to the terminal - -Once `onTerminalReady` finishes, you're free to start writing content! This is the process or connection that wants to display content to the user (rather than the user sending content). - -``` -t.io.print('Print a string without a newline'); -t.io.println('Print a string and add CRLF'); -``` - -You usually want to go through the `io` object to display content rather than going directly through the terminal. It will take care of encoding UTF-16 to UTF-8 and then sending it via `t.interpret` (which processes escape sequences). If you use the `t.print` function directly, it won't do either of those things, which might be what you want. - -## Encoding - -Modern applications need to make sure they handle data encoding properly at all times lest we end up with [Mojibake](https://en.wikipedia.org/wiki/Mojibake) everywhere. All data going in & out of hterm is via the `hterm.Terminal.IO` object (which may be accessed via `t.io` in the code snippets above). - -### hterm->app - -When hterm passes data to the application (via the `onVTKeystroke` and `sendString` callbacks), it uses [UTF-16](https://en.wikipedia.org/wiki/UTF-16) in native JavaScript strings. The application should then convert it to whatever encoding it expects. - -A common example when working with [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) is to convert the string to an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBuffer) with [UTF-8](https://en.wikipedia.org/wiki/UTF-8) encoding. This is easily accomplished with the [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) API. - -``` -const encoder = new TextEncoder(); -const ws = new WebSocket(...); -... - io.onVTKeystroke = (str) => { - ws.send(encoder.encode(str)); - }; -``` - -Note: <=hterm-1.83 offered a `send-encoding` preference where you could select between `utf-8` and `raw` settings. The `utf-8` mode would encode [UTF-8](https://en.wikipedia.org/wiki/UTF-8) [code unit](https://en.wikipedia.org/wiki/Character_encoding)s into a JS [UTF-16](https://en.wikipedia.org/wiki/UTF-16) string while the `raw` mode would pass through the [UTF-16](https://en.wikipedia.org/wiki/UTF-16) string unmodified. With >=hterm-1.84, the `send-encoding` preference has been dropped and hterm always runs in the equivalent `raw` mode. - -### app->hterm - -When passing data to hterm to interpret, strings should be in [UTF-16](https://en.wikipedia.org/wiki/UTF-16) encoding. This covers `hterm.Terminal.IO`'s `print`, `writeUTF16`, `println`, and `writelnUTF16` APIs as well as `hterm.Terminal`'s `interpret`. - -A few APIs are also provided to pass in [UTF-16](https://en.wikipedia.org/wiki/UTF-16) strings with [UTF-8](https://en.wikipedia.org/wiki/UTF-8) [code unit](https://en.wikipedia.org/wiki/Character_encoding)s, but those are deprecated and should be avoided. This covers `hterm.Terminal.IO`'s `writeUTF8` and `writelnUTF8` APIs. - -Note: <=hterm-1.84 required `hterm.Terminal.interpret`'s argument to be a string of [UTF-8](https://en.wikipedia.org/wiki/UTF-8) [code unit](https://en.wikipedia.org/wiki/Character_encoding)s when the `receive-encoding` was set to `utf-8`. With >=hterm-1.85, `hterm.Terminal.interpret` always uses [UTF-16](https://en.wikipedia.org/wiki/UTF-16) strings. diff --git a/shell/PTY4J.md b/shell/PTY4J.md deleted file mode 100644 index cb07476510b..00000000000 --- a/shell/PTY4J.md +++ /dev/null @@ -1,135 +0,0 @@ - - -Original link: https://github.com/JetBrains/pty4j - -# Pty4J - Pseudo terminal(PTY) implementation in Java. - -[![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) - - -[![Build Status](https://travis-ci.com/traff/pty4j.svg?branch=master)](https://travis-ci.com/JetBrains/pty4j) - -This is a Java implementation of PTY. Written in JNA with native code to make fork of a process. - -It is based on two projects that provide the same functionality: [JPty](https://github.com/jawi/JPty) -and [elt](https://code.google.com/p/elt/). - -While JPty is pretty good and written using only JNA it suffers from a -hang on Mac OS X when Java is under debug (https://github.com/jawi/JPty/issues/2), because -fork doesn't work well in java. - -elt works ok, but it has mostly native code(using JNI). - -So this one is a mix of the other two: a port of elt to JNA in the style it is made in JPty with only -fork and process exec written in native. - -Also pty4j implements java interface for pty for windows, using [WinPty](https://github.com/rprichard/winpty) library. - -## Dependencies - -This library depends on JTermios, part of the PureJavaComm library found at -. Pty4j depends on the version of PureJavaComm, -not uploaded to [the maven central](https://search.maven.org/artifact/com.github.purejavacomm/purejavacomm). -It'a available as [org.jetbrains.pty4j:purejavacomm](https://bintray.com/jetbrains/pty4j/org.jetbrains.pty4j%3Apurejavacomm). - -Windows pty implementation used here is the magnificent WinPty library written by Ryan Prichard: https://github.com/rprichard/winpty - -## Adding Pty4J to your build - -The releases are uploaded to [org.jetbrains.pty4j:pty4j](https://bintray.com/jetbrains/pty4j/org.jetbrains.pty4j%3Apty4j). -Please click on the "Set Me Up!" button there and follow the instructions. - -### Maven - -``` - - - org.jetbrains.pty4j - pty4j - 0.8.6 - - - - - - bintray-jetbrains-pty4j - bintray - https://jetbrains.bintray.com/pty4j - - -``` - -### Gradle - -``` -repositories { - maven { - url "https://jetbrains.bintray.com/pty4j" - } -} - -// or use jcenter -// repositories { -// jcenter() -// } - -dependencies { - compile 'org.jetbrains.pty4j:pty4j:0.8.6' -} -``` - -## Usage - -Using this library is relatively easy: - - // The command to run in a PTY... - String[] cmd = { "/bin/sh", "-l" }; - // The initial environment to pass to the PTY child process... - String[] env = { "TERM=xterm" }; - - PtyProcess pty = PtyProcess.exec(cmd, env); - - OutputStream os = pty.getOutputStream(); - InputStream is = pty.getInputStream(); - - // ... work with the streams ... - - // wait until the PTY child process terminates... - int result = pty.waitFor(); - - // free up resources. - pty.close(); - -The operating systems currently supported by pty4j are: Linux, OSX and -Windows. - -**Note that this library is not yet fully tested on all platforms.** - -## Changes - - 0.8 | 28-08-2018 | Native binaries are bundled into pty4j.jar - 0.7 | 14-06-2016 | Updated to match the new winpty API - 0.6 | 08-02-2016 | Correct NamedPipe usage for winpty - FreeBSD support - 0.5 | 28-09-2015 | Supports JNA 4.1, Cygwin support, fixes - 0.4 | 13-01-2015 | Fixes - 0.3 | 16-08-2013 | Native code for fork and process exec. - 0.2 | 03-08-2013 | Linux and Windows supported. - 0.1 | 20-07-2013 | Initial version. - -## License - -The code in this library is licensed under Eclipse Public License, version -1.0 and can be found online at: . diff --git a/shell/pom.xml b/shell/pom.xml index 66fdb378684..c5c4db0bf4b 100644 --- a/shell/pom.xml +++ b/shell/pom.xml @@ -35,7 +35,7 @@ sh - 0.9.3 + 0.12.10-jdk8 2.4.0 32.0.0-jre diff --git a/shell/src/main/java/org/apache/zeppelin/shell/terminal/helper/IOHelper.java b/shell/src/main/java/org/apache/zeppelin/shell/terminal/helper/IOHelper.java deleted file mode 100644 index d0349d75c51..00000000000 --- a/shell/src/main/java/org/apache/zeppelin/shell/terminal/helper/IOHelper.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.zeppelin.shell.terminal.helper; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class IOHelper { - private static final Logger LOGGER = LoggerFactory.getLogger(IOHelper.class); - - public static void close(Closeable... closables) { - for (Closeable closable : closables) { - try { - closable.close(); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - } - } - } - - public static synchronized void copyLibPty(Path dataDir) throws IOException { - Path donePath = dataDir.resolve(".DONE"); - - if (Files.exists(donePath)) { - return; - } - - String jarPath = getClassPath(IOHelper.class) + File.separator; - Set nativeFiles = getNativeFiles(); - for (String nativeFile : nativeFiles) { - Path nativePath = dataDir.resolve(nativeFile); - - if (Files.notExists(nativePath)) { - Files.createDirectories(nativePath.getParent()); - InputStream inputStream = IOHelper.class.getResourceAsStream("/" + nativeFile); - if (null == inputStream) { - Path source = Paths.get(jarPath + nativeFile); - if (!Files.exists(source)) { - throw new IOException("Can't find pytlib file : " + jarPath + nativeFile); - } else { - LOGGER.info("Use the pytlib file {} outside the JAR package.", jarPath + nativeFile); - } - Files.copy(source, nativePath); - } else { - LOGGER.info("Use the libpty file {} in the JAR package resource.", nativeFile); - Files.copy(inputStream, nativePath); - close(inputStream); - } - } - } - - Files.createFile(donePath); - } - - private static Set getNativeFiles() { - final Set nativeFiles = new HashSet<>(); - - List freebsd = Arrays.asList( - "libpty/freebsd/x86/libpty.so", "libpty/freebsd/x86_64/libpty.so"); - List linux = Arrays.asList( - "libpty/linux/x86/libpty.so", "libpty/linux/x86_64/libpty.so"); - List macosx = Arrays.asList( - "libpty/macosx/x86/libpty.dylib", "libpty/macosx/x86_64/libpty.dylib"); - List win_x86 = Arrays.asList( - "libpty/win/x86/winpty.dll", "libpty/win/x86/winpty-agent.exe"); - List win_x86_64 = Arrays.asList( - "libpty/win/x86_64/winpty.dll", "libpty/win/x86_64/winpty-agent.exe", - "libpty/win/x86_64/cyglaunch.exe"); - List win_xp = Arrays.asList( - "libpty/win/xp/winpty.dll", "libpty/win/xp/winpty-agent.exe"); - - nativeFiles.addAll(freebsd); - nativeFiles.addAll(linux); - nativeFiles.addAll(macosx); - nativeFiles.addAll(win_x86); - nativeFiles.addAll(win_x86_64); - nativeFiles.addAll(win_xp); - - return nativeFiles; - } - - private static String getClassPath(Class clazz) throws UnsupportedEncodingException { - // Check if the parameters passed in by the user are empty - if (clazz == null) { - throw new java.lang.IllegalArgumentException("The parameter cannot be empty!"); - } - - ClassLoader loader = clazz.getClassLoader(); - // Get the full name of the class, including the package name - String clsName = clazz.getName() + ".class"; - // Get the package where the incoming parameters are located - Package pack = clazz.getPackage(); - String path = ""; - // If not an anonymous package, convert the package name to a path - if (pack != null) { - String packName = pack.getName(); - // Here is a simple decision to determine whether it is a Java base class library, - // preventing users from passing in the JDK built-in class library. - if (packName.startsWith("java.") || packName.startsWith("javax.")) { - throw new java.lang.IllegalArgumentException("Do not transfer system classes!"); - } - - // In the name of the class, remove the part of the package name - // and get the file name of the class. - clsName = clsName.substring(packName.length() + 1); - // Determine whether the package name is a simple package name, and if so, - // directly convert the package name to a path. - if (packName.indexOf(".") < 0) { - path = packName + "/"; - } else { - // Otherwise, the package name is converted to a path according - // to the component part of the package name. - int start = 0, end = 0; - end = packName.indexOf("."); - while (end != -1) { - path = path + packName.substring(start, end) + "/"; - start = end + 1; - end = packName.indexOf(".", start); - } - path = path + packName.substring(start) + "/"; - } - } - // Call the classReloader's getResource method, passing in the - // class file name containing the path information. - java.net.URL url = loader.getResource(path + clsName); - // Get path information from the URL object - String realPath = url.getPath(); - // Remove the protocol name "file:" in the path information. - int pos = realPath.indexOf("file:"); - if (pos > -1) { - realPath = realPath.substring(pos + 5); - } - // Remove the path information and the part that contains the class file information, - // and get the path where the class is located. - pos = realPath.indexOf(path + clsName); - realPath = realPath.substring(0, pos - 1); - // If the class file is packaged into a JAR file, etc., - // remove the corresponding JAR and other package file names. - if (realPath.endsWith("!")) { - realPath = realPath.substring(0, realPath.lastIndexOf("/")); - } - - try { - realPath = java.net.URLDecoder.decode(realPath, "utf-8"); - } catch (UnsupportedEncodingException e) { - LOGGER.error(e.getMessage(), e); - } - - return realPath; - } - -} diff --git a/shell/src/main/java/org/apache/zeppelin/shell/terminal/service/TerminalService.java b/shell/src/main/java/org/apache/zeppelin/shell/terminal/service/TerminalService.java index bdc5762cee8..f7d3c13f9d0 100644 --- a/shell/src/main/java/org/apache/zeppelin/shell/terminal/service/TerminalService.java +++ b/shell/src/main/java/org/apache/zeppelin/shell/terminal/service/TerminalService.java @@ -19,9 +19,9 @@ import com.google.gson.Gson; import com.pty4j.PtyProcess; +import com.pty4j.PtyProcessBuilder; import com.pty4j.WinSize; import org.apache.commons.lang3.StringUtils; -import org.apache.zeppelin.shell.terminal.helper.IOHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,8 +31,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -69,10 +67,6 @@ public void onTerminalReady() { private void initializeProcess() throws Exception { LOGGER.info("initialize TerminalService Process"); - String userHome = System.getProperty("user.home"); - Path dataDir = Paths.get(userHome).resolve(".terminalfx"); - IOHelper.copyLibPty(dataDir); - boolean isWindows = System.getProperty("os.name").startsWith("Windows"); if (isWindows) { this.termCommand = "cmd.exe".split("\\s+"); @@ -83,9 +77,7 @@ private void initializeProcess() throws Exception { Map envs = new HashMap<>(System.getenv()); envs.put("TERM", "xterm"); - System.setProperty("PTY_LIB_FOLDER", dataDir.resolve("libpty").toString()); - - this.process = PtyProcess.exec(termCommand, envs, userHome); + this.process = new PtyProcessBuilder().setCommand(termCommand).setEnvironment(envs).start(); process.setWinSize(new WinSize(columns, rows)); this.inputReader = new BufferedReader(new InputStreamReader(process.getInputStream())); diff --git a/shell/src/main/resources/libpty/freebsd/x86/libpty.so b/shell/src/main/resources/libpty/freebsd/x86/libpty.so deleted file mode 100755 index 962272cae7c..00000000000 Binary files a/shell/src/main/resources/libpty/freebsd/x86/libpty.so and /dev/null differ diff --git a/shell/src/main/resources/libpty/freebsd/x86_64/libpty.so b/shell/src/main/resources/libpty/freebsd/x86_64/libpty.so deleted file mode 100755 index 8a0b896b887..00000000000 Binary files a/shell/src/main/resources/libpty/freebsd/x86_64/libpty.so and /dev/null differ diff --git a/shell/src/main/resources/libpty/linux/ppc64le/libpty.so b/shell/src/main/resources/libpty/linux/ppc64le/libpty.so deleted file mode 100755 index 37966c30673..00000000000 Binary files a/shell/src/main/resources/libpty/linux/ppc64le/libpty.so and /dev/null differ diff --git a/shell/src/main/resources/libpty/linux/x86/libpty.so b/shell/src/main/resources/libpty/linux/x86/libpty.so deleted file mode 100644 index 6bfa7bfcfea..00000000000 Binary files a/shell/src/main/resources/libpty/linux/x86/libpty.so and /dev/null differ diff --git a/shell/src/main/resources/libpty/linux/x86_64/libpty.so b/shell/src/main/resources/libpty/linux/x86_64/libpty.so deleted file mode 100644 index 4c3a87c3f05..00000000000 Binary files a/shell/src/main/resources/libpty/linux/x86_64/libpty.so and /dev/null differ diff --git a/shell/src/main/resources/libpty/macosx/x86/libpty.dylib b/shell/src/main/resources/libpty/macosx/x86/libpty.dylib deleted file mode 100644 index cf48e925e7e..00000000000 Binary files a/shell/src/main/resources/libpty/macosx/x86/libpty.dylib and /dev/null differ diff --git a/shell/src/main/resources/libpty/macosx/x86_64/libpty.dylib b/shell/src/main/resources/libpty/macosx/x86_64/libpty.dylib deleted file mode 100644 index 1427ea07f59..00000000000 Binary files a/shell/src/main/resources/libpty/macosx/x86_64/libpty.dylib and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/x86/winpty-agent.exe b/shell/src/main/resources/libpty/win/x86/winpty-agent.exe deleted file mode 100644 index 29355980ddc..00000000000 Binary files a/shell/src/main/resources/libpty/win/x86/winpty-agent.exe and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/x86/winpty.dll b/shell/src/main/resources/libpty/win/x86/winpty.dll deleted file mode 100755 index 9379c9c1d01..00000000000 Binary files a/shell/src/main/resources/libpty/win/x86/winpty.dll and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/x86_64/cyglaunch.exe b/shell/src/main/resources/libpty/win/x86_64/cyglaunch.exe deleted file mode 100644 index d84e6e964c1..00000000000 Binary files a/shell/src/main/resources/libpty/win/x86_64/cyglaunch.exe and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/x86_64/winpty-agent.exe b/shell/src/main/resources/libpty/win/x86_64/winpty-agent.exe deleted file mode 100644 index b5abdeee385..00000000000 Binary files a/shell/src/main/resources/libpty/win/x86_64/winpty-agent.exe and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/x86_64/winpty.dll b/shell/src/main/resources/libpty/win/x86_64/winpty.dll deleted file mode 100644 index 208cef3e3b1..00000000000 Binary files a/shell/src/main/resources/libpty/win/x86_64/winpty.dll and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/xp/winpty-agent.exe b/shell/src/main/resources/libpty/win/xp/winpty-agent.exe deleted file mode 100755 index f78a0658a2e..00000000000 Binary files a/shell/src/main/resources/libpty/win/xp/winpty-agent.exe and /dev/null differ diff --git a/shell/src/main/resources/libpty/win/xp/winpty.dll b/shell/src/main/resources/libpty/win/xp/winpty.dll deleted file mode 100755 index 098ecae3783..00000000000 Binary files a/shell/src/main/resources/libpty/win/xp/winpty.dll and /dev/null differ