OSDN Git Service

Merge commit '2458eff3aea04f67893bc824b5cf896fbb767332'
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / ProxyChooser.java
diff --git a/src/main/java/jp/sourceforge/jindolf/ProxyChooser.java b/src/main/java/jp/sourceforge/jindolf/ProxyChooser.java
new file mode 100644 (file)
index 0000000..fd10613
--- /dev/null
@@ -0,0 +1,308 @@
+/*\r
+ * proxy chooser\r
+ *\r
+ * Copyright(c) 2009 olyutorskii\r
+ * $Id: ProxyChooser.java 956 2009-12-13 15:14:07Z olyutorskii $\r
+ */\r
+\r
+package jp.sourceforge.jindolf;\r
+\r
+import java.awt.Component;\r
+import java.awt.Container;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ItemEvent;\r
+import java.awt.event.ItemListener;\r
+import java.net.InetSocketAddress;\r
+import java.net.Proxy;\r
+import javax.swing.BorderFactory;\r
+import javax.swing.ButtonGroup;\r
+import javax.swing.ButtonModel;\r
+import javax.swing.ComboBoxEditor;\r
+import javax.swing.ComboBoxModel;\r
+import javax.swing.DefaultComboBoxModel;\r
+import javax.swing.JComboBox;\r
+import javax.swing.JComponent;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JRadioButton;\r
+import javax.swing.JTextField;\r
+import javax.swing.border.Border;\r
+\r
+/**\r
+ * プロクシサーバ選択画面。\r
+ * @see <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>\r
+ * @see <a href="http://www.ietf.org/rfc/rfc1928.txt">RFC1928</a>\r
+ */\r
+@SuppressWarnings("serial")\r
+public class ProxyChooser extends JPanel implements ItemListener{\r
+\r
+    /**\r
+     * ポート番号選択肢を生成する。\r
+     * @return ポート番号選択肢\r
+     */\r
+    private static ComboBoxModel buildPortRecommender(){\r
+        DefaultComboBoxModel model = new DefaultComboBoxModel();\r
+        model.addElement("80");\r
+        model.addElement("1080");\r
+        model.addElement("3128");\r
+        model.addElement("8000");\r
+        model.addElement("8080");\r
+        model.addElement("10080");\r
+        return model;\r
+    }\r
+\r
+    private final JRadioButton isDirect =\r
+            new JRadioButton("直接接続");\r
+    private final JRadioButton isHttp =\r
+            new JRadioButton("HTTP-Proxy (RFC2616)");\r
+    private final JRadioButton isSocks =\r
+            new JRadioButton("SOCKS (RFC1928)");\r
+    private final ButtonGroup buttonGroup = new ButtonGroup();\r
+\r
+    private final JTextField hostname = new JTextField();\r
+    private final JComboBox port = new JComboBox();\r
+    private final JComponent serverInfo = buildServerPanel();\r
+\r
+\r
+    /**\r
+     * コンストラクタ。\r
+     */\r
+    public ProxyChooser(){\r
+        this(ProxyInfo.DEFAULT);\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * コンストラクタ。\r
+     * @param proxyInfo プロクシ設定\r
+     */\r
+    public ProxyChooser(ProxyInfo proxyInfo){\r
+        super();\r
+\r
+        this.buttonGroup.add(this.isDirect);\r
+        this.buttonGroup.add(this.isHttp);\r
+        this.buttonGroup.add(this.isSocks);\r
+        this.isDirect.addItemListener(this);\r
+        this.isHttp  .addItemListener(this);\r
+        this.isSocks .addItemListener(this);\r
+\r
+        this.hostname.setComponentPopupMenu(new TextPopup());\r
+        Monodizer.monodize(this.hostname);\r
+        GUIUtils.addMargin(this.hostname, 1, 4, 1, 4);\r
+\r
+        this.port.setModel(buildPortRecommender());\r
+        this.port.setEditable(true);\r
+        ComboBoxEditor editor = this.port.getEditor();\r
+        Component comp = editor.getEditorComponent();\r
+        GUIUtils.addMargin(comp, 1, 4, 1, 4);\r
+        if(comp instanceof JComponent){\r
+            ((JComponent)comp).setComponentPopupMenu(new TextPopup());\r
+        }\r
+        Monodizer.monodize(this.port);\r
+\r
+        design(this);\r
+\r
+        setProxyInfo(proxyInfo);\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * レイアウトを行う。\r
+     * @param content コンテナ\r
+     */\r
+    private void design(Container content){\r
+        GridBagLayout layout = new GridBagLayout();\r
+        GridBagConstraints constraints = new GridBagConstraints();\r
+\r
+        content.setLayout(layout);\r
+\r
+        constraints.insets = new Insets(2, 2, 2, 2);\r
+\r
+        constraints.weightx = 1.0;\r
+        constraints.gridwidth = GridBagConstraints.REMAINDER;\r
+        constraints.fill = GridBagConstraints.BOTH;\r
+        constraints.anchor = GridBagConstraints.NORTHWEST;\r
+\r
+        content.add(this.isDirect, constraints);\r
+        content.add(this.isHttp, constraints);\r
+        content.add(this.isSocks, constraints);\r
+        content.add(this.serverInfo, constraints);\r
+\r
+        constraints.weighty = 1.0;\r
+        content.add(new JPanel(), constraints);\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * サーバ情報パネルを生成する。\r
+     * @return サーバ情報パネル\r
+     */\r
+    private JComponent buildServerPanel(){\r
+        JPanel panel = new JPanel();\r
+\r
+        GridBagLayout layout = new GridBagLayout();\r
+        GridBagConstraints constraints = new GridBagConstraints();\r
+\r
+        panel.setLayout(layout);\r
+\r
+        constraints.insets = new Insets(2, 2, 2, 2);\r
+\r
+        constraints.weightx = 0.0;\r
+        constraints.gridwidth = 1;\r
+        constraints.fill = GridBagConstraints.NONE;\r
+        constraints.anchor = GridBagConstraints.NORTHEAST;\r
+        panel.add(new JLabel("アドレス:"), constraints);\r
+\r
+        constraints.weightx = 1.0;\r
+        constraints.gridwidth = GridBagConstraints.REMAINDER;\r
+        constraints.fill = GridBagConstraints.HORIZONTAL;\r
+        constraints.anchor = GridBagConstraints.NORTHWEST;\r
+        panel.add(this.hostname, constraints);\r
+\r
+        constraints.weightx = 0.0;\r
+        constraints.gridwidth = 1;\r
+        constraints.fill = GridBagConstraints.NONE;\r
+        constraints.anchor = GridBagConstraints.NORTHEAST;\r
+        panel.add(new JLabel("ポート:"), constraints);\r
+\r
+        constraints.gridwidth = GridBagConstraints.REMAINDER;\r
+        constraints.anchor = GridBagConstraints.NORTHWEST;\r
+        panel.add(this.port, constraints);\r
+\r
+        String warn =\r
+                "<html>※ このプロクシサーバは本当に信頼できますか?<br>"\r
+                + "あなたが人狼BBSにログインしている間、<br>"\r
+                + "あなたのパスワードは平文状態のまま<br>"\r
+                + "このプロクシサーバ上を何度も通過します。</html>";\r
+        panel.add(new JLabel(warn), constraints);\r
+\r
+        Border border = BorderFactory.createTitledBorder("プロクシサーバ情報");\r
+        panel.setBorder(border);\r
+\r
+        return panel;\r
+    }\r
+\r
+    /**\r
+     * プロクシの種別を返す。\r
+     * @return プロクシ種別\r
+     */\r
+    protected Proxy.Type getType(){\r
+        if(this.isDirect.isSelected()) return Proxy.Type.DIRECT;\r
+        if(this.isHttp  .isSelected()) return Proxy.Type.HTTP;\r
+        if(this.isSocks .isSelected()) return Proxy.Type.SOCKS;\r
+\r
+        return Proxy.Type.DIRECT;\r
+    }\r
+\r
+    /**\r
+     * サーバ名を返す。\r
+     * プロクシのホスト名として妥当なものか否かは検証されない。\r
+     * @return サーバ名\r
+     */\r
+    protected String getHostName(){\r
+        String hostText = this.hostname.getText();\r
+        hostText = hostText.trim();\r
+        return hostText;\r
+    }\r
+\r
+    /**\r
+     * ポート番号を返す。\r
+     * 番号の体をなしていなければゼロを返す。\r
+     * @return ポート番号\r
+     */\r
+    protected int getPort(){\r
+        Object portItem = this.port.getEditor().getItem();\r
+        String portText = portItem.toString();\r
+        portText = portText.trim();\r
+\r
+        int result;\r
+        try{\r
+            result = Integer.parseInt(portText);\r
+        }catch(NumberFormatException e){\r
+            return 0;\r
+        }\r
+\r
+        if(result < 0) result = 0;\r
+        if(65535 < result) result = 65535;\r
+\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * サーバへのソケットアドレスを生成する。\r
+     * @return ソケットアドレス\r
+     */\r
+    protected InetSocketAddress getInetSocketAddress(){\r
+        return InetSocketAddress.createUnresolved(getHostName(), getPort());\r
+    }\r
+\r
+    /**\r
+     * プロクシ設定を返す。\r
+     * @return プロクシ設定\r
+     */\r
+    public ProxyInfo getProxyInfo(){\r
+        Proxy.Type type = getType();\r
+        return new ProxyInfo(type, getInetSocketAddress());\r
+    }\r
+\r
+    /**\r
+     * プロクシ設定を設定する。\r
+     * UIに反映される。\r
+     * @param proxyInfo プロクシ設定。nullなら直接接続と解釈される。\r
+     */\r
+    public final void setProxyInfo(ProxyInfo proxyInfo){\r
+        Proxy.Type type;\r
+        InetSocketAddress addr;\r
+        if(proxyInfo == null){\r
+            type = Proxy.Type.DIRECT;\r
+            addr = ProxyInfo.IP4SOCKET_NOBODY;\r
+        }else{\r
+            type = proxyInfo.getType();\r
+            addr = proxyInfo.address();\r
+        }\r
+\r
+        ButtonModel model;\r
+        switch(type){\r
+        case DIRECT: model = this.isDirect.getModel(); break;\r
+        case HTTP:   model = this.isHttp  .getModel(); break;\r
+        case SOCKS:  model = this.isSocks .getModel(); break;\r
+        default:     model = this.isDirect.getModel(); break;\r
+        }\r
+        this.buttonGroup.setSelected(model, true);\r
+\r
+        this.hostname.setText(addr.getHostName());\r
+        this.port.getEditor()\r
+                 .setItem(Integer.valueOf(addr.getPort()));\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * プロクシ種別ボタン操作の受信。\r
+     * @param event ボタン操作イベント\r
+     */\r
+    public void itemStateChanged(ItemEvent event){\r
+        Object source = event.getSource();\r
+\r
+        Proxy.Type type;\r
+        if     (source == this.isDirect) type = Proxy.Type.DIRECT;\r
+        else if(source == this.isHttp)   type = Proxy.Type.HTTP;\r
+        else if(source == this.isSocks)  type = Proxy.Type.SOCKS;\r
+        else                             return;\r
+\r
+        if(type == Proxy.Type.DIRECT){\r
+            this.hostname.setEnabled(false);\r
+            this.port    .setEnabled(false);\r
+        }else{\r
+            this.hostname.setEnabled(true);\r
+            this.port    .setEnabled(true);\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+}\r