/******************************************************************************* * Copyright (c) 2017 Rogue Wave Software Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Rogue Wave Software Inc. - initial implementation *******************************************************************************/ package org.eclipse.php.internal.core.util; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; /** * Utility class for monitoring the network addresses of underlying workstation. * The network addresses detection is triggered in a separate job right after * the instantiation of a class and is performed only once for an instance * lifetime. Clients may also use this class to verify provided network * addresses validity by means of existence in detected addresses. * * @author Bartlomiej Laczkowski */ public class NetworkMonitor { private Inet4Address publicAddress; private List<Inet4Address> privateAddresses; private List<Inet4Address> allAddresses; private final CountDownLatch latch; private final Validator validator; private final Detector detector; public NetworkMonitor() { validator = new Validator(); detector = new Detector(); latch = new CountDownLatch(1); // Start address detection immediately detector.schedule(); } /** * Network addresses validation process listener. */ public static interface IHostsValidationListener { /** * Notifies about the results of validation process by means of the list * of invalid addresses (the ones that could not be found in the list of * addresses detected by the monitor). * * @param invalidAddresses */ void validated(List<String> invalidAddresses); } private class Detector extends Job { public Detector() { super(""); //$NON-NLS-1$ setSystem(true); setUser(false); addJobChangeListener(new JobChangeAdapter() { public void done(IJobChangeEvent event) { // Signal that addresses have been collected latch.countDown(); removeJobChangeListener(this); }; }); } @Override protected IStatus run(IProgressMonitor monitor) { publicAddress = NetworkUtil.getPublicAddress(); privateAddresses = new ArrayList<Inet4Address>(); privateAddresses.addAll(NetworkUtil.getPrivateAddresses()); allAddresses = new ArrayList<Inet4Address>(); if (publicAddress != null) allAddresses.add(publicAddress); allAddresses.addAll(privateAddresses); allAddresses.add(NetworkUtil.LOCALHOST); return Status.OK_STATUS; } } private class Validator extends AbstractDeferredJob { private String[] addresses; private IHostsValidationListener[] validationListeners; public Validator() { super("", 200); //$NON-NLS-1$ setSystem(true); setUser(false); } @Override protected IStatus run(final IProgressMonitor monitor) { try { // Wait for addresses to be collected latch.await(); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } List<String> invalid = new ArrayList<String>(); for (String clientHost : addresses) { if (monitor.isCanceled()) return Status.CANCEL_STATUS; if (!NetworkUtil.isIPv4Address(clientHost) && !clientHost.equalsIgnoreCase("localhost")) { //$NON-NLS-1$ // Mark invalid if it is not a literal IP address invalid.add(clientHost); continue; } if (monitor.isCanceled()) return Status.CANCEL_STATUS; Inet4Address clientHostAddress; try { clientHostAddress = (Inet4Address) InetAddress.getByName(clientHost); } catch (UnknownHostException e) { invalid.add(clientHost); continue; } boolean isInvalid = true; if (clientHostAddress != null) { if (NetworkUtil.isLoopbackAddress(clientHostAddress)) // Local addresses are always valid continue; for (Inet4Address address : allAddresses) { if (clientHostAddress.getHostAddress().equals(address.getHostAddress())) { isInvalid = false; break; } } } if (isInvalid) invalid.add(clientHost); } for (IHostsValidationListener validationListener : validationListeners) validationListener.validated(invalid); return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; } void validate(String[] addresses, IHostsValidationListener[] validationListeners) { this.addresses = addresses; this.validationListeners = validationListeners; defer(); } } /** * Validates the list of provided addresses by means of their existence in * the list of detected ones. * * @param addresses * @param validationListener */ public void validate(String[] addresses, IHostsValidationListener[] validationListeners) { validator.validate(addresses, validationListeners); } /** * Returns the list of all detected network addresses. * * @return list of all detected network addresses */ public List<Inet4Address> getAllAddresses() { try { // Wait for addresses to be collected latch.await(); } catch (InterruptedException e) { return new ArrayList<Inet4Address>(); } return allAddresses; } /** * Returns the list of detected private network addresses. * * @return list of detected private network addresses */ public List<Inet4Address> getPrivateAddresses() { try { // Wait for addresses to be collected latch.await(); } catch (InterruptedException e) { return new ArrayList<Inet4Address>(); } return privateAddresses; } /** * Returns detected public address. * * @return detected public address or <code>null</code> if no address could * be detected */ public Inet4Address getPublicAddress() { try { // Wait for addresses to be collected latch.await(); } catch (InterruptedException e) { return null; } return publicAddress; } }