1 /* NetworkSettingsPanel.java -- Sets proxy settings for network.
2 Copyright (C) 2010 Red Hat
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18 
19 package net.sourceforge.jnlp.controlpanel;
20 
21 import java.awt.BorderLayout;
22 import java.awt.CardLayout;
23 import java.awt.Component;
24 import java.awt.Dimension;
25 import java.awt.FlowLayout;
26 import java.awt.GridBagConstraints;
27 import java.awt.GridBagLayout;
28 import java.awt.GridLayout;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.awt.event.ItemEvent;
32 import java.awt.event.ItemListener;
33 import java.util.ArrayList;
34 
35 import javax.swing.Box;
36 import javax.swing.ButtonGroup;
37 import javax.swing.JButton;
38 import javax.swing.JCheckBox;
39 import javax.swing.JLabel;
40 import javax.swing.JOptionPane;
41 import javax.swing.JPanel;
42 import javax.swing.JRadioButton;
43 import javax.swing.JTextField;
44 import javax.swing.text.AttributeSet;
45 import javax.swing.text.BadLocationException;
46 import javax.swing.text.PlainDocument;
47 
48 import net.sourceforge.jnlp.config.DeploymentConfiguration;
49 import net.sourceforge.jnlp.runtime.Translator;
50 
51 /**
52  * This is the pane used with creating a JDialog version. This allows changing
53  * the network configuration: Proxy
54  *
55  * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
56  *
57  */
58 @SuppressWarnings("serial")
59 public class NetworkSettingsPanel extends JPanel implements ActionListener {
60 
61     private final DeploymentConfiguration config;
62 
63     private JPanel description;
64     private final ArrayList<JPanel> proxyPanels = new ArrayList<>(); // The stuff with editable fields
65 
66     /** List of properties used by this panel */
67     public static String[] properties = {
68         DeploymentConfiguration.KEY_PROXY_TYPE,
69         DeploymentConfiguration.KEY_PROXY_HTTP_HOST,
70         DeploymentConfiguration.KEY_PROXY_HTTP_PORT,
71         DeploymentConfiguration.KEY_PROXY_BYPASS_LOCAL,
72         DeploymentConfiguration.KEY_PROXY_AUTO_CONFIG_URL
73     };
74 
75     /**
76      * Creates a new instance of the network settings panel.
77      *
78      * @param config
79      *            Loaded DeploymentConfiguration file.
80      */
NetworkSettingsPanel(DeploymentConfiguration config)81     public NetworkSettingsPanel(DeploymentConfiguration config) {
82         super();
83         this.config = config;
84         setLayout(new BorderLayout());
85 
86         addComponents();
87     }
88 
89     /**
90      * This adds the components to the panel.
91      */
addComponents()92     protected void addComponents() {
93         JPanel settingPanel = new NamedBorderPanel(Translator.R("CPHeadNetworkSettings"));
94         settingPanel.setLayout(new GridBagLayout());
95         GridBagConstraints c = new GridBagConstraints();
96         c.fill = GridBagConstraints.BOTH;
97         c.weightx = 1;
98         c.weighty = 1;
99         c.gridx = 0;
100 
101         JLabel networkDesc = new JLabel("<html>" + Translator.R("CPNetworkSettingsDescription") + "<hr /></html>");
102 
103         JLabel[] description = { new JLabel("<html>" + Translator.R("NSDescription-1") + "</html>"),
104                 new JLabel("<html>" + Translator.R("NSDescription0") + "</html>"),
105                 new JLabel("<html>" + Translator.R("NSDescription1") + "</html>"),
106                 new JLabel("<html>" + Translator.R("NSDescription2") + "</html>"),
107                 new JLabel("<html>" + Translator.R("NSDescription3") + "</html>") };
108 
109         this.description = new JPanel(new CardLayout());
110         for (int i = 0; i < description.length; i++)
111             this.description.add(description[i], String.valueOf(i - 1));
112 
113         // Settings for selecting Proxy Server
114         JPanel proxyServerPanel = new JPanel(new GridLayout(0, 1));
115         JPanel proxyLocationPanel = new JPanel(new GridBagLayout());
116         JPanel proxyBypassPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
117 
118         JLabel addressLabel = new JLabel(Translator.R("NSAddress") + ":");
119         JLabel portLabel = new JLabel(Translator.R("NSPort") + ":");
120         final JTextField addressField = new JTextField(config.getProperty(properties[1]), 10);
121         addressField.getDocument().addDocumentListener(new DocumentAdapter(config, properties[1]));
122 
123         final JTextField portField = new JTextField(5);
124         portField.setDocument(NetworkSettingsPanel.getPortNumberDocument());
125         portField.getDocument().addDocumentListener(new DocumentAdapter(config, properties[2]));
126         portField.setText(config.getProperty(properties[2]));
127 
128         // Create the button which allows setting of other types of proxy.
129         JButton advancedProxyButton = new JButton(Translator.R("NSAdvanced") + "...");
130         advancedProxyButton.addActionListener(new ActionListener() {
131             @Override
132             public void actionPerformed(ActionEvent e) {
133                 AdvancedProxySettingsDialog.showAdvancedProxySettingsDialog(config);
134                 addressField.setText(config.getProperty(properties[1]));
135                 portField.setText(config.getProperty(properties[2]));
136             }
137         });
138 
139         JCheckBox bypassCheckBox = new JCheckBox(Translator.R("NSBypassLocal"), Boolean.parseBoolean(config.getProperty(properties[3])));
140         bypassCheckBox.addItemListener(new ItemListener() {
141             @Override
142             public void itemStateChanged(ItemEvent e) {
143                 config.setProperty(properties[3], String.valueOf(e.getStateChange() == ItemEvent.SELECTED));
144             }
145         });
146         c.gridy = 0;
147         c.gridx = GridBagConstraints.RELATIVE;
148         c.weightx = 0;
149         proxyLocationPanel.add(Box.createHorizontalStrut(20), c);
150         proxyLocationPanel.add(addressLabel, c);
151         c.weightx = 1;
152         proxyLocationPanel.add(addressField, c);
153         c.weightx = 0;
154         proxyLocationPanel.add(portLabel, c);
155         c.weightx = 1;
156         proxyLocationPanel.add(portField, c);
157         c.weightx = 0;
158         proxyLocationPanel.add(advancedProxyButton, c);
159         proxyBypassPanel.add(Box.createHorizontalStrut(5));
160         proxyBypassPanel.add(bypassCheckBox);
161 
162         proxyServerPanel.add(proxyLocationPanel);
163         proxyServerPanel.add(proxyBypassPanel);
164 
165         JRadioButton directConnection = new JRadioButton(Translator.R("NSDirectConnection"), config.getProperty(properties[0]).equals("0"));
166         directConnection.setActionCommand("0");
167         directConnection.addActionListener(this);
168 
169         JRadioButton useProxyServer = new JRadioButton(Translator.R("NSManualProxy"), config.getProperty(properties[0]).equals("1"));
170         useProxyServer.setActionCommand("1");
171         useProxyServer.addActionListener(this);
172 
173         JRadioButton useAutoProxyConfigScript = new JRadioButton(Translator.R("NSAutoProxy"), config.getProperty(properties[0]).equals("2"));
174         useAutoProxyConfigScript.setActionCommand("2");
175         useAutoProxyConfigScript.addActionListener(this);
176 
177         JRadioButton useBrowserSettings = new JRadioButton(Translator.R("NSBrowserProxy"), config.getProperty(properties[0]).equals("3"));
178         useBrowserSettings.setActionCommand("3");
179         useBrowserSettings.addActionListener(this);
180 
181         ButtonGroup modeSelect = new ButtonGroup();
182         modeSelect.add(useBrowserSettings);
183         modeSelect.add(useProxyServer);
184         modeSelect.add(useAutoProxyConfigScript);
185         modeSelect.add(directConnection);
186 
187         // Settings for Automatic Proxy Configuration Script
188         JPanel proxyAutoPanel = new JPanel(new GridBagLayout());
189         JLabel locationLabel = new JLabel(Translator.R("NSScriptLocation") + ":");
190         final JTextField locationField = new JTextField(config.getProperty(properties[4]), 20);
191         locationField.getDocument().addDocumentListener(new DocumentAdapter(config, properties[4]));
192 
193         c.gridx = 0;
194         proxyAutoPanel.add(Box.createHorizontalStrut(20), c);
195         c.gridx = GridBagConstraints.RELATIVE;
196         proxyAutoPanel.add(locationLabel, c);
197         c.weightx = 1;
198         proxyAutoPanel.add(locationField, c);
199 
200         c.weighty = 0;
201         c.gridx = 0;
202         c.gridy = 0;
203         settingPanel.add(networkDesc, c);
204         c.gridy = 1;
205         settingPanel.add(this.description, c);
206         c.gridy = 2;
207         settingPanel.add(directConnection, c);
208         c.gridy = 3;
209         settingPanel.add(useBrowserSettings, c);
210         c.gridy = 4;
211         settingPanel.add(useProxyServer, c);
212         c.gridy = 5;
213         settingPanel.add(proxyServerPanel, c);
214         proxyPanels.add(proxyServerPanel);
215         c.gridy = 6;
216         settingPanel.add(useAutoProxyConfigScript, c);
217         c.gridy = 7;
218         settingPanel.add(proxyAutoPanel, c);
219         proxyPanels.add(proxyAutoPanel);
220 
221         // Filler to pack the bottom of the panel.
222         Component filler = Box.createRigidArea(new Dimension(1, 1));
223         c.gridy++;
224         c.weighty = 1;
225         settingPanel.add(filler, c);
226 
227         setState(); // depending on default setting we will enable or disable
228 
229         add(settingPanel, BorderLayout.CENTER);
230 
231     }
232 
233     /**
234      * Enable/Disable the panel and all its children recursively.
235      *
236      * @param panel
237      *            JPanel which needs to be enabled or disabled.
238      * @param enable
239      *            true if the panel and its children are to be enabled, false
240      *            otherwise.
241      */
enablePanel(JPanel panel, boolean enable)242     private void enablePanel(JPanel panel, boolean enable) {
243         // This will be used to enable all components in this panel recursively.
244         // Ridiculously slow if lots of nested panels.
245         for (Component c : panel.getComponents()) {
246             if (c instanceof JPanel) {
247                 enablePanel((JPanel) c, enable);
248             }
249             c.setEnabled(enable);
250         }
251     }
252 
253     @Override
actionPerformed(ActionEvent e)254     public void actionPerformed(ActionEvent e) {
255         config.setProperty(properties[0], e.getActionCommand());
256         setState();
257     }
258 
259     /**
260      * This enables and disables the appropriate panels.
261      */
setState()262     private void setState() {
263         ((CardLayout) this.description.getLayout()).show(this.description, config.getProperty(properties[0]));
264         switch (config.getProperty(properties[0])) {
265             case "0":
266                 for (JPanel panel : proxyPanels)
267                     enablePanel(panel, false);
268                 break;
269             case "1":
270                 enablePanel(proxyPanels.get(1), false);
271                 enablePanel(proxyPanels.get(0), true);
272                 break;
273             case "2":
274                 enablePanel(proxyPanels.get(0), false);
275                 enablePanel(proxyPanels.get(1), true);
276                 break;
277             case "3":
278                 for (JPanel panel : proxyPanels)
279                     enablePanel(panel, false);
280                 break;
281         }
282     }
283 
284     /**
285      * Creates a PlainDocument that only take numbers if it will create a valid port number.
286      * @return PlainDocument which will ensure numeric values only and is a valid port number.
287      */
getPortNumberDocument()288     public static PlainDocument getPortNumberDocument(){
289         return new PlainDocument(){
290             @Override
291             public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
292                 if (str != null) {
293                     try {
294                         Integer.valueOf(str);
295                         int val = Integer.valueOf(this.getText(0, this.getLength()) + str);
296                         if (val < 1 || val > 65535) { // Invalid port number if true
297                             throw new NumberFormatException("Invalid port number");
298                         }
299                         super.insertString(offs, str, a);
300                     } catch (Exception e) {
301                         JOptionPane.showMessageDialog(null, Translator.R("CPInvalidPort"), Translator.R("CPInvalidPortTitle")
302                                 , JOptionPane.WARNING_MESSAGE);
303                     }
304                 }
305             }
306         };
307     }
308 }
309