/* * $Id$ * * Copyright (c) 2004-2005 by the TeXlapse Team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package net.sourceforge.texlipse.viewer.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import net.sourceforge.texlipse.TexlipsePlugin; import net.sourceforge.texlipse.properties.TexlipseProperties; /** * A server that takes in filename-linenumber commands * and passes these commands as events to its listener. * * The server will listen to the specified socket until it gets * a command "QUIT". * * @author Esa Seuranen * @author Kimmo Karlsson */ public class FileLocationServer implements Runnable { // the singleton instance private static FileLocationServer instance = new FileLocationServer(); // the socket where the server is currently listening private ServerSocket ssocket; // the listener, which will be notified every time a file location command occurs private FileLocationListener listener; /** * Create a new Server. */ private FileLocationServer() { } /** * @return the shared instance */ public static FileLocationServer getInstance() { return instance; } /** * Check to see if the server is already running. * @return true, if the server is running */ public boolean isRunning() { return ssocket != null; } /** * Stop the server. */ public void stop() { if (ssocket == null) { return; } try { Socket s = new Socket("localhost", ssocket.getLocalPort()); s.getOutputStream().write("QUIT\n".getBytes()); s.close(); } catch (UnknownHostException e) { //shouldn't happen } catch (IOException e) { TexlipsePlugin.log("Stopping FileLocation server: ", e); } } /** * Set the file location listener. * @param listener the new file location listener. */ public void setListener(FileLocationListener listener) { this.listener = listener; } /** * Run the socket listener. * */ public void run() { // Try to open a server socket on port // Note that we can't choose a port less than 1023 if we are not // privileged users (root) ssocket = null; try { ssocket = new ServerSocket(TexlipsePlugin.getDefault().getPreferenceStore().getInt(TexlipseProperties.FILE_LOCATION_PORT)); } catch (IOException e) { TexlipsePlugin.log("Starting server", e); } // Create a socket object from the ServerSocket to listen and accept connections. // Open input and output streams try { while (ssocket != null) { // Wait for connection Socket csocket = ssocket.accept(); BufferedReader is = new BufferedReader(new InputStreamReader(csocket.getInputStream())); String line = null; while ((line = is.readLine()) != null) { parseLine(line); } } } catch (IOException e) { ssocket = null; TexlipsePlugin.log("Server error: ", e); } } /** * Try to parse a "filename:linenumber" -combination * and notify listener if parsing is successful. * * @param line the line of characters to parse */ private void parseLine(String line) { int index = line.lastIndexOf(':'); if (index > 0) { String file = line.substring(0, index); int i = index+1; while (i < line.length() && Character.isDigit(line.charAt(i))) { i++; } String num = line.substring(index+1, i); int lineNumber = -1; try { lineNumber = Integer.parseInt(num); } catch (NumberFormatException e) { } if (listener != null) { listener.showLineOfFile(file, lineNumber); } } else { if (line.startsWith("QUIT")) { ssocket = null; } } } }