All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.derby.ExecSupport Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * 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.
 */
/*
 * ExecSupport.java
 *
 * Created on March 5, 2004, 12:57 PM
 */

package org.netbeans.modules.derby;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.windows.*;
/**
 *
 * @author  ludo
 */
public class ExecSupport {

    private String lookFor;
    private OutputCopier[] copyMakers;
    private Thread t;
    private Connect connect;
    private Map outputStringHandlers = null;
    private String displayName;
    private Process child;

    /** Creates a new instance of ExecSupport */
    public ExecSupport(final Process child, String displayName) {
        this.displayName = displayName;
        this.child = child;
    }

    /**
     * Redirect the standard output and error streams of the child process to an
     * output window.
     */
    public void start() {
        // Get a tab on the output window.  If this client has been
        // executed before, the same tab will be returned.
        InputOutput io = org.openide.windows.IOProvider.getDefault().getIO(
            displayName, false);
        try {
            io.getOut().reset();
        }
        catch (IOException e) {
            // not a critical error, continue
            Logger.getLogger("global").log(Level.INFO, null, e);
        }
        io.select();
        copyMakers = new OutputCopier[3];
        (copyMakers[0] = new OutputCopier(new InputStreamReader(child.getInputStream()), io.getOut(), true, lookFor, outputStringHandlers)).start();
        (copyMakers[1] = new OutputCopier(new InputStreamReader(child.getErrorStream()), io.getErr(), true, lookFor, outputStringHandlers)).start();
        (copyMakers[2] = new OutputCopier(io.getIn(), new OutputStreamWriter(child.getOutputStream()), true)).start();
        new Thread() {
            @Override
            public void run() {
                try {
                    int ret = child.waitFor();
                    Thread.sleep(2000);  // time for copymakers
                } catch (InterruptedException e) {
                } finally {
                    try {
                        copyMakers[0].interrupt();
                        copyMakers[1].interrupt();
                        copyMakers[2].interrupt();
                    } catch (Exception e) {
                        Logger.getLogger("global").log(Level.INFO, null, e);
                    }
                }
            }
        }.start();
    }
    
    public void setStringToLookFor(String lookFor) {
        this.lookFor = lookFor;
    }
    
    /**
     * Add an output string handler. If the specified string will be found in
     * the output stream, the handler will be invoked.
     *
     * @param string
     * @param handler
     */
    public void addOutputStringHandler(String string, Runnable handler) {
        if (outputStringHandlers == null) {
            outputStringHandlers = new HashMap<>();
        }
        outputStringHandlers.put(string, handler);
    }

    public boolean isStringFound() {
        if (copyMakers == null) {
            return false;
        }
        return (copyMakers[0].stringFound() ||
                copyMakers[1].stringFound() ||
                copyMakers[2].stringFound());
    }
    
    /** This thread simply reads from given Reader and writes read chars to given Writer. */
    public static  class OutputCopier extends Thread {
        final Writer os;
        final Reader is;
        /** while set to false at streams that writes to the OutputWindow it must be
         * true for a stream that reads from the window.
         */
        final boolean autoflush;
        private boolean done = false;
        private String stringToLookFor;
        private boolean stringFound = false;
        private Map outputStreamHandlers;
        
        private static final int FOUND = SearchUtil.FOUND;
        
        public OutputCopier(Reader is, Writer os, boolean b, String lookFor,
                Map outputStreamHandlers) {
            this.os = os;
            this.is = is;
            autoflush = b;
            this.stringToLookFor = lookFor;
            this.outputStreamHandlers = outputStreamHandlers;
        }
        
        public OutputCopier(Reader is, Writer os, boolean b) {
            this(is, os, b, null, null);
        }
        
        public boolean stringFound() {
            return stringFound;
        }
        
        /* Makes copy. */
        @Override
        public void run() {
            int read;
            int stringFoundChars = 0;
            Map stringFoundCharsMap
                    = outputStreamHandlers != null
                    ? new HashMap() : null;
            char[] buff = new char [256];
            try {
                while ((read = read(is, buff, 0, 256)) > 0x0) {
                    if (stringToLookFor != null) {
                        stringFoundChars = SearchUtil.checkForString(stringToLookFor, stringFoundChars, buff, read);
                        if (stringFoundChars == FOUND) {
                            stringToLookFor = null;
                            stringFound = true;
                        }
                    }
                    if (outputStreamHandlers != null) {
                        checkOutputHandlers(stringFoundCharsMap, buff, read);
                    }
                    if (os!=null){
                        os.write(buff,0,read);
                        if (autoflush) {
                            os.flush();
                        }
                    }
                }
            } catch (IOException | InterruptedException ex) {
            }
        }

        /**
         * Check whether the output contains some strings for which a handler
         * should be invoked.
         *
         * @param stringFoundCharsMap Map of pairs [string, prefix found
         * in previous iterations.]
         * @param buff Buffer with the current part of the output.
         * @param read How many characters have been read into the buffer.
         */
        private void checkOutputHandlers(
                Map stringFoundCharsMap, char[] buff, int read) {
            assert outputStreamHandlers != null;
            for (Map.Entry e
                    : outputStreamHandlers.entrySet()) {
                Integer alreadyFoundOb = stringFoundCharsMap.get(
                        e.getKey());
                int alreadyFound = alreadyFoundOb == null ? 0 : alreadyFoundOb;
                int found = SearchUtil.checkForString(e.getKey(),
                        alreadyFound, buff, read);
                if (found == SearchUtil.FOUND) {
                    stringFoundCharsMap.remove(e.getKey());
                    e.getValue().run();
                } else if (found > 0) {
                    stringFoundCharsMap.put(e.getKey(), found);
                } else if (found == 0) {
                    stringFoundCharsMap.remove(e.getKey());
                }
            }
        }
        
        @Override
        public void interrupt() {
            super.interrupt();
            done = true;
        }
        
        private int read(Reader is, char[] buff, int start, int count) throws InterruptedException, IOException {
            
            while (!is.ready() && !done) {
                sleep(100);
            }
            
            return is.read(buff, start, count);
        }

    }

    /** Waits for startup of a server, waits until the message set through the setStringToLookFor() method. 
     *  @param timeout timeout
     *  @return true if the connection was successfully established, false if timed out
     */ 
    public boolean waitForMessage(int timeout) {
        int retryTime = 10;
        connect = new Connect(retryTime); 
        t = new Thread(connect);
        t.start();
        try {
            t.join(timeout);
        } catch(InterruptedException ie) {
        }
        if (t.isAlive()) {
            connect.finishLoop();
            t.interrupt();//for thread deadlock
        }
        return connect.getStatus();
    }

    public boolean interruptWaiting() {
        if (t == null) {
            return false;
        } else {
            if (t.isAlive()) {
                connect.finishLoop();
                t.interrupt();
                return true;
            } else {
                return false;
            }
        }
    }
    
    public void terminate() {
        this.child.destroy();
    }
    
    private class Connect implements Runnable  {

        int retryTime;
        boolean status = false;
        boolean loop = true;

        public Connect(int retryTime) {
            this.retryTime = retryTime; 
        } 

        public void finishLoop() {
            loop = false;
        }

        @Override
        public void run() {
            while (loop && child.isAlive()) {
                if (isStringFound()) {
                    status = true;
                    break;
                }
                try {
                    Thread.sleep(retryTime);
                } catch(InterruptedException ie) {
                }
            }
        }

        boolean getStatus() {
            return status;
        }
    }
    
    
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy