/*=============================================================================#
 # Copyright (c) 2009, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.r.console.ui.launching;

import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ibm.icu.text.DateFormat;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
import org.eclipse.ui.statushandlers.StatusManager;

import org.eclipse.statet.jcommons.rmi.RMIAddress;

import org.eclipse.statet.ecommons.ui.SharedUIResources;
import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.viewers.ViewerUtils.TreeComposite;

import org.eclipse.statet.internal.r.console.ui.Messages;
import org.eclipse.statet.internal.r.console.ui.RConsoleUIPlugin;
import org.eclipse.statet.rj.server.RjsComConfig;
import org.eclipse.statet.rj.server.Server;
import org.eclipse.statet.rj.server.ServerInfo;


public class RRemoteConsoleSelectionDialog extends SelectionStatusDialog {
	
	
	public static abstract class SpecialAddress {
		
		private final RMIAddress rmiAddress;
		private final String privateHost;
		
		
		public SpecialAddress(final RMIAddress rmiAddress, final String privateHost) {
			this.rmiAddress= rmiAddress;
			this.privateHost= privateHost;
		}
		
		
		public abstract RMIClientSocketFactory getSocketFactory(IProgressMonitor monitor) throws CoreException;
		
	}
	
	
	private static final String SETTINGS_DIALOG_ID= "RRemoteConsoleSelection"; //$NON-NLS-1$
	private static final String SETTINGS_HOST_HISTORY_KEY= "hosts.history"; //$NON-NLS-1$
	
	private static final Pattern ADDRESS_MULTI_PATTERN= Pattern.compile("\\/?\\s*[\\,\\;]+\\s*"); //$NON-NLS-1$
	private static final Pattern ADDRESS_WITH_PORT_PATTERN= Pattern.compile("(.*):(\\d{1,5})"); //$NON-NLS-1$
	
	
	private static class RemoteR {
		
		final String hostName;
		final String hostIP;
		final String address;
		
		final ServerInfo info;
		
		RemoteR(final String hostName, final String hostIP, final String address, final ServerInfo info) {
			this.hostName= hostName;
			this.hostIP= hostIP;
			this.address= address;
			
			this.info= info;
		}
		
		String createSummary() {
			final StringBuilder sb= new StringBuilder(100);
			sb.append("Address:   ").append(this.address).append('\n');
			sb.append('\n');
			sb.append("Host-Name: ").append(this.hostName).append('\n');
			sb.append("Host-IP:   ").append(this.hostIP).append('\n');
			sb.append("Date:      ").append((this.info.getTimestamp() != 0) ?
					DateFormat.getDateInstance().format(this.info.getTimestamp()) : "<unknown>").append('\n');
			sb.append("Directory: ").append(this.info.getDirectory()).append('\n');
			sb.append("Status:    ");
			switch (this.info.getState()) {
			case Server.S_NOT_STARTED:
				sb.append("New – Ready to connect and start R");
				break;
			case Server.S_CONNECTED:
			case Server.S_CONNECTED_STALE:
				sb.append("Running – Connected (username is ");
				sb.append((this.info.getUsername(ServerInfo.USER_CONSOLE) != null) ?
						this.info.getUsername(ServerInfo.USER_CONSOLE)  : "<unknown>").append(')');
				break;
			case Server.S_LOST:
				sb.append("Running – Connection lost / Ready to reconnect");
				break;
			case Server.S_DISCONNECTED:
				sb.append("Running – Disconnected / Ready to reconnect");
				break;
			case Server.S_STOPPED:
				sb.append("Stopped");
				break;
			default:
				sb.append("Unknown");
				break;
			}
			return sb.toString();
		}
		
	}
	
	private static class RemoteRContentProvider implements ITreeContentProvider {
		
		private final HashMap<String, RemoteR[]> mapping= new HashMap<>();
		
		@Override
		public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
		}
		
		@Override
		@SuppressWarnings({ "unchecked", "rawtypes" })
		public Object[] getElements(final Object inputElement) {
			final List<RemoteR> all= (List<RemoteR>) inputElement;
			
			this.mapping.clear();
			final Map mapping= this.mapping;
			for (final RemoteR r : all) {
				final String username= r.info.getUsername(ServerInfo.USER_OWNER).toLowerCase();
				List<RemoteR> list= (List<RemoteR>) mapping.get(username);
				if (list == null) {
					list= new ArrayList<>();
					mapping.put(username, list);
				}
				list.add(r);
			}
			
			final Set<Map.Entry> entrySet= mapping.entrySet();
			for (final Entry cat : entrySet) {
				final List<RemoteR> list= (List<RemoteR>) cat.getValue();
				cat.setValue(list.toArray(new RemoteR[list.size()]));
			}
			return this.mapping.keySet().toArray();
		}
		
		@Override
		public Object getParent(final Object element) {
			if (element instanceof RemoteR) {
				return ((RemoteR) element).info.getUsername(ServerInfo.USER_OWNER);
			}
			return null;
		}
		
		@Override
		public boolean hasChildren(final Object element) {
			return (element instanceof String);
		}
		
		@Override
		public Object[] getChildren(final Object parentElement) {
			if (parentElement instanceof String) {
				return this.mapping.get(parentElement);
			}
			return null;
		}
		
		@Override
		public void dispose() {
		}
		
	}
	
	private static abstract class RemoteRLabelProvider extends CellLabelProvider {
		
		@Override
		public void update(final ViewerCell cell) {
			final Object element= cell.getElement();
			String text= null;
			if (element instanceof RemoteR) {
				text= getText((RemoteR) element);
			}
			cell.setText(text);
		}
		
		public abstract String getText(RemoteR r);
		
		@Override
		public Font getToolTipFont(final Object element) {
			if (element instanceof RemoteR) {
				return JFaceResources.getTextFont();
			}
			return null;
		}
		
		@Override
		public String getToolTipText(final Object element) {
			if (element instanceof RemoteR) {
				return ((RemoteR) element).createSummary();
			}
			return null;
		}
		
	}
	
	
	private Combo hostAddressControl;
	
	private TreeViewer rServerViewer;
	
	private List<RemoteR> rServerList;
	
	private final boolean filterOnlyRunning;
	
	private String username;
	
	private final List<String> historyAddress= new ArrayList<>(DialogUtils.HISTORY_MAX + 10);
	private final List<String> additionalAddress= new ArrayList<>(8);
	private final Map<String, SpecialAddress> specialAddress= new HashMap<>(8);
	private String initialAddress;
	
	
	public RRemoteConsoleSelectionDialog(final Shell parentShell, final boolean onlyRunning) {
		super(parentShell);
		setTitle(Messages.RRemoteConsoleSelectionDialog_title);
		setMessage(Messages.RRemoteConsoleSelectionDialog_message);
		
		setStatusLineAboveButtons(true);
		setDialogBoundsSettings(getDialogSettings(), Dialog.DIALOG_PERSISTSIZE);
		
		this.username= System.getProperty("user.name"); //$NON-NLS-1$
		this.filterOnlyRunning= onlyRunning;
	}
	
	
	public void setUser(final String username) {
		if (username != null && username.length() > 0) {
			this.username= username;
		}
	}
	
	public void setInitialAddress(final String address) {
		this.additionalAddress.remove(address);
		this.additionalAddress.add(0, address);
		this.initialAddress= address;
	}
	
	public void addAdditionalAddress(final String label, final SpecialAddress factory) {
		this.additionalAddress.add(label);
		if (factory != null) {
			this.specialAddress.put(label, factory);
		}
	}
	
	public void clearAdditionaAddress(final boolean specialOnly) {
		if (specialOnly) {
			for (final Entry<String, ?> entry : this.specialAddress.entrySet()) {
				this.additionalAddress.remove(entry.getKey());
			}
		}
		else {
			this.additionalAddress.clear();
		}
		this.specialAddress.clear();
	}
	
	
	protected IDialogSettings getDialogSettings() {
		return DialogUtils.getDialogSettings(RConsoleUIPlugin.getInstance(), SETTINGS_DIALOG_ID);
	}
	
	@Override
	protected Control createContents(final Composite parent) {
//		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.statet.r.ui.remote_engine_selection_dialog"); //$NON-NLS-1$
		
		return super.createContents(parent);
	}
	
	@Override
	protected Control createDialogArea(final Composite parent) {
		// page group
		final Composite area= (Composite) super.createDialogArea(parent);
		
		createMessageArea(area);
		final IDialogSettings dialogSettings= getDialogSettings();
		
		{	final Composite composite= new Composite(area, SWT.NONE);
			composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
			composite.setLayout(LayoutUtils.newCompositeGrid(3));
			
			final Label label= new Label(composite, SWT.NONE);
			label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
			label.setText(Messages.RRemoteConsoleSelectionDialog_Hostname_label);
			
			this.hostAddressControl= new Combo(composite, SWT.DROP_DOWN);
			final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false);
			gd.widthHint= LayoutUtils.hintWidth(this.hostAddressControl, 50);
			this.hostAddressControl.setLayoutData(gd);
			final String[] history= dialogSettings.getArray(SETTINGS_HOST_HISTORY_KEY);
			if (history != null) {
				this.historyAddress.addAll(Arrays.asList(history));
			}
			this.hostAddressControl.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetDefaultSelected(final SelectionEvent e) {
					update();
				}
			});
			
			final Button goButton= new Button(composite, SWT.PUSH);
			goButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
			goButton.setText(Messages.RRemoteConsoleSelectionDialog_Update_label);
			goButton.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(final SelectionEvent e) {
					update();
				}
			});
		}
		
		{	final TreeComposite composite= new TreeComposite(area, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
			final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
			gd.heightHint= LayoutUtils.hintHeight(composite.tree, 10);
			composite.setLayoutData(gd);
			this.rServerViewer= composite.viewer;
			composite.tree.setHeaderVisible(true);
			ColumnViewerToolTipSupport.enableFor(composite.viewer);
			
			{	final TreeViewerColumn column= new TreeViewerColumn(this.rServerViewer, SWT.NONE);
				column.getColumn().setText(Messages.RRemoteConsoleSelectionDialog_Table_UserOrEngine_label);
				composite.layout.setColumnData(column.getColumn(), new ColumnWeightData(1));
				column.setLabelProvider(new RemoteRLabelProvider() {
					@Override
					public void update(final ViewerCell cell) {
						final Object element= cell.getElement();
						String text= null;
						Image image= null;
						if (element instanceof String) {
							text= (String) element;
							image= SharedUIResources.getImages().get(SharedUIResources.OBJ_USER_IMAGE_ID);
						}
						else if (element instanceof RemoteR) {
							text= getText((RemoteR) element);
						}
						cell.setText(text);
						cell.setImage(image);
					}
					
					@Override
					public String getText(final RemoteR r) {
						return r.info.getName();
					}
				});
			}
			{	final TreeViewerColumn column= new TreeViewerColumn(this.rServerViewer, SWT.NONE);
				column.getColumn().setText(Messages.RRemoteConsoleSelectionDialog_Table_Host_label);
				composite.layout.setColumnData(column.getColumn(), new ColumnWeightData(1));
				column.setLabelProvider(new RemoteRLabelProvider() {
					@Override
					public String getText(final RemoteR r) {
						return r.hostName;
					}
				});
			}
			
			this.rServerViewer.setContentProvider(new RemoteRContentProvider());
			
			this.rServerViewer.getTree().addSelectionListener(new SelectionListener() {
				@Override
				public void widgetSelected(final SelectionEvent e) {
					updateState();
				}
				@Override
				public void widgetDefaultSelected(final SelectionEvent e) {
					updateState();
					if (getOkButton().isEnabled()) {
						buttonPressed(IDialogConstants.OK_ID);
					}
				}
			});
		}
		
		Dialog.applyDialogFont(area);
		
		updateInput();
		if (this.rServerList != null) {
			updateStatus(new Status(IStatus.OK, RConsoleUIPlugin.BUNDLE_ID,
					Messages.RRemoteConsoleSelectionDialog_info_ListRestored_message ));
		}
		return area;
	}
	
	private void update() {
		final String input= this.hostAddressControl.getText();
		this.rServerList= null;
		final AtomicReference<IStatus> status= new AtomicReference<>();
		if (input != null && input.length() > 0) {
			try {
				new ProgressMonitorDialog(getShell()).run(true, true, new IRunnableWithProgress() {
					@Override
					public void run(final IProgressMonitor monitor) throws InvocationTargetException {
						status.set(updateRServerList(input, monitor));
					}
				});
			}
			catch (final InvocationTargetException e) {
				// not used
			}
			catch (final InterruptedException e) {
				this.rServerViewer= null;
				status.compareAndSet(null, Status.CANCEL_STATUS);
			}
		}
		if (status.get() != null) {
			updateStatus(status.get());
		}
		getOkButton().setEnabled(false);
		if (this.rServerList != null && this.rServerList.size() > 0) {
			if (!this.specialAddress.containsKey(input)) {
				this.historyAddress.remove(input);
				this.historyAddress.add(0, input);
			}
			if (this.filterOnlyRunning) {
				for (final Iterator<RemoteR> iter= this.rServerList.iterator(); iter.hasNext();) {
					switch (iter.next().info.getState()) {
					case Server.S_NOT_STARTED:
					case Server.S_STOPPED:
						iter.remove();
					}
				}
			}
			updateInput();
			return;
		}
		else {
			this.rServerViewer.setInput(null);
		}
	}
	
	private void updateInput() {
		final String selectedAddress= this.hostAddressControl.getText();
		final List<String> list= new ArrayList<>(this.historyAddress.size() + this.additionalAddress.size());
		list.addAll(this.historyAddress);
		for (final String address : this.additionalAddress) {
			if (!list.contains(address)) {
				list.add(address);
			}
		}
		this.hostAddressControl.setItems(list.toArray(new String[list.size()]));
		
		this.rServerViewer.setInput(this.rServerList);
		
		if (this.username != null && this.username.length() > 0) {
			Display.getCurrent().asyncExec(new Runnable() {
				@Override
				public void run() {
					if (RRemoteConsoleSelectionDialog.this.initialAddress != null) {
						RRemoteConsoleSelectionDialog.this.hostAddressControl.setText(RRemoteConsoleSelectionDialog.this.initialAddress);
						RRemoteConsoleSelectionDialog.this.initialAddress= null;
					}
					else if (selectedAddress != null && selectedAddress.length() > 0) {
						RRemoteConsoleSelectionDialog.this.hostAddressControl.setText(selectedAddress);
					}
					else if (RRemoteConsoleSelectionDialog.this.hostAddressControl.getItemCount() > 0) {
						RRemoteConsoleSelectionDialog.this.hostAddressControl.select(0);
					}
					RRemoteConsoleSelectionDialog.this.rServerViewer.expandToLevel(RRemoteConsoleSelectionDialog.this.username.toLowerCase(), 1);
					updateState();
				}
			});
		}
	}
	
	private void updateState() {
		final IStructuredSelection selection= (IStructuredSelection) this.rServerViewer.getSelection();
		getOkButton().setEnabled(selection.getFirstElement() instanceof RemoteR);
	}
	
	@Override
	protected void computeResult() {
		final IStructuredSelection selection= (IStructuredSelection) this.rServerViewer.getSelection();
		final Object element= selection.getFirstElement();
		if (element instanceof RemoteR) {
			setSelectionResult(new Object[] { ((RemoteR) element).address });
		}
	}
	
	@Override
	public boolean close() {
		final IDialogSettings dialogSettings= getDialogSettings();
		dialogSettings.put(SETTINGS_HOST_HISTORY_KEY, this.historyAddress.toArray(new String[this.historyAddress.size()]));
		
		return super.close();
	}
	
	private IStatus updateRServerList(final String combined, final IProgressMonitor monitor) {
		final List<RemoteR> infos= new ArrayList<>();
		
		final String[] addresses= ADDRESS_MULTI_PATTERN.split(combined, -1);
		if (addresses.length == 0) {
			return null;
		}
		final SubMonitor m= SubMonitor.convert(monitor, Messages.RRemoteConsoleSelectionDialog_task_Gathering_message, addresses.length*2 +2);
		
		String failedHosts= null;
		final List<IStatus> failedStatus= new ArrayList<>();
		m.worked(1);
		
		// Collect R engines for each address
		for (int i= 0; i < addresses.length; i++) {
			m.setWorkRemaining((addresses.length - i) * 2 + 1);
			
			String address= addresses[i];
			final SpecialAddress special= this.specialAddress.get(address);
			if (special == null) {
				if (address.startsWith("rmi:")) { //$NON-NLS-1$
					address= address.substring(4);
				}
				if (address.startsWith("//")) { //$NON-NLS-1$
					address= address.substring(2);
				}
			}
			if (address.isEmpty()) {
				return null;
			}
			if (monitor.isCanceled()) {
				return Status.CANCEL_STATUS;
			}
			IStatus status;
			if (special == null) {
				final Matcher matcher= ADDRESS_WITH_PORT_PATTERN.matcher(address);
				if (matcher.matches()) {
					status= collectServerInfos(matcher.group(1), Integer.parseInt(matcher.group(2)), null,
							infos, m.newChild(1) );
				}
				else {
					status= collectServerInfos(address, Registry.REGISTRY_PORT, null,
							infos, m.newChild(1) );
				}
			}
			else {
				address= special.rmiAddress.getAddress();
				status= collectServerInfos(null, 0, special, infos, m.newChild(1));
			}
			switch (status.getSeverity()) {
			case IStatus.CANCEL:
				return status;
			case IStatus.ERROR:
				StatusManager.getManager().handle(status, StatusManager.LOG);
				return status;
			case IStatus.WARNING:
				failedStatus.add(status);
				failedHosts= (failedHosts == null) ? address : (failedHosts + ", " + address); //$NON-NLS-1$
				continue;
			default:
				continue;
			}
		}
		
		if (!failedStatus.isEmpty()) {
			StatusManager.getManager().handle(new MultiStatus(RConsoleUIPlugin.BUNDLE_ID, 0, 
					failedStatus.toArray(new IStatus[failedStatus.size()]),
					"Info about connection failures when browsing R engines:", null), //$NON-NLS-1$
					StatusManager.LOG );
		}
		if (!infos.isEmpty() || failedStatus.isEmpty() ) {
			this.rServerList= infos;
		}
		
		if (failedHosts != null) {
			return new Status(IStatus.WARNING, RConsoleUIPlugin.BUNDLE_ID,
					Messages.RRemoteConsoleSelectionDialog_error_ConnectionFailed_message+failedHosts );
		}
		return Status.OK_STATUS;
	}
	
	private static IStatus collectServerInfos(String address, int port,
			final SpecialAddress special,
			final List<RemoteR> infos, final SubMonitor m) {
		try {
			if (special != null) {
				address= special.rmiAddress.getAddress();
				port= special.rmiAddress.getPort().get();
			}
			m.subTask(NLS.bind(Messages.RRemoteConsoleSelectionDialog_task_Resolving_message, address));
			final InetAddress inetAddress= InetAddress.getByName(address);
			final String hostname= inetAddress.getHostName();
			final String hostip= inetAddress.getHostAddress();
			m.worked(1);
			if (m.isCanceled()) {
				return Status.CANCEL_STATUS;
			}
			
			m.subTask(NLS.bind(Messages.RRemoteConsoleSelectionDialog_task_Connecting_message, hostname));
			final Registry registry;
			if (special != null) {
				final RMIClientSocketFactory socketFactory= special.getSocketFactory(m.newChild(5));
				RjsComConfig.setRMIClientSocketFactory(socketFactory);
				registry= LocateRegistry.getRegistry(special.privateHost, port, socketFactory );
			}
			else {
				RjsComConfig.setRMIClientSocketFactory(null);
				registry= LocateRegistry.getRegistry(address, port);
			}
			final String rmiBase= (port == Registry.REGISTRY_PORT) ?
					"//" + address + '/' : //$NON-NLS-1$
					"//" + address + ':' + port + '/'; //$NON-NLS-1$
			final String[] names= registry.list();
			for (final String name : names) {
				try {
					final Remote remote= registry.lookup(name);
					if (remote instanceof Server) {
						final Server server= (Server) remote;
						final ServerInfo info= server.getInfo();
						final String rmiAddress= rmiBase+name;
						final RemoteR r= new RemoteR(hostname, hostip, rmiAddress, info);
						infos.add(r);
					}
				}
				catch (final Exception e) {
				}
			}
			return Status.OK_STATUS;
		}
		catch (final RemoteException e) {
			return new Status(IStatus.WARNING, RConsoleUIPlugin.BUNDLE_ID, address);
		}
		catch (final UnknownHostException e) {
			return new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, "Unknown host: " + e.getLocalizedMessage()); //$NON-NLS-1$
		}
		catch (final CoreException e) {
			return e.getStatus();
		}
		finally {
			RjsComConfig.clearRMIClientSocketFactory();
		}
	}
	
}
