package com.bc.process.util; import java.io.OutputStream; import java.io.IOException; /** * This processObserver waits for the first ':' on a process's output stream and interprets this as a * password prompt. The prompt is answered by providing the password to the given outputStream. * Note that Input- and OutputStream are non-intuitive in java.lang.Process - processOutputStream * (from the perspective of this application and java.lang.Process) translates to the * process's stdin stream. * This Observer is used (for example) when external processes (like oracle's sqlplus) need to * know a password in order to connect to a database, but the password must not be given on the * commandline. Note that the complete commandline might be visible to all users of a system * (on unix via ps), therefor no password should be given on the commandline but only via stdin. * * This code is copied from EnterPasswordProcessObserver and enhanced by some code to answer more * sqlplus questions if connection could not be established. Otherwise the process would block waiting * for more input. * * This is some sample output from sqlplus when oracle is unreachable (given an 'ENTER' on every * prompt sqlplus displays). Similar output is done when the tns name is unknown etc.: * <code> * SQL*Plus: Release 10.2.0.1.0 - Production on Di Okt 4 10:57:05 2005 * Copyright (c) 1982, 2005, Oracle. All rights reserved. * * Kennwort eingeben: * ERROR: * ORA-12170: TNS: Connect Timeout aufgetreten * * * Benutzernamen eingeben: * ERROR: * ORA-12560: TNS: Fehler bei Protokolladapter * * * Benutzernamen eingeben: * ERROR: * ORA-12560: TNS: Fehler bei Protokolladapter * * * SP2-0157: CONNECT-Versuch zu ORACLE nach 3 Versuchen aufgegeben, SQL*Plus wird verlassen * </code> * @see EnterPasswordProcessObserver */ public class SqlPlusProcessObserver implements ProcessStreamObserver { private OutputStream processOutputStream; private String password; private boolean hasError = false; /** * * @param processOutputStream * @param password String to pass to the external application. Note that terminating "\n" might be needed. */ public SqlPlusProcessObserver(OutputStream processOutputStream, String password) { this.processOutputStream = processOutputStream; this.password = password; } public void processWroteToStream(String characterData) { boolean hasColon = characterData.indexOf(":")>-1; if(password != null && hasColon) { try { processOutputStream.write((password).getBytes()); processOutputStream.flush(); password = null; } catch (IOException ignore) { } } else if(hasColon) { try { processOutputStream.write("\n".getBytes()); processOutputStream.flush(); } catch (IOException ignore) { } } if(characterData.indexOf("ERROR") > -1) { hasError = true; } } public boolean hasError() { return hasError; } }