OSDN Git Service

ログ出力処理修正
authorOlyutorskii <olyutorskii@users.osdn.me>
Sun, 2 Dec 2012 04:01:10 +0000 (13:01 +0900)
committerOlyutorskii <olyutorskii@users.osdn.me>
Sun, 2 Dec 2012 04:01:10 +0000 (13:01 +0900)
pom.xml
src/main/java/jp/sfjp/jindolf/log/LogFrame.java
src/main/java/jp/sfjp/jindolf/log/LogPanel.java [new file with mode: 0644]
src/main/java/jp/sfjp/jindolf/log/LoggingDispatcher.java
src/main/java/jp/sfjp/jindolf/log/SwingDocHandler.java

diff --git a/pom.xml b/pom.xml
index 4a73665..96e0b33 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>4.10</version>
+            <version>4.11</version>
             <scope>test</scope>
         </dependency>
 
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>2.5.1</version>
+                <version>3.0</version>
                 <configuration>
                     <source>1.6</source>  <!-- for NetBeans IDE -->
                     <target>1.6</target>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-assembly-plugin</artifactId>
-                <version>2.3</version>
+                <version>2.4</version>
                 <configuration>
                     <archiveBaseDirectory>.</archiveBaseDirectory>
                     <descriptors>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-source-plugin</artifactId>
-                <version>2.1.2</version>
-                <!-- 2.2はplexus-archiverへの依存性で問題あり -->
+                <version>2.2.1</version>
                 <configuration>
                     <includePom>true</includePom>
                     <archive>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-site-plugin</artifactId>
-                <version>3.1</version>
+                <version>3.2</version>
                 <configuration>
                     <generateReports>true</generateReports>
                     <locales>ja</locales>
                 <configuration>
                     <effort>Max</effort>
                     <threshold>Low</threshold>
+                    <!-- for Jenkins -->
+                    <findbugsXmlOutput>true</findbugsXmlOutput>
+                    <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
+                    <xmlOutput>true</xmlOutput>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>cobertura-maven-plugin</artifactId>
+                <version>2.5.2</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <formats>
+                        <format>html</format>
+                        <format>xml</format> <!-- for Jenkins -->
+                    </formats>
                 </configuration>
             </plugin>
 
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-project-info-reports-plugin</artifactId>
-                <version>2.5.1</version>
+                <version>2.6</version>
                 <configuration>
                     <linkOnly>true</linkOnly>
                     <offline>true</offline>
                 <version>2.5.2</version>
                 <configuration>
                     <encoding>${project.build.sourceEncoding}</encoding>
+                    <formats>
+                        <format>html</format>
+                        <format>xml</format> <!-- for Jenkins -->
+                    </formats>
                 </configuration>
             </plugin>
 
                     <skip>false</skip>
                     <effort>Max</effort>
                     <threshold>Low</threshold>
+                    <!-- for Jenkins -->
+                    <findbugsXmlOutput>true</findbugsXmlOutput>
+                    <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
+                    <xmlOutput>true</xmlOutput>
                     <!-- excludeFilterFile/ -->
                 </configuration>
             </plugin>
index ce47599..f755ed9 100644 (file)
@@ -8,91 +8,51 @@
 package jp.sfjp.jindolf.log;
 
 import java.awt.Container;
-import java.awt.EventQueue;
 import java.awt.Frame;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
 import java.util.logging.Handler;
-import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JDialog;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollBar;
-import javax.swing.JScrollPane;
 import javax.swing.JSeparator;
-import javax.swing.JTextArea;
-import javax.swing.border.Border;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import javax.swing.text.PlainDocument;
-import jp.sfjp.jindolf.dxchg.TextPopup;
-import jp.sfjp.jindolf.util.GUIUtils;
-import jp.sfjp.jindolf.util.Monodizer;
 
 /**
- * ã\83­ã\82°è¡¨ç¤ºã\83\91ã\83\8dã\83«
+ * ã\83­ã\82°è¡¨ç¤ºã\82¦ã\82£ã\83³ã\83\89ã\82¦
  */
 @SuppressWarnings("serial")
