⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractshell.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
    }


    /**
     * This method creates the python server process and starts the sockets, so that we
     * can talk with the server.
     * 
     * @param milisSleep: time to wait after creating the process.
     * @throws IOException is some error happens creating the sockets - the process is terminated.
     * @throws JDTNotAvailableException 
     * @throws CoreException 
     * @throws CoreException
     */
    protected synchronized void startIt(int milisSleep) throws IOException, JDTNotAvailableException, CoreException {
    	if(inStart || isConnected){
    		//it is already in the process of starting, so, if we are in another thread, just forget about it.
    		return;
    	}
    	inStart = true;
        try {
			if (finishedForGood) {
				throw new RuntimeException(
						"Shells are already finished for good, so, it is an invalid state to try to restart it.");
			}

			try {

				int pWrite = SocketUtil.findUnusedLocalPort("127.0.0.1", 50000, 55000);
				int pRead = SocketUtil.findUnusedLocalPort("127.0.0.1", 55001, 60000);

				if (process != null) {
					endIt(); //end the current process
				}

				String execMsg = createServerProcess(pWrite, pRead);
				dbg("executing " + execMsg,1);

				sleepALittle(200);
				String osName = System.getProperty("os.name");
				if (process == null) {
					String msg = "Error creating python process - got null process(" + execMsg + ") - os:" + osName;
                    dbg(msg, 1);
                    PydevPlugin.log(msg);
					throw new CoreException(PydevPlugin.makeStatus(IStatus.ERROR, msg, new Exception(msg)));
				}
				try {
					int exitVal = process.exitValue(); //should throw exception saying that it still is not terminated...
					String msg = "Error creating python process - exited before creating sockets - exitValue = ("+ exitVal + ")(" + execMsg + ") - os:" + osName;
					dbg(msg, 1);
					PydevPlugin.log(msg);
					throw new CoreException(PydevPlugin.makeStatus(IStatus.ERROR, msg, new Exception(msg)));
				} catch (IllegalThreadStateException e2) { //this is ok
				}

				dbg("afterCreateProcess ",1);
				//ok, process validated, so, let's get its output and store it for further use.
				afterCreateProcess();

				boolean connected = false;
				int attempts = 0;

				dbg("connecting... ",1);
				sleepALittle(milisSleep);
				socketToWrite = null;
				serverSocket = new ServerSocket(pRead); //read in this port
				int maxAttempts = PyCodeCompletionPreferencesPage.getNumberOfConnectionAttempts();
				while (!connected && attempts < maxAttempts && !finishedForGood) {
					attempts += 1;
					dbg("connecting attept..."+attempts,1);
					try {
						if (socketToWrite == null || socketToWrite.isConnected() == false) {
							socketToWrite = new Socket("127.0.0.1", pWrite); //we should write in this port
						}

						if (socketToWrite != null || socketToWrite.isConnected()) {
							serverSocket.setSoTimeout(milisSleep * 2); //let's give it a higher timeout, as we're already half - connected
							try {
								socketToRead = serverSocket.accept();
                                socketToRead.setSoTimeout(5000);
								connected = true;
								dbg("connected! ",1);
							} catch (SocketTimeoutException e) {
								//that's ok, timeout for waiting connection expired, let's check it again in the next loop
							}
						}
					} catch (IOException e1) {
						if (socketToWrite != null && socketToWrite.isConnected() == true) {
							String msg = "Attempt: " + attempts + " of " + maxAttempts + 
                            " failed, trying again...(socketToWrite already binded)";
                            
							dbg(msg,1);
                            PydevPlugin.log(IStatus.ERROR, msg, e1);
						}
						if (socketToWrite != null && !socketToWrite.isConnected() == true) {
						    String msg = "Attempt: " + attempts + " of " + maxAttempts +
                            " failed, trying again...(socketToWrite still not binded)";
                            
						    dbg(msg,1);
                            PydevPlugin.log(IStatus.ERROR, msg, e1);
						}
					}

					//if not connected, let's sleep a little for another attempt
					if (!connected) {
						sleepALittle(milisSleep);
					}
				}

				if (!connected && !finishedForGood) {
					dbg("NOT connected ",1);

					//what, after all this trouble we are still not connected????!?!?!?!
					//let's communicate this to the user...
					String isAlive;
					try {
						int exitVal = process.exitValue(); //should throw exception saying that it still is not terminated...
						isAlive = " - the process in NOT ALIVE anymore (output=" + exitVal + ") - ";
					} catch (IllegalThreadStateException e2) { //this is ok
						isAlive = " - the process in still alive (killing it now)- ";
						process.destroy();
					}

					String output = getProcessOutput();
					String msg = "Error connecting to python process (" + execMsg + ") " +
                    isAlive + " the output of the process is: " + output;
                    
                    RuntimeException exception = new RuntimeException(msg);
                    dbg(msg, 1);
                    PydevPlugin.log(exception);
					throw exception;
				}

			} catch (IOException e) {

				if (process != null) {
					process.destroy();
					process = null;
				}
				throw e;
			}
		} finally {
			this.inStart = false;
		}
		
		
		//if it got here, everything went ok (otherwise we would have gotten an exception).
		isConnected = true;
    }



    private synchronized void afterCreateProcess() {
        try {
            process.getOutputStream().close(); //we won't write to it...
        } catch (IOException e2) {
        }
        
        //will print things if we are debugging or just get it (and do nothing except emptying it)
        stdReader = new ThreadStreamReader(process.getInputStream());
        errReader = new ThreadStreamReader(process.getErrorStream());
        
        stdReader.setName("Shell reader (stdout)");
        errReader.setName("Shell reader (stderr)");
        
        stdReader.start();
        errReader.start();
    }


    /**
     * @return the current output of the process
     */
    protected synchronized String getProcessOutput(){
        try {
            String output = "";
            output += "Std output:\n" + stdReader.contents.toString();
            output += "\n\nErr output:\n" + errReader.contents.toString();
            return output;
        } catch (Exception e) {
            return "Unable to get output";
        }
    }


    /**
     * @param pWrite the port where we should write
     * @param pRead the port where we should read
     * @return the command line that was used to create the process 
     * 
     * @throws IOException
     * @throws JDTNotAvailableException 
     */
    protected abstract String createServerProcess(int pWrite, int pRead) throws IOException, JDTNotAvailableException;

    protected synchronized void communicateWork(String desc, IProgressMonitor monitor) {
        if(monitor != null){
            monitor.setTaskName(desc);
            monitor.worked(1);
        }
    }

    public synchronized void clearSocket() throws IOException {
    	while(true){ //clear until we get no message...
	        byte[] b = new byte[AbstractShell.BUFFER_SIZE];
            if(this.socketToRead != null){
    	        this.socketToRead.getInputStream().read(b);
    	
    	        String s = new String(b);
    	        s = s.replaceAll((char)0+"",""); //python sends this char as payload.
    	        if(s.length() == 0){
    	        	return;
    	        }
            }
    	}        
    }

    /**
     * @param operation
     * @return
     * @throws IOException
     */
    public synchronized String read(IProgressMonitor monitor) throws IOException {
        if(finishedForGood){
            throw new RuntimeException("Shells are already finished for good, so, it is an invalid state to try to read from it.");
        }
        if(inStart){
            throw new RuntimeException("The shell is still not completely started, so, it is an invalid state to try to read from it..");
        }
        if(!isConnected){
            throw new RuntimeException("The shell is still not connected, so, it is an invalid state to try to read from it..");
        }
        if(isInRead){
            throw new RuntimeException("The shell is already in read mode, so, it is an invalid state to try to read from it..");
        }
        if(isInWrite){
            throw new RuntimeException("The shell is already in write mode, so, it is an invalid state to try to read from it..");
        }
        
        isInRead = true;

        try {
            StringBuffer str = new StringBuffer();
            int j = 0;
            while (j < 200) {
                byte[] b = new byte[AbstractShell.BUFFER_SIZE];

                this.socketToRead.getInputStream().read(b);

                String s = new String(b);

                //processing without any status to present to the user
                if (s.indexOf("@@PROCESSING_END@@") != -1) { //each time we get a processing message, reset j to 0.
                    s = s.replaceAll("@@PROCESSING_END@@", "");
                    j = 0;
                    communicateWork("Processing...", monitor);
                }

                //processing with some kind of status
                if (s.indexOf("@@PROCESSING:") != -1) { //each time we get a processing message, reset j to 0.
                    s = s.replaceAll("@@PROCESSING:", "");
                    s = s.replaceAll("END@@", "");
                    j = 0;
                    s = URLDecoder.decode(s, ENCODING_UTF_8);
                    if (s.trim().equals("") == false) {
                        communicateWork("Processing: " + s, monitor);
                    } else {
                        communicateWork("Processing...", monitor);
                    }
                    s = "";
                }

                s = s.replaceAll((char) 0 + "", ""); //python sends this char as payload.
                str.append(s);

                if (str.indexOf("END@@") != -1) {
                    break;
                } else {

                    if (s.length() == 0) { //only raise if nothing was received.
                        j++;
                    } else {
                        j = 0; //we are receiving, even though that may take a long time if the namespace is really polluted...
                    }
                    sleepALittle(10);
                }

            }

            String ret = str.toString().replaceFirst("@@COMPLETIONS", "");
            //remove END@@
            try {
                if (ret.indexOf("END@@") != -1) {
                    ret = ret.substring(0, ret.indexOf("END@@"));
                    return ret;
                } else {
                    throw new RuntimeException("Couldn't find END@@ on received string.");
                }
            } catch (RuntimeException e) {
                e.printStackTrace();
                if (ret.length() > 500) {
                    ret = ret.substring(0, 499) + "...(continued)...";//if the string gets too big, it can crash Eclipse...
                }
                PydevPlugin.log(IStatus.ERROR, "ERROR WITH STRING:" + ret, e);
                return "";
            }
        } finally{
            isInRead = false;
        }
    }

    /**
     * @return s string with the contents read.
     * @throws IOException

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -