--- /dev/null
+/*\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