/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tuscany.sca.host.corba;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @version $Rev$ $Date$
* Class partially copied from eclipse wst project
* (http://repo1.maven.org/maven2/org/eclipse/wst/server/core/1.0.205-v20070829b/).
* Finally we should use jar from maven dependency. Problem described in
* http://www.fornax-platform.org/cp/display/fornax/2.+Hello+World+Tutorial+(CSC)?replyToComment=2098#comment-2098
* needs to be fixed.
*/
public class SocketUtil {
protected static final Object lock = new Object();
private static Set<String> localHostCache;
private static Set<String> notLocalHostCache = new HashSet<String>();
private static Map<String, CacheThread> threadMap = new HashMap<String, CacheThread>();
private static Set<InetAddress> addressCache;
static class CacheThread extends Thread {
private Set<InetAddress> currentAddresses;
private Set<String> addressList;
private String host;
private Set<String> nonAddressList;
private Map<String, CacheThread> threadMap2;
public CacheThread(String host,
Set<InetAddress> currentAddresses,
Set<String> addressList,
Set<String> nonAddressList,
Map<String, CacheThread> threadMap2) {
super("Caching localhost information");
this.host = host;
this.currentAddresses = currentAddresses;
this.addressList = addressList;
this.nonAddressList = nonAddressList;
this.threadMap2 = threadMap2;
}
public void run() {
if (currentAddresses != null) {
Iterator<InetAddress> iter2 = currentAddresses.iterator();
while (iter2.hasNext()) {
InetAddress addr = iter2.next();
String hostname = addr.getHostName();
String hostname2 = addr.getCanonicalHostName();
synchronized (lock) {
if (hostname != null && !addressList.contains(hostname))
addressList.add(hostname);
if (hostname2 != null && !addressList.contains(hostname2))
addressList.add(hostname2);
}
}
}
try {
InetAddress[] addrs = InetAddress.getAllByName(host);
int length = addrs.length;
for (int j = 0; j < length; j++) {
InetAddress addr = addrs[0];
String hostname = addr.getHostName();
String hostname2 = addr.getCanonicalHostName();
synchronized (lock) {
if (addr.isLoopbackAddress()) {
if (hostname != null && !addressList.contains(hostname))
addressList.add(hostname);
if (hostname2 != null && !addressList.contains(hostname2))
addressList.add(hostname2);
} else {
if (hostname != null && !nonAddressList.contains(hostname))
nonAddressList.add(hostname);
if (hostname2 != null && !nonAddressList.contains(hostname2))
nonAddressList.add(hostname2);
}
}
}
} catch (UnknownHostException e) {
synchronized (lock) {
if (host != null && !nonAddressList.contains(host))
nonAddressList.add(host);
}
}
synchronized (lock) {
threadMap2.remove(host);
}
}
}
public static boolean isLocalhost(final String host) {
if (host == null || host.equals(""))
return false;
if ("localhost".equals(host) || "127.0.0.1".equals(host))
return true;
// check simple cases
try {
InetAddress localHostaddr = InetAddress.getLocalHost();
if (localHostaddr.getHostName().equals(host) || host.equals(localHostaddr.getCanonicalHostName())
|| localHostaddr.getHostAddress().equals(host))
return true;
} catch (Exception e) {
}
// check for current thread and wait if necessary
boolean currentThread = false;
try {
Thread t = null;
synchronized (lock) {
t = threadMap.get(host);
}
if (t != null && t.isAlive()) {
currentThread = true;
t.join(30);
}
} catch (Exception e) {
}
// check if cache is still ok
boolean refreshedCache = false;
try {
// get network interfaces
final Set<InetAddress> currentAddresses = new HashSet<InetAddress>();
currentAddresses.add(InetAddress.getLocalHost());
Enumeration<?> nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
NetworkInterface inter = (NetworkInterface)nis.nextElement();
Enumeration<InetAddress> ias = inter.getInetAddresses();
while (ias.hasMoreElements())
currentAddresses.add(ias.nextElement());
}
// check if cache is empty or old and refill it if necessary
if (addressCache == null || !addressCache.containsAll(currentAddresses)
|| !currentAddresses.containsAll(addressCache)) {
CacheThread cacheThread = null;
refreshedCache = true;
synchronized (lock) {
addressCache = currentAddresses;
notLocalHostCache = new HashSet<String>();
localHostCache = new HashSet<String>(currentAddresses.size() * 3);
Iterator<InetAddress> iter = currentAddresses.iterator();
while (iter.hasNext()) {
InetAddress addr = iter.next();
String a = addr.getHostAddress();
if (a != null && !localHostCache.contains(a))
localHostCache.add(a);
}
cacheThread = new CacheThread(host, currentAddresses, localHostCache, notLocalHostCache, threadMap);
threadMap.put(host, cacheThread);
cacheThread.setDaemon(true);
cacheThread.setPriority(Thread.NORM_PRIORITY - 1);
cacheThread.start();
}
cacheThread.join(200);
}
} catch (Exception e) {
}
synchronized (lock) {
if (localHostCache.contains(host))
return true;
if (notLocalHostCache.contains(host))
return false;
}
// if the cache hasn't been cleared, maybe we still need to lookup the
// host
if (!refreshedCache && !currentThread) {
try {
CacheThread cacheThread = null;
synchronized (lock) {
cacheThread = new CacheThread(host, null, localHostCache, notLocalHostCache, threadMap);
threadMap.put(host, cacheThread);
cacheThread.setDaemon(true);
cacheThread.setPriority(Thread.NORM_PRIORITY - 1);
cacheThread.start();
}
cacheThread.join(75);
synchronized (lock) {
if (localHostCache.contains(host))
return true;
}
} catch (Exception e) {
}
}
return false;
}
}