/*
 * Copyright 2016 Javier Garcia Alonso.
 *
 * Licensed 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 com.profesorfalken.jpowershell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Processor used to send commands to PowerShell console.<p^>
 * It works as an independent thread and its results are collected using the
 * Future interface.
 *
 * @author Javier Garcia Alonso
 */
class PowerShellCommandProcessor implements Callable {

    private static final String CRLF = "\r\n";

    private final BufferedReader reader;
    private volatile boolean checkTimeout;
    private final String name;

    /**
     * Constructor that takes the output and the input of the PowerShell session
     *
     * @param commandWriter the input to the PowerShell console
     * @param inputStream the stream needed to read the command output
     */
    public PowerShellCommandProcessor(String name, PrintWriter commandWriter, InputStream inputStream, boolean checkTimeout) {
        this.reader = new BufferedReader(new InputStreamReader(
                inputStream));
        this.checkTimeout = checkTimeout;
        this.name = name;
    }

    /**
     * Calls the command and returns its output
     *
     * @return
     * @throws IOException
     */
    @Override
    public String call() throws IOException, InterruptedException {
        String line;
        StringBuilder powerShellOutput = new StringBuilder();

        synchronized(this) {
            if (startReading()) {
                while (null != (line = this.reader.readLine())) {
                    powerShellOutput.append(line).append(CRLF);
                    try {
                        if (!continueReading()) {
                            break;
                        }
                    } catch (InterruptedException ex) {
                        Logger.getLogger(PowerShellCommandProcessor.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }

        return powerShellOutput.toString();
    }

    //Checks when we can start reading the output. Timeout if it takes too long in order to avoid hangs
    private boolean startReading() throws IOException, InterruptedException {
        int timeWaiting = 0;

        while (!this.reader.ready()) {
            Thread.sleep(PowerShell.WAIT_PAUSE);
            timeWaiting += PowerShell.WAIT_PAUSE;
            if (checkTimeout && timeWaiting > PowerShell.MAX_WAIT) {
                return false;
            }
        }
        return true;
    }

    //Checks when we the reader can continue to read.
    private boolean continueReading() throws IOException, InterruptedException {
        Thread.sleep(PowerShell.WAIT_PAUSE);
        return this.reader.ready();
    }
}

@@ -1252,16 +1252,13 @@
 ate 
-volatile
+final
  boo
@@ -1306,16 +1306,143 @@
 ng name;
+%0A    %0A    //Create static lock in order to synchronize the reading process%0A    private static final Object LOCK = new Object();
 %0A%0A    /*
@@ -2271,20 +2271,20 @@
 ronized(
-this
+LOCK
 ) %7B%0A    

Create static lock in order to synchronize the reading process