-public class LogFrame extends JDialog
-        implements WindowListener, ActionListener, DocumentListener{
+public class LogFrame extends JDialog {
 
-    private static final Document DOC_EMPTY = new PlainDocument();
+    private static final String CMD_CLOSELOG = "CMD_CLOSE_LOG";
+    private static final String CMD_CLEARLOG = "CMD_CLEAR_LOG";
 
 
-    private final JTextArea textarea;
-    private final Document document = new PlainDocument();
-    private final JScrollPane scrollPane;
-    private final JScrollBar vertical;
-    private final Handler handler;
-
+    private final LogPanel logPanel = new LogPanel();
     private final JButton clearButton = new JButton("クリア");
     private final JButton closeButton = new JButton("閉じる");
 
+
     /**
-     * ã\83­ã\82°è¡¨ç¤ºã\83\91ã\83\8dã\83«ã\81®ç\94\9fæ\88\90
+     * ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
      * @param owner フレームオーナー
      */
     public LogFrame(Frame owner){
         super(owner);
-        setModal(false);
-
-        if(LogUtils.hasLoggingPermission()){
-            this.handler = new SwingDocHandler(this.document);
-        }else{
-            this.handler = null;
-        }
-
-        GUIUtils.modifyWindowAttributes(this, true, false, true);
-
-        this.textarea = new JTextArea();
-        this.textarea.setEditable(false);
-        this.textarea.setLineWrap(true);
-        this.textarea.setDocument(DOC_EMPTY);
-        Border border = BorderFactory.createEmptyBorder(3, 3, 3, 3);
-        this.textarea.setBorder(border);
-        Monodizer.monodize(this.textarea);
-        JPopupMenu popup = new TextPopup();
-        this.textarea.setComponentPopupMenu(popup);
-
-        this.scrollPane = new JScrollPane(this.textarea);
-        this.vertical = this.scrollPane.getVerticalScrollBar();
 
         design();
 
-        this.clearButton.addActionListener(this);
-        this.closeButton.addActionListener(this);
+        this.clearButton.setActionCommand(CMD_CLEARLOG);
+        this.closeButton.setActionCommand(CMD_CLOSELOG);
 
-        this.document.addDocumentListener(this);
+        ActionListener actionListener = new ActionWatcher();
+        this.clearButton.addActionListener(actionListener);
+        this.closeButton.addActionListener(actionListener);
 
-        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
-        addWindowListener(this);
+        setResizable(true);
+        setLocationByPlatform(true);
+        setModal(false);
 
         return;
     }
@@ -112,7 +72,7 @@ public class LogFrame extends JDialog
         constraints.fill = GridBagConstraints.BOTH;
         constraints.gridwidth = GridBagConstraints.REMAINDER;
 
-        content.add(this.scrollPane, constraints);
+        content.add(this.logPanel, constraints);
 
         constraints.weighty = 0.0;
         constraints.fill = GridBagConstraints.HORIZONTAL;
@@ -133,182 +93,50 @@ public class LogFrame extends JDialog
     }
 
     /**
-     * ロギングハンドラを取得する
+     * ロギングハンドラを返す
      * @return ロギングハンドラ
      */
     public Handler getHandler(){
-        return this.handler;
+        return this.logPanel.getHandler();
     }
 
     /**
-     * 垂直スクロールバーを末端に設定する。
+     * ログ内容をクリアする。
      */
-    private void showLastPos(){
-        if( ! isVisible() ) return;
-        if(this.textarea.getDocument() != this.document) return;
-
-        EventQueue.invokeLater(new Runnable(){
-            public void run(){
-                LogFrame.this.vertical.setValue(Integer.MAX_VALUE);
-                return;
-            }
-        });
-
+    public void clearLog(){
+        this.logPanel.clearLog();
         return;
     }
 
-    /**
-     * ウィンドウクローズ処理。
-     */
-    private void close(){
-        setVisible(false);
-        return;
-    }
 
     /**
-     * ã\83­ã\82°ã\82¯ã\83ªã\82¢å\87¦ç\90\86
+     * ã\83\9cã\82¿ã\83³æ\93\8dä½\9cã\82\92ç\9b£è¦\96ã\81\99ã\82\8b
      */
-    private void clear(){
-        try{
-            this.document.remove(0, this.document.getLength());
-        }catch(BadLocationException e){
-            assert false;
-        }
-        return;
-    }
+    private final class ActionWatcher implements ActionListener{
 
-    /**
-     * {@inheritDoc}
-     * ウィンドウの表示・非表示を設定する。
-     * @param visible trueなら表示 {@inheritDoc}
-     */
-    @Override
-    public void setVisible(boolean visible){
-        super.setVisible(visible);
-
-        if(visible){
-            this.textarea.setDocument(this.document);
-            showLastPos();
-        }else{
-            this.textarea.setDocument(DOC_EMPTY);
+        /**
+         * コンストラクタ。
+         */
+        ActionWatcher(){
+            super();
+            return;
         }
 
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowActivated(WindowEvent event){
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowDeactivated(WindowEvent event){
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowIconified(WindowEvent event){
-        this.textarea.setDocument(DOC_EMPTY);
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowDeiconified(WindowEvent event){
-        this.textarea.setDocument(this.document);
-        showLastPos();
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowOpened(WindowEvent event){
-        this.textarea.setDocument(this.document);
-        showLastPos();
-        return;
-    }
+        /**
+         * {@inheritDoc}
+         * ボタン押下イベント処理。
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void actionPerformed(ActionEvent event){
+            String cmd = event.getActionCommand();
 
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowClosed(WindowEvent event){
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void windowClosing(WindowEvent event){
-        close();
-        return;
-    }
+            if     (CMD_CLEARLOG.equals(cmd)) clearLog();
+            else if(CMD_CLOSELOG.equals(cmd)) setVisible(false);
 
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void actionPerformed(ActionEvent event){
-        Object source = event.getSource();
-        if(source == this.clearButton){
-            clear();
-        }else if(source == this.closeButton){
-            close();
+            return;
         }
 
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void changedUpdate(DocumentEvent event){
-        showLastPos();
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void insertUpdate(DocumentEvent event){
-        showLastPos();
-        return;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @param event {@inheritDoc}
-     */
-    @Override
-    public void removeUpdate(DocumentEvent event){
-        showLastPos();
-        return;
     }
 
 }
diff --git a/src/main/java/jp/sfjp/jindolf/log/LogPanel.java b/src/main/java/jp/sfjp/jindolf/log/LogPanel.java
new file mode 100644 (file)
index 0000000..1a3c415
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Log panel
+ *
+ * License : The MIT License
+ * Copyright(c) 2012 olyutorskii
+ */
+
+package jp.sfjp.jindolf.log;
+
+import java.awt.Adjustable;
+import java.awt.EventQueue;
+import java.util.logging.Handler;
+import javax.swing.BorderFactory;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.border.Border;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.PlainDocument;
+import jp.sfjp.jindolf.dxchg.TextPopup;
+import jp.sfjp.jindolf.util.Monodizer;
+
+/**
+ * スクロールバー付きログ表示パネル。
+ * 垂直スクロールバーは自動的に最下部へトラックする。
+ */
+@SuppressWarnings("serial")
+public class LogPanel extends JScrollPane {
+
+    private static final Document DOC_EMPTY = new PlainDocument();
+
+
+    private final Document document = new PlainDocument();
+    private final Handler handler;
+
+    private final JTextArea textarea = new JTextArea();
+
+
+    /**
+     * コンストラクタ。
+     */
+    public LogPanel(){
+        super();
+
+        if(LogUtils.hasLoggingPermission()){
+            this.handler = new SwingDocHandler(this.document);
+        }else{
+            this.handler = null;
+        }
+
+        this.textarea.setDocument(DOC_EMPTY);
+        this.textarea.setEditable(false);
+        this.textarea.setLineWrap(true);
+        Monodizer.monodize(this.textarea);
+
+        Border border = BorderFactory.createEmptyBorder(3, 3, 3, 3);
+        this.textarea.setBorder(border);
+
+        JPopupMenu popup = new TextPopup();
+        this.textarea.setComponentPopupMenu(popup);
+
+        setViewportView(this.textarea);
+
+        DocumentListener docListener = new DocWatcher();
+        this.document.addDocumentListener(docListener);
+
+        AncestorListener ancestorListener = new AncestorWatcher();
+        addAncestorListener(ancestorListener);
+
+        return;
+    }
+
+    /**
+     * ロギングハンドラを返す。
+     * @return ロギングハンドラ
+     */
+    public Handler getHandler(){
+        return this.handler;
+    }
+
+    /**
+     * 垂直スクロールバーをドキュメント下端に設定し、
+     * ログの最新部を表示する。
+     * 不可視状態なら何もしない。
+     */
+    private void showLastPos(){
+        if(this.textarea.getDocument() != this.document) return;
+
+        final Adjustable yPos = getVerticalScrollBar();
+        EventQueue.invokeLater(new Runnable(){
+            @Override
+            public void run(){
+                yPos.setValue(Integer.MAX_VALUE);
+                return;
+            }
+        });
+
+        return;
+    }
+
+    /**
+     * モデルとビューを連携させる。
+     * スクロール位置は末端に。
+     */
+    private void attachModel(){
+        if(this.textarea.getDocument() != this.document){
+            this.textarea.setDocument(this.document);
+        }
+        showLastPos();
+        return;
+    }
+
+    /**
+     * モデルとビューを切り離す。
+     */
+    private void detachModel(){
+        if(this.textarea.getDocument() == DOC_EMPTY) return;
+        this.textarea.setDocument(DOC_EMPTY);
+        return;
+    }
+
+    /**
+     * ログ内容をクリアする。
+     */
+    public void clearLog(){
+        try{
+            int docLength = this.document.getLength();
+            this.document.remove(0, docLength);
+        }catch(BadLocationException e){
+            assert false;
+        }
+        return;
+    }
+
+
+    /**
+     * 画面更新が必要な状態か監視し、必要に応じてモデルとビューを切り離す。
+     */
+    private final class AncestorWatcher implements AncestorListener{
+
+        /**
+         * コンストラクタ。
+         */
+        AncestorWatcher(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void ancestorAdded(AncestorEvent event){
+            attachModel();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void ancestorRemoved(AncestorEvent event){
+            detachModel();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void ancestorMoved(AncestorEvent event){
+            return;
+        }
+
+    }
+
+
+    /**
+     * ドキュメント操作を監視し、スクロールバーを更新する。
+     */
+    private final class DocWatcher implements DocumentListener{
+
+        /**
+         * コンストラクタ。
+         */
+        DocWatcher(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void changedUpdate(DocumentEvent event){
+            showLastPos();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void insertUpdate(DocumentEvent event){
+            showLastPos();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param event {@inheritDoc}
+         */
+        @Override
+        public void removeUpdate(DocumentEvent event){
+            showLastPos();
+            return;
+        }
+
+    }
+
+}
index cbd0e0f..710c195 100644 (file)
@@ -23,6 +23,7 @@ public class LoggingDispatcher extends EventQueue{
 
     private static final Logger LOGGER = Logger.getAnonymousLogger();
 
+
     /**
      * コンストラクタ。
      */
@@ -31,8 +32,9 @@ public class LoggingDispatcher extends EventQueue{
         return;
     }
 
+
     /**
-     * 独自ロガーにエラーや例外を吐く、
+     * 匿名ロガーにエラーや例外を吐く、
      * カスタム化されたイベントキューに差し替える。
      */
     public static void replaceEventQueue(){
@@ -44,17 +46,18 @@ public class LoggingDispatcher extends EventQueue{
     }
 
     /**
-     * 異常系をログ出力
+     * 異常系を匿名ロガーに出力する
      * @param e 例外
      */
-    private void errlog(Throwable e){
+    private static void logThrowable(Throwable e){
         LOGGER.log(Level.SEVERE, FATALMSG, e);
         return;
     }
 
+
     /**
      * {@inheritDoc}
-     * 発生した例外をログ出力する。
+     * イベントディスパッチにより発生した例外を匿名ログ出力する。
      * @param event {@inheritDoc}
      */
     @Override
@@ -62,12 +65,12 @@ public class LoggingDispatcher extends EventQueue{
         try{
             super.dispatchEvent(event);
         }catch(RuntimeException e){
-            errlog(e);
+            logThrowable(e);
             throw e;
         }catch(Exception e){
-            errlog(e);
+            logThrowable(e);
         }catch(Error e){
-            errlog(e);
+            logThrowable(e);
             throw e;
         }
         // TODO Toolkit#beep()もするべきか
index c9686e7..1eecac1 100644 (file)
@@ -37,6 +37,7 @@ public class SwingDocHandler extends Handler{
 
     private final Document document;
 
+
     /**
      * ログハンドラの生成。
      * @param document ドキュメントモデル
@@ -100,9 +101,11 @@ public class SwingDocHandler extends Handler{
         final String message = formatter.format(record);
 
         EventQueue.invokeLater(new Runnable(){
+            @Override
             public void run(){
                 appendLog(message);
                 chopHead();
+                return;
             }
         });
 
@@ -120,6 +123,7 @@ public class SwingDocHandler extends Handler{
 
     /**
      * {@inheritDoc}
+     * ログ受け入れを締め切る。
      */
     @Override
     public void close(){