--- /dev/null 2015-04-26 06:51:08.003313989 -0700 +++ new/jdk/src/jdk.jline/share/classes/jdk/internal/jline/TerminalFactory.java 2015-06-18 03:05:10.692852244 -0700 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jline; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import jline.internal.Configuration; +import jline.internal.Log; +import jline.internal.Preconditions; + +import static jline.internal.Preconditions.checkNotNull; + +/** + * Creates terminal instances. + * + * @author Jason Dillon + * @since 2.0 + */ +public class TerminalFactory +{ + public static final String JLINE_TERMINAL = "jline.terminal"; + + public static final String AUTO = "auto"; + + public static final String UNIX = "unix"; + + public static final String WIN = "win"; + + public static final String WINDOWS = "windows"; + + public static final String NONE = "none"; + + public static final String OFF = "off"; + + public static final String FALSE = "false"; + + private static Terminal term = null; + + public static synchronized Terminal create() { + if (Log.TRACE) { + //noinspection ThrowableInstanceNeverThrown + Log.trace(new Throwable("CREATE MARKER")); + } + + String type = Configuration.getString(JLINE_TERMINAL, AUTO); + if ("dumb".equals(System.getenv("TERM"))) { + type = "none"; + Log.debug("$TERM=dumb; setting type=", type); + } + + Log.debug("Creating terminal; type=", type); + + Terminal t; + try { + String tmp = type.toLowerCase(); + + if (tmp.equals(UNIX)) { + t = getFlavor(Flavor.UNIX); + } + else if (tmp.equals(WIN) | tmp.equals(WINDOWS)) { + t = getFlavor(Flavor.WINDOWS); + } + else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) { + t = new UnsupportedTerminal(); + } + else { + if (tmp.equals(AUTO)) { + String os = Configuration.getOsName(); + Flavor flavor = Flavor.UNIX; + if (os.contains(WINDOWS)) { + flavor = Flavor.WINDOWS; + } + t = getFlavor(flavor); + } + else { + try { + t = (Terminal) Thread.currentThread().getContextClassLoader().loadClass(type).newInstance(); + } + catch (Exception e) { + throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e); + } + } + } + } + catch (Exception e) { + Log.error("Failed to construct terminal; falling back to unsupported", e); + t = new UnsupportedTerminal(); + } + + Log.debug("Created Terminal: ", t); + + try { + t.init(); + } + catch (Throwable e) { + Log.error("Terminal initialization failed; falling back to unsupported", e); + return new UnsupportedTerminal(); + } + + return t; + } + + public static synchronized void reset() { + term = null; + } + + public static synchronized void resetIf(final Terminal t) { + if(t == term) { + reset(); + } + } + + public static enum Type + { + AUTO, + WINDOWS, + UNIX, + NONE + } + + public static synchronized void configure(final String type) { + checkNotNull(type); + System.setProperty(JLINE_TERMINAL, type); + } + + public static synchronized void configure(final Type type) { + checkNotNull(type); + configure(type.name().toLowerCase()); + } + + // + // Flavor Support + // + + public static enum Flavor + { + WINDOWS, + UNIX + } + + private static final Map> FLAVORS = new HashMap>(); + + static { + registerFlavor(Flavor.WINDOWS, AnsiWindowsTerminal.class); + registerFlavor(Flavor.UNIX, UnixTerminal.class); + } + + public static synchronized Terminal get() { + if (term == null) { + term = create(); + } + return term; + } + + public static Terminal getFlavor(final Flavor flavor) throws Exception { + Class type = FLAVORS.get(flavor); + if (type != null) { + return type.newInstance(); + } + + throw new InternalError(); + } + + public static void registerFlavor(final Flavor flavor, final Class type) { + FLAVORS.put(flavor, type); + } + +}