posts - 41,  comments - 40,  trackbacks - 0

          前幾天自己發表的只運行一個實例的文章,感謝Pande的留意,并提出寶貴意見,他推薦的正好是我想找的RSSOwl源碼,以下是我分析RSSOwl如何做到只運行一個實例并且激活的,如有錯誤,請拍磚。

          http://sourceforge.krugle.com/kse/files/cvs/cvs.sourceforge.net/rssowl/RSSOwl/src/java/net/sourceforge/rssowl/controller/RSSOwlLoader.java

          根據 RSSOwlLoader.java 中的

          [code]
          private static void startupProcess( String[] args )
          {
          ? ...

          ? if( !System.getProperties().containsKey( PROPERTY_ALLOW_MULTI_INSTANCES )&&StartupManager.isRSSOwlRunning( feedArgument ) )

          ? ...

          }
          [/code]

          追蹤到 StartupManager.java 見下:

          http://sourceforge.krugle.com/kse/files/cvs/cvs.sourceforge.net/rssowl/RSSOwl/src/java/net/sourceforge/rssowl/controller/thread/StartupManager.java

          追蹤到 StartupManager.isRSSOwlRunning( String message ) 用途為建立ServerSocket,監聽本地8794端口

          [code]
          static ServerSocket applLockSocket;

          public static boolean isRSSOwlRunning( String message )
          {

          ? try{ applLockSocket=new ServerSocket( 8794, 50, InetAddress.getByName( "127.0.0.1" ) );? //1987年9月4日出生?

          ?????? handleSocketUnBound();? //

          ?????? return false;
          ???? }
          ? catch( java.net.BindException e )??? //Another instance already running
          ?????? {
          ???????? ...

          ???????? handleSocketBound( message );? //

          ???????? return true;
          ?????? }?
          ? catch( IOException e )? //Other Error
          ?????? {
          ???????? ...

          ???????? return false;
          ?????? }
          }
          [/code]

          追蹤到 StartupManager.handleSocketUnBound() 和 StartupManager.handleSocketBound( String message )

          [code]
          private static void handleSocketBound( String message )
          {
          ? Socket socket;

          ? try{ socket=new Socket( InetAddress.getByName( "127.0.0.1" ), 8794 );

          ?????? PrintWriter writer=new PrintWriter( new OutputStreamWriter( socket.getOutputStream() ) );

          ?????? writer.println( ( message!=null&&message.length()>0 ) ? message : DEFAULT_MESSAGE );

          ?????? writer.flush();
          ???? }
          ? catch( UnknownHostException e )
          ?????? {
          ???????? ...
          ?????? }
          ? catch( IOException e )
          ?????? {
          ???????? ...
          ?????? }
          }
          [/code]

          [code]
          /**
          ?* Server not yet running. Start it and listen for incoming messages.
          ?*/
          private static void handleSocketUnBound()
          {
          ? listen();? //轉向,為了對稱好看?還是為了兼容?
          }

          /**
          ?* Listen for incoming messages.看看接受的連接發送了什么內容
          ?*/
          private static void listen()
          {
          ? //Run the Server inside a Thread
          ? server=new ExtendedThread()? //extends from Thread
          ? {
          ??? public void run()
          ??? {
          ????? while( !isStopped()&&!isInterrupted() )
          ?????????? {
          ???????????? BufferedReader buffReader=null;

          ???????????? try{ //Read a single line from the Socket
          ????????????????? Socket socket=applLockSocket.accept();

          ????????????????? buffReader=new BufferedReader( new InputStreamReader( socket.getInputStream() ) );

          ????????????????? final String message=buffReader.readLine();

          ????????????????? socket.close();

          ????????????????? //Check the received message
          ????????????????? if( ( message!=null&&message.length()>0 )&&GUI.display!=null&&!GUI.display.isDisposed() )? //激活某個GUI的代碼在此,我們進去看看
          ??????????????????? {
          ????????????????????? GUI.display.asyncExec( new Runnable()
          ????????????????????? {
          ??????????????????????? public void run()
          ??????????????????????? {
          ????????????????????????? //Restore the RSSOwl Window and handle Message
          ????????????????????????? if( GUI.isAlive() )
          ??????????????????????????? {
          ????????????????????????????? GUI.rssOwlGui.restoreWindow();? //找到了,轉到GUI.java

          ????????????????????????????? //Handle the message as Link if valid argument
          ????????????????????????????? if( RSSOwlLoader.isValidArgument( message ) )
          ??????????????????????????????? {
          ????????????????????????????????? GUI.rssOwlGui.getEventManager().actionHandleSuppliedLink( message );
          ??????????????????????????????? }
          ??????????????????????????? }
          ??????????????????????? }
          ????????????????????? } );
          ??????????????????? }
          ??????????????? }
          ???????????? catch( IOException e )
          ????????????????? {
          ??????????????????? ...
          ????????????????? }
          ???????????? finally{ //關閉流
          ??????????????????? }
          ?????????? }
          ??? }
          ? };

          ? server.setDaemon( true );

          ? server.setName( "Startup Manager Thread" );

          ? server.start();
          }
          [/code]

          追蹤到 GUI.java 見下:

          http://sourceforge.krugle.com/kse/files/cvs/cvs.sourceforge.net/rssowl/RSSOwl/src/java/net/sourceforge/rssowl/controller/GUI.java

          追蹤到GUI.restoreWindow()

          [code]
          /**
          ?* Restore the application window either from taskbar or the tray.
          ?*/
          public void restoreWindow()
          {
          ? //RSSOwl is minimized to Tray
          ? if( GlobalSettings.useSystemTray()&&rssOwlSystray!=null&&rssOwlSystray.isMinimizedToTray() )
          ??? {
          ????? rssOwlSystray.restoreWindow();
          ??? }
          ? else{ //RSSOwl is not active
          ??????? shell.forceActive();? //就是它了

          ??????? shell.setMinimized( false );
          ????? }
          }
          [/code]

          原理如下:

          在本地8794端口建立服務監聽,并且一直監聽此端口,試圖接受此端口其它實例(其它程序?)發送的輸入

          如果讀到數據(好像沒有判斷數據的合法性,僅僅判斷數據不為空),并且自己不是“激活”狀態,就“激活”自己;

          如果建立服務監聽不成功,說明已經有實例(其它程序?)占用此端口了,向此端口發送數據喚醒前一個實例,停幾秒以便前一個實例接受,然后退出。

          程序用的是SWT,激活方法用的是shell.forceActive(),but it's not good for core java.

          以上分析如有不對,懇請斧正。



          ?

          posted on 2007-09-01 17:03 NeedJava 閱讀(1477) 評論(1)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 齐齐哈尔市| 克拉玛依市| 德兴市| 永泰县| 霍城县| 始兴县| 奎屯市| 保德县| 个旧市| 克什克腾旗| 洪江市| 吴忠市| 周至县| 宁海县| 常熟市| 孙吴县| 灵石县| 广平县| 泾阳县| 梅州市| 保靖县| 同江市| 大渡口区| 南昌县| 古交市| 礼泉县| 固镇县| 旬阳县| 宁国市| 旬邑县| 新建县| 琼中| 磐安县| 若尔盖县| 修武县| 双江| 珲春市| 阳山县| 惠水县| 定日县| 措美县|