View Javadoc

1   /*
2    * $HeadURL: $
3    * $Date: $
4    * $Revision: $
5    * $Author: $
6    * 
7    * Copyright (c) 2005 MindTree Consulting Ltd. 
8    * 
9    * This file is part of Insight.
10   * 
11   * Insight is free software: you can redistribute it and/or modify it under the 
12   * terms of the GNU General Public License as published by the Free Software 
13   * Foundation, either version 3 of the License, or (at your option) any later 
14   * version.
15   * 
16   * Insight is distributed in the hope that it will be useful, but 
17   * WITHOUT ANY WARRANTY; without even the implied warranty of 
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
19   * Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public License along with 
22   * Insight.  If not, see <http://www.gnu.org/licenses/>.
23   */
24  package com.mindtree.techworks.insight.gui.preferences;
25  
26  import java.awt.Component;
27  import java.awt.GridBagConstraints;
28  import java.awt.GridBagLayout;
29  import java.awt.Insets;
30  import java.awt.event.ActionEvent;
31  import java.awt.event.ActionListener;
32  import java.util.ArrayList;
33  import java.util.Iterator;
34  
35  import javax.swing.AbstractListModel;
36  import javax.swing.BorderFactory;
37  import javax.swing.JButton;
38  import javax.swing.JCheckBox;
39  import javax.swing.JLabel;
40  import javax.swing.JList;
41  import javax.swing.JPanel;
42  import javax.swing.JPasswordField;
43  import javax.swing.JScrollPane;
44  import javax.swing.JTextField;
45  import javax.swing.ListSelectionModel;
46  
47  import com.mindtree.techworks.insight.InsightConstants;
48  import com.mindtree.techworks.insight.gui.widgets.StatusBar;
49  import com.mindtree.techworks.insight.preferences.PreferenceManager;
50  import com.mindtree.techworks.insight.preferences.model.Preference;
51  import com.mindtree.techworks.insight.preferences.model.PreferenceAttribute;
52  import com.mindtree.techworks.insight.preferences.model.PreferenceAttributeType;
53  import com.mindtree.techworks.insight.preferences.model.PreferenceInfo;
54  
55  
56  /**
57  *
58  * The <code>RemoteFilesUIPanel</code> displays the UI for editing 
59  * remote file set preferences.
60  *
61  * @see com.mindtree.techworks.insight.preferences.model.Preference
62  * @see com.mindtree.techworks.insight.gui.preferences.AbstractPreferencesUIPanel
63  *
64  * @author  Regunath B
65  * @version 1.0, 05/03/22
66  */
67  public class RemoteFilesUIPanel extends AbstractPreferencesUIPanel implements  ActionListener {
68  	
69  	/**
70  	 * Used for object serialization
71  	 */
72  	private static final long serialVersionUID = 3816413009678139497L;
73  	
74  	/**
75  	 * Constants for attribute Ids and prefixes of the remote file 
76  	 * set preference 
77  	 */
78  	private static final String REQUIRES_AUTHENTICATION = "authentication";
79  	private static final String REQUIRES_AUTHENTICATION_NAME = "Requires Authentication";
80  	private static final String USER = "username";
81  	private static final String USER_NAME = "User Name";
82  	private static final String PASSWORD = "password";
83  	private static final String PASSWORD_NAME = "Password";
84  	private static final String URL_PREFIX = "urlId";
85  //	private static final String URL_ATTRIB_NAME_PREFIX = "urlName";
86  	private static final String IGNORE_PROXY = "ignoreProxy";
87  	private static final String IGNORE_PROXY_NAME = "Ignore Proxy";
88  	
89  	/**
90  	 * Constants to identify the file set edit action
91  	 */
92  	private static final int NONE = 0;
93  	private static final int ADD = 1;
94  	private static final int EDIT = 2;
95  	private static final int REMOVE = 3;
96  	
97  	/**
98  	 * State that holds the action type
99  	 */
100 	private int action = NONE;
101 	
102 	/**
103 	 * The display widgets
104 	 */
105 	private JList configuredFilesetsList;
106 	private JButton addButton;
107 	private JButton editButton;
108 	private JButton removeButton;
109 	private JTextField nameField;
110 	private JList urlList;
111 	private JTextField newURLField;
112 	private JButton addURLButton;
113 	private JButton removeURLButton;
114 	private JCheckBox requiresAuthentication;
115 	private JTextField userField;
116 	private JPasswordField passwordField;
117 	private JCheckBox ignoreProxy;
118 	private JButton applyChangesButton;
119 	
120 	/**
121 	 * Layout definition for the fileset details
122 	 */
123 	private GridBagLayout gl;
124 	private GridBagConstraints gc;		
125 	
126 //	private FilesetModel filesetModel;
127 	
128 	/**
129 	 * No args constructor
130 	 */
131 	public RemoteFilesUIPanel() {
132 	}
133 
134 	/** 
135 	 * ActionListener interface method implementation
136 	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
137 	 */
138 	public void actionPerformed(ActionEvent event) {
139 		Object source = event.getSource();
140 		if (source == this.addButton) {
141 			this.action = ADD;
142 			this.configuredFilesetsList.removeSelectionInterval(0,this.configuredFilesetsList.getModel().getSize() - 1);
143 			setDetailsWidgetsEnable(true);
144 		} else if (source == this.editButton) {
145 			if (this.configuredFilesetsList.getSelectedIndex() > -1) {
146 				this.action = EDIT;
147 				PreferenceInfo prefInfo = (PreferenceInfo)this.configuredFilesetsList
148 					.getModel().getElementAt(this.configuredFilesetsList
149 							.getSelectedIndex());
150 				displayFilesetInfoForEdit(PreferenceManager.getInstance().getPreference(prefInfo.getCompleteId()));
151 			}
152 		} else if (source == this.removeButton) {
153 			if (this.configuredFilesetsList.getSelectedIndex() > -1) {
154 				this.action = REMOVE;
155 				((FilesetModel)this.configuredFilesetsList.getModel())
156 					.removeFileset(this.configuredFilesetsList.getSelectedIndex());
157 				setDetailsWidgetsEnable(false);
158 			}
159 		} else if (source == this.removeURLButton) {
160 			if (this.urlList.getSelectedIndex() > -1) {
161 				((URLListModel)this.urlList.getModel())
162 				.removeURL(this.urlList.getSelectedIndex());
163 			}
164 		} else if (source == this.addURLButton) {
165 			if (newURLField.getText().trim().length() > 0) {
166 				((URLListModel)this.urlList.getModel()).addURL(newURLField.getText());
167 				newURLField.setText("");
168 			}
169 		} else if (source == this.requiresAuthentication) {
170 			if (this.configuredFilesetsList.getSelectedIndex() > -1) {
171 				PreferenceInfo prefInfo = (PreferenceInfo)this.configuredFilesetsList.getModel().
172 				getElementAt(this.configuredFilesetsList.getSelectedIndex());
173 				checkAuthenticationEnable(PreferenceManager.getInstance().getPreference(prefInfo.getCompleteId()));
174 			} else {
175 				checkAuthenticationEnable(null);
176 			}
177 		} else if (source == applyChangesButton) {
178 			if (this.nameField.getText().trim().length() < InsightConstants.PREFERENCE_NAME_MIN_SIZE) {
179 				StatusBar.getInstance().setDisplayText(0,InsightConstants.getLiteral("ERROR_FILESET_NAME") + 
180 						InsightConstants.PREFERENCE_NAME_MIN_SIZE, false);
181 				return;
182 			}
183 			Preference childPreference = null;
184 			switch(this.action) {
185 				case ADD:
186 					childPreference = new Preference(String.valueOf(new Object().hashCode()), true, true, this.nameField.getText());
187 					createAndAddBooleanAttribute(childPreference, REQUIRES_AUTHENTICATION, 
188 							REQUIRES_AUTHENTICATION_NAME, this.requiresAuthentication);				
189 					createAndAddBooleanAttribute(childPreference, IGNORE_PROXY, 
190 							IGNORE_PROXY_NAME, this.ignoreProxy);
191 					createAndAddTextAttribute(childPreference, USER, USER_NAME, this.userField);
192 					createAndAddPasswordAttribute(childPreference, PASSWORD, PASSWORD_NAME, this.passwordField);
193 					
194 					this.preference.addChildPreference(childPreference);
195 					
196 					// update the GUI
197 					((FilesetModel)this.configuredFilesetsList.getModel()).addFileset(childPreference);
198 					
199 					break;
200 				case EDIT:
201 					childPreference = (Preference)((FilesetModel)this.configuredFilesetsList.
202 						getModel()).getPreference(this.configuredFilesetsList.getSelectedIndex());
203 					childPreference.setName(this.nameField.getText());
204 					childPreference.getPreferenceAttributeById(REQUIRES_AUTHENTICATION).setValue(this.requiresAuthentication.isSelected() ? TRUE : FALSE);
205 					childPreference.getPreferenceAttributeById(IGNORE_PROXY).setValue(this.ignoreProxy.isSelected() ? TRUE : FALSE);
206 					childPreference.getPreferenceAttributeById(USER).setValue(this.userField.getText());
207 					childPreference.getPreferenceAttributeById(PASSWORD).setValue(new String(this.passwordField.getPassword()));
208 					((FilesetModel)this.configuredFilesetsList.getModel()).listDataUpdated(this.configuredFilesetsList.getSelectedIndex());
209 					break;
210 			}
211 			// Remove all old URLs and add the new ones
212 			updateURLListToPreference(childPreference);
213 			setDetailsWidgetsEnable(false);
214 			this.action = NONE;
215 		}
216 	}
217 		
218 	
219 	/**
220 	 *  Overriden super class method
221 	 * @see com.mindtree.techworks.insight.gui.preferences.AbstractPreferencesUIPanel#initializeDisplay()
222 	 */
223 	protected void initializeDisplay() {
224 		this.configuredFilesetsList = new JList(new FilesetModel());
225 		this.configuredFilesetsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
226 		addComponent(new JLabel(InsightConstants.getLiteral("CONFIGURED_FILESETS")),0,0,0,0,1,1);		
227 		addComponent(new JScrollPane(configuredFilesetsList),1,0,1,1,1,4);	
228 		this.addButton = new JButton(InsightConstants.getLiteral("ADD"));
229 		this.editButton = new JButton(InsightConstants.getLiteral("EDIT"));
230 		this.removeButton = new JButton(InsightConstants.getLiteral("REMOVE"));
231 		this.addButton.addActionListener(this);
232 		this.editButton.addActionListener(this);
233 		this.removeButton.addActionListener(this);
234 		addComponent(addButton,2,0,0,0,1,1);	
235 		addComponent(editButton,2,1,0,0,1,1);	
236 		addComponent(removeButton,2,2,0,0,1,1);	
237 		
238 		// add the widgets for the fileset details
239 		JPanel filesetDetailsPanel = new JPanel();
240 		this.gl = new GridBagLayout();
241 		this.gc = new GridBagConstraints();
242 		filesetDetailsPanel.setLayout(gl);
243 		filesetDetailsPanel.setBorder(BorderFactory.createTitledBorder(InsightConstants.getLiteral("FILESET_DETAILS")));
244 		addComponent(filesetDetailsPanel,0,4,1,1,3,1);	
245 		
246 		addComponent(filesetDetailsPanel,new JLabel(InsightConstants.getLiteral("NAME")),0,0,0,0,1,1);
247 		this.nameField = new JTextField();
248 		addComponent(filesetDetailsPanel,nameField,1,0,1,0,4,1);
249 		this.urlList = new JList(new URLListModel());
250 		this.urlList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
251 		addComponent(filesetDetailsPanel,new JLabel(InsightConstants.getLiteral("URLS")),0,1,0,0,1,1);		
252 		addComponent(filesetDetailsPanel,new JScrollPane(urlList),1,1,1,1,4,2);			
253 		this.removeURLButton = new JButton(InsightConstants.getLiteral("REMOVE"));
254 		this.removeURLButton.addActionListener(this);
255 		addComponent(filesetDetailsPanel,removeURLButton,5,1,0,0,1,1);	
256 		addComponent(filesetDetailsPanel,new JLabel(InsightConstants.getLiteral("NEW_URL")),0,3,0,0,1,1);
257 		this.newURLField = new JTextField();
258 		addComponent(filesetDetailsPanel,newURLField,1,3,1,0,4,1);
259 		this.addURLButton = new JButton(InsightConstants.getLiteral("ADD"));
260 		this.addURLButton.addActionListener(this);
261 		addComponent(filesetDetailsPanel,addURLButton,5,3,0,0,1,1);	
262 		this.requiresAuthentication = new JCheckBox(InsightConstants.getLiteral("REQUIRES_AUTHENTICATION"));
263 		this.requiresAuthentication.addActionListener(this);
264 		addComponent(filesetDetailsPanel,requiresAuthentication,0,4,1,0,6,1);
265 		addComponent(filesetDetailsPanel,new JLabel(InsightConstants.getLiteral("USER")),0,5,0,0,1,1);
266 		this.userField = new JTextField();
267 		addComponent(filesetDetailsPanel,userField,1,5,1,0,1,1);
268 		addComponent(filesetDetailsPanel,new JLabel(InsightConstants.getLiteral("PASSWORD")),2,5,0,0,1,1);
269 		this.passwordField = new JPasswordField();
270 		addComponent(filesetDetailsPanel,passwordField,3,5,1,0,1,1);
271 		this.ignoreProxy = new JCheckBox(InsightConstants.getLiteral("IGNORE_PROXY"));
272 		addComponent(filesetDetailsPanel,ignoreProxy,0,6,1,0,6,1);
273 		this.applyChangesButton = new JButton(InsightConstants.getLiteral("APPLY_FILESET_CHANGES"));
274 		this.applyChangesButton.addActionListener(this);
275 		addComponent(filesetDetailsPanel,applyChangesButton,3,7,1,0,3,1);
276 		// disable the details widgets
277 		setDetailsWidgetsEnable(false);		
278 	}
279 	
280 
281 	/**
282 	 *  Overriden super class method
283 	 * @see com.mindtree.techworks.insight.gui.preferences.AbstractPreferencesUIPanel#setPreferenceValues()
284 	 */
285 	protected  void setPreferenceValues() {
286 		// update the fileset list change
287 		updateFilesetListToPreference();
288 	}
289 	
290 	/**
291 	 * Helper method to update the list of filesets in the Preference for this panel
292 	 */
293 	private final void updateFilesetListToPreference() {
294 		ArrayList oldValues = new ArrayList();
295 		Iterator iterator = this.preference.iterateChildPreferenceIds();
296 		while(iterator.hasNext()) {
297 			oldValues.add(iterator.next());
298 		}
299 		iterator = oldValues.iterator();
300 		while(iterator.hasNext()) {
301 			this.preference.removePreference(
302 					this.preference.getPreferenceById(
303 							(String)iterator.next()));
304 		}
305 		for (int i = 0; i < this.configuredFilesetsList.getModel().getSize(); i++) {
306 			this.preference.addChildPreference(((FilesetModel)this.configuredFilesetsList.getModel()).getPreference(i));
307 		}				
308 	}
309 	
310 	/**
311 	 * Helper method to update the list of URLs in the specified file set Preference
312 	 * @param childPreference the Preference to be updated with URL list
313 	 */
314 	private final void updateURLListToPreference(Preference childPreference) {
315 		ArrayList oldValues = new ArrayList();
316 		Iterator iterator = childPreference.iteratePreferenceAttributeIds();
317 		while(iterator.hasNext()) {
318 			String id = (String)iterator.next();
319 			if (id.startsWith(URL_PREFIX)) {
320 				oldValues.add(id);
321 			}
322 		}
323 		iterator = oldValues.iterator();
324 		while(iterator.hasNext()) {
325 			childPreference.removePreferenceAttribute(
326 					childPreference.getPreferenceAttributeById(
327 							(String)iterator.next()));
328 		}
329 		for (int i = 0; i < this.urlList.getModel().getSize(); i++) {
330 			String identifier = (String)this.urlList.getModel().getElementAt(i);
331 			PreferenceAttribute newAttribute = new PreferenceAttribute(PreferenceAttributeType.TEXT,
332 					URL_PREFIX + i, identifier, false,
333 					true, true, childPreference);
334 			newAttribute.setName(URL_PREFIX + i);
335 			childPreference.addPreferenceAttribute(newAttribute);
336 		}		
337 	}
338 	
339 	/**
340 	 * Helper method that displays the specified file set information for
341 	 * editing
342 	 * @param filesetInfo Presefernce containing the file set information
343 	 */
344 	private final void displayFilesetInfoForEdit(Preference filesetInfo) {
345 		setDetailsWidgetsEnable(true);
346 		this.nameField.setText(filesetInfo.getName());
347 		Iterator iterator = filesetInfo.iteratePreferenceAttributeIds();
348 		while(iterator.hasNext()) {			
349 			String id = (String)iterator.next();
350 			PreferenceAttribute prefAttribute = filesetInfo.getPreferenceAttributeById(id);
351 			if (id.startsWith(URL_PREFIX)) {
352 				((URLListModel)this.urlList.getModel()).addURL(prefAttribute.getValue());
353 			} else if (id.equals(REQUIRES_AUTHENTICATION)) {
354 				this.requiresAuthentication.setSelected(prefAttribute.getValue().equals(TRUE));
355 			} else if (id.equals(IGNORE_PROXY)) {
356 				this.ignoreProxy.setSelected(prefAttribute.getValue().equals(TRUE));
357 			}
358 		}
359 		checkAuthenticationEnable(filesetInfo);
360 	}
361 	
362 	/**
363 	 * Adds the specified component to the specified panel using the specified constraints.
364 	 **/
365 	private final void addComponent(JPanel panel, Component c, int gridx, int gridy, int weightx,
366 		int weighty, int width, int height) {
367 		gc.fill = GridBagConstraints.BOTH;
368 		gc.anchor = GridBagConstraints.NORTHWEST;
369 		gc.insets = new Insets(5,5,5,5);		
370 		gc.gridx = gridx;
371 		gc.gridy = gridy;
372 		gc.weightx = weightx;
373 		gc.weighty = weighty;
374 		gc.gridwidth = width;
375 		gc.gridheight = height;		
376 		gl.setConstraints( c, gc);
377 		panel.add(c);
378 	}	
379 
380 	/**
381 	 * Helper method to set the enable status of file set details widgest
382 	 * @param enable true to enable, false to disable
383 	 */
384 	private void setDetailsWidgetsEnable(boolean enable) {
385 		this.nameField.setText("");
386 		this.nameField.setEditable(enable);
387 		this.nameField.setEnabled(enable);		
388 		((URLListModel)this.urlList.getModel()).clearAll();
389 		this.urlList.setEnabled(enable);
390 		this.newURLField.setText("");
391 		this.newURLField.setEditable(enable);
392 		this.newURLField.setEnabled(enable);		
393 		this.requiresAuthentication.setEnabled(enable);
394 		this.ignoreProxy.setEnabled(enable);
395 		this.ignoreProxy.setSelected(false);
396 		this.requiresAuthentication.setSelected(false);
397 		// pass null so that only enabling/disabling is done
398 		checkAuthenticationEnable(null);
399 		this.removeURLButton.setEnabled(enable);
400 		this.addURLButton.setEnabled(enable);
401 		this.applyChangesButton.setEnabled(enable);
402 		if (enable) {
403 			this.nameField.requestFocus();
404 		}
405 	}
406 	
407 	/**
408 	 * Helper method that checks enabling and disabling of the user credential widgets
409 	 */
410 	private void checkAuthenticationEnable(Preference filesetInfo) {
411 		boolean authenticationEnabled = this.requiresAuthentication.isSelected();
412 		this.userField.setEditable(authenticationEnabled);
413 		this.passwordField.setEditable(authenticationEnabled);
414 		this.userField.setEnabled(authenticationEnabled);
415 		this.passwordField.setEnabled(authenticationEnabled);
416 		this.userField.setText((authenticationEnabled && filesetInfo != null) ? 
417 				filesetInfo.getPreferenceAttributeById(USER).getValue() : "");
418 		this.passwordField.setText((authenticationEnabled && filesetInfo != null) ? 
419 				filesetInfo.getPreferenceAttributeById(PASSWORD).getValue() : "");
420 	}	
421 
422 	/**
423 	 * Helper class to that acts as the model for the fileset JList 
424 	 */
425 	private class FilesetModel extends AbstractListModel {
426 		
427 		/**
428 		 * Used for object serialization
429 		 */
430 		private static final long serialVersionUID = 4136861131212594441L;
431 		
432 		/**
433 		 * Collection that holds the configured fileset data
434 		 */
435 		private ArrayList configuredFilesets = new ArrayList();
436 
437 		/**
438 		 * No args constructor
439 		 */
440 		public FilesetModel() {
441 			Iterator iterator = preference.iterateChildPreferences();
442 			while(iterator.hasNext()) {
443 				Preference filesetPreference = (Preference)iterator.next();
444 				configuredFilesets.add(filesetPreference);
445 			}			
446 		}
447 
448 		/**
449 		 * Adds the specified fileset information to this model
450 		 * @param filesetInfo Preference containing the file set information to be added
451 		 */
452 		public void addFileset(Preference filesetInfo) {
453 			configuredFilesets.add(filesetInfo);
454 			super.fireIntervalAdded(this, configuredFilesets.size() - 1, configuredFilesets.size() - 1);
455 		}
456 		
457 		/**
458 		 * Informs this model that the data at the specified index has changed
459 		 * @param index index at which the data has changed
460 		 */
461 		public void listDataUpdated(int index) {
462 			super.fireContentsChanged(this, index, index);
463 		}		
464 		
465 		/**
466 		 * Removes the specified fileset information to this model
467 		 * @param index from where to remove the file set information
468 		 */
469 		public void removeFileset(int index) {
470 			if (index < 0 || index >= configuredFilesets.size()) {
471 				return;
472 			}
473 			configuredFilesets.remove(index);
474 			super.fireIntervalRemoved(this, index, index);
475 		}
476 		
477 		
478 		/** 
479 		 * Superclass abstract method implementation
480 		 * @see javax.swing.ListModel#getSize()
481 		 */
482 		public int getSize() {
483 			return configuredFilesets.size();
484 		}
485 		
486 		/**
487 		 * Returns the Preference at the sepcified index
488 		 * @param index index of the required Preference
489 		 * @return Preference at the specified index
490 		 */
491 		public Preference getPreference(int index) {
492 			return (Preference)configuredFilesets.get(index);
493 		}
494 
495 		/** 
496 		 * Superclass abstract method implementation
497 		 * @see javax.swing.ListModel#getElementAt(int)
498 		 */
499 		public Object getElementAt(int index) {
500 			return ((Preference)configuredFilesets.get(index)).getPreferenceInfo();
501 		}
502 	}
503 	
504 	/**
505 	 * Helper class to that acts as the model for the URL JList 
506 	 */
507 	private class URLListModel extends AbstractListModel {
508 		
509 		/**
510 		 * Used for object serialization
511 		 */
512 		private static final long serialVersionUID = 897042512829232835L;
513 		
514 		/**
515 		 * Collection that holds the configured URL data
516 		 */
517 		private ArrayList configuredURLs = new ArrayList();
518 
519 		/**
520 		 * No args constructor
521 		 */
522 		public URLListModel() {
523 		}
524 
525 		/**
526 		 * Adds the specified URL information to this model
527 		 * @param url the URL string
528 		 */
529 		public void addURL(String url) {
530 			configuredURLs.add(url);
531 			super.fireIntervalAdded(this, configuredURLs.size() - 1, configuredURLs.size() - 1);
532 		}
533 		
534 		/**
535 		 * Removes the specified URL information to this model
536 		 * @param index from where to remove the URL information
537 		 */
538 		public void removeURL(int index) {
539 			if (index < 0 || index >= configuredURLs.size()) {
540 				return;
541 			}			
542 			configuredURLs.remove(index);
543 			super.fireIntervalRemoved(this, index, index);
544 		}
545 		
546 		/**
547 		 * Clears the entire list contents
548 		 */
549 		public void clearAll() {
550 			if (configuredURLs.size() > 0) {
551 				int lastIndex = configuredURLs.size() - 1;
552 				configuredURLs.clear();
553 				super.fireIntervalRemoved(this, 0, lastIndex);
554 			}
555 		}
556 		
557 		/** 
558 		 * Superclass abstract method implementation
559 		 * @see javax.swing.ListModel#getSize()
560 		 */
561 		public int getSize() {
562 			return configuredURLs.size();
563 		}
564 
565 		/** 
566 		 * Superclass abstract method implementation
567 		 * @see javax.swing.ListModel#getElementAt(int)
568 		 */
569 		public Object getElementAt(int index) {
570 			return configuredURLs.get(index);
571 		}
572 	}
573 
574 }