2011-12-20 10 views
1

ユーザーがアプリケーションを再実行しようとすると、最初の実行でのみ実行されるrcpアプリケーションがありました.2番目のインスタンスは、ソケットを介してソケット上の引数を最初にサーバーとして機能し、サイレントモードで終了するインスタンス。最初のインスタンスはそのメッセージを受け取ってデコードし、それらの引数で呼び出されたかのように動作します。RCPアプリケーションの以前のインスタンスを表示

これまでのところ、2つのインスタンス間で引数を渡すための内部プロトコル仕様を作成しました。

最初のインスタンス(RCPアプリケーション)を前面に表示できませんでした。それだけで、

これは私の以前のquestion

に継続して、私は前のポストに行われた変更は、アプリケーションクラスのメソッド行の下

public Object start(IApplicationContext context) throws Exception { 
     if (!ApplicationInstanceManager.registerInstance()) { 
      return IApplication.EXIT_OK; 
     } 
     ApplicationInstanceManager 
       .setApplicationInstanceListener(new ApplicationInstanceListener() { 
        public void newInstanceCreated() { 
         Display.getDefault().asyncExec(new Runnable() { 
          public void run() { 
           System.out.println("New instance detected..."); 

           //Display.getCurrent().getActiveShell() 
             .forceActive();// this gives null 
                 // pointer exception 
                 // hence commented 
          } 
         }); 
        } 
       }); 
     Display display = PlatformUI.createDisplay(); 
     try { 
      int returnCode = PlatformUI.createAndRunWorkbench(display, 
        new ApplicationWorkbenchAdvisor()); 
      if (returnCode == PlatformUI.RETURN_RESTART) 
       return IApplication.EXIT_RESTART; 
      else 
       return IApplication.EXIT_OK; 
     } finally { 
      display.dispose(); 
     } 
    } 

を持って私を停止して開始されている最小化した状態でありますフロント

Display.getCurrent().getActiveShell().forceActive(); 

への適用がgetActiveShell(ATヌルポインタ例外を生成する)

私は前のインスタンスを最大化するか前面に持っていくことができます

答えて

2

私はRCPを単一のインスタンスに制限するためにインスタンスマネージャーを作成しました。

ここApplication.javaに行くコードはstart方法では、です:

if (!ApplicationInstanceManager.registerInstance()) { 
     return IApplication.EXIT_OK; 
    } 

    ApplicationInstanceManager 
      .setApplicationInstanceListener(new ApplicationInstanceListener() { 
       public void newInstanceCreated() { 
        Display.getDefault().asyncExec(new Runnable() { 
         public void run() { 
          if (DEBUG) 
           System.out.println("New instance detected..."); 
          Display.getCurrent().getActiveShell().forceActive(); 
         } 
        }); 
       } 
      }); 

ここでリスナーインタフェースです:

public interface ApplicationInstanceListener { 

    public void newInstanceCreated(); 

} 

そして、ここでマネージャークラスがあります:

public class ApplicationInstanceManager { 

    private static final boolean DEBUG = true; 

    private static ApplicationInstanceListener subListener; 

    /** Randomly chosen, but static, high socket number */ 
    public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331; 

    /** Must end with newline */ 
    public static final String SINGLE_INSTANCE_SHARED_KEY = "$$RabidNewInstance$$\n"; 

    /** 
    * Registers this instance of the application. 
    * 
    * @return true if first instance, false if not. 
    */ 
    public static boolean registerInstance() { 
     // returnValueOnError should be true if lenient (allows app to run on 
     // network error) or false if strict. 
     boolean returnValueOnError = true; 
     // try to open network socket 
     // if success, listen to socket for new instance message, return true 
     // if unable to open, connect to existing and send new instance message, 
     // return false 
     try { 
      final ServerSocket socket = new ServerSocket(
        SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress 
          .getLocalHost()); 
      if (DEBUG) 
       System.out 
         .println("Listening for application instances on socket " 
           + SINGLE_INSTANCE_NETWORK_SOCKET); 
      Thread instanceListenerThread = new InstanceListenerThread(socket); 
      instanceListenerThread.start(); 
      // listen 
     } catch (UnknownHostException e) { 
      EclipseLogging.logError(RabidPlugin.getDefault(), 
        RabidPlugin.PLUGIN_ID, e); 
      return returnValueOnError; 
     } catch (IOException e) { 
      return portTaken(returnValueOnError, e); 

     } 
     return true; 
    } 

    private static boolean portTaken(boolean returnValueOnError, IOException e) { 
     if (DEBUG) 
      System.out.println("Port is already taken. " 
        + "Notifying first instance."); 
     try { 
      Socket clientSocket = new Socket(InetAddress.getLocalHost(), 
        SINGLE_INSTANCE_NETWORK_SOCKET); 
      OutputStream out = clientSocket.getOutputStream(); 
      out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes()); 
      out.close(); 
      clientSocket.close(); 
      System.out.println("Successfully notified first instance."); 
      return false; 
     } catch (UnknownHostException e1) { 
      EclipseLogging.logError(RabidPlugin.getDefault(), 
        RabidPlugin.PLUGIN_ID, e); 
      return returnValueOnError; 
     } catch (IOException e1) { 
      EclipseLogging 
        .logError(
          RabidPlugin.getDefault(), 
          RabidPlugin.PLUGIN_ID, 
          "Error connecting to local port for single instance notification", 
          e); 
      return returnValueOnError; 
     } 
    } 

    public static void setApplicationInstanceListener(
      ApplicationInstanceListener listener) { 
     subListener = listener; 
    } 

    private static void fireNewInstance() { 
     if (subListener != null) { 
      subListener.newInstanceCreated(); 
     } 
    } 

    public static void main(String[] args) { 
     if (!ApplicationInstanceManager.registerInstance()) { 
      // instance already running. 
      System.out.println("Another instance of this application " 
        + "is already running. Exiting."); 
      System.exit(0); 
     } 
     ApplicationInstanceManager 
       .setApplicationInstanceListener(new ApplicationInstanceListener() { 
        public void newInstanceCreated() { 
         System.out.println("New instance detected..."); 
         // this is where your handler code goes... 
        } 
       }); 
    } 

    public static class InstanceListenerThread extends Thread { 

     private ServerSocket socket; 

     public InstanceListenerThread(ServerSocket socket) { 
      this.socket = socket; 
     } 

     @Override 
     public void run() { 
      boolean socketClosed = false; 
      while (!socketClosed) { 
       if (socket.isClosed()) { 
        socketClosed = true; 
       } else { 
        try { 
         Socket client = socket.accept(); 
         BufferedReader in = new BufferedReader(
           new InputStreamReader(client.getInputStream())); 
         String message = in.readLine(); 
         if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(
           message.trim())) { 
          if (DEBUG) 
           System.out.println("Shared key matched - " 
             + "new application instance found"); 
          fireNewInstance(); 
         } 
         in.close(); 
         client.close(); 
        } catch (IOException e) { 
         socketClosed = true; 
        } 
       } 
      } 
     } 
    } 
} 
+0

、あなたが使用可能な任意のポートを使用し、他の人が読み取ることができるファイルにそのポートを書き込むことができます。場所は、通常のようなコードを使用して、あなたのアクティベーターから取得されorg.eclipse.osgi.service.datalocation.Location.isSet()org.eclipse.osgi.service.datalocation.Location.lock()

を使用したOSGiのインスタンスの場所それ。 forceActive()は、OSが完全にフォローしない要求であることに注意してください。 –

+0

@raghav:そうではありません。アプリケーションに静的なブール値を追加します。 –

+0

@Gilbert Display.getCurrent()。getActiveShell()。forceActive(); はnullpointer例外を生成しています – srk

2

後あなたのIApplicationが起動すると、あなたはまた

public Location getInstanceLocation() { 
    if (locationTracker == null) { 
     Filter filter = null; 
     try { 
      filter = context.createFilter(Location.INSTANCE_FILTER); 
     } catch (InvalidSyntaxException e) { 
      // ignore this. It should never happen as we have tested the 
      // above format. 
     } 
     locationTracker = new ServiceTracker(context, filter, null); 
     locationTracker.open(); 
    } 
    return (Location) locationTracker.getService(); 
} 
関連する問題