/MDCDiscovery/src/main/java/org/smpte/_2071/_2012/mdcd/naming/NamingServices.java
https://bitbucket.org/psymes/34cs-st2071 · Java · 587 lines · 433 code · 72 blank · 82 comment · 92 complexity · 028e38a4b14be2e63ccdcc7951732b74 MD5 · raw file
- package org.smpte._2071._2012.mdcd.naming;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.InetAddress;
- import java.net.InetSocketAddress;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashSet;
- import java.util.LinkedHashSet;
- import java.util.Map;
- import java.util.Properties;
- import java.util.Set;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import javax.naming.NamingException;
- import org.smpte._2071._2012.mdcd.impl.Utils;
- import org.smpte._2071._2012.mdcd.naming.NamingService.NAMING_TYPE;
- import org.smpte._2071._2012.mdcd.net.DHCPClient;
- import org.xbill.DNS.Name;
- public class NamingServices
- {
- public static String FACTORY_PROPERTIES = "NamingServices.properties";
-
- public static final String NULL_DOMAIN = "";
-
- public static final String[] LOCALLINK_DNS_DOMAINS = new String[] {"local.",
- "254.169.in-arpa.",
- "8.e.f.ip6.arpa.",
- "9.e.f.ip6.arpa.",
- "a.e.f.ip6.arpa.",
- "b.e.f.ip6.arpa."};
-
- private static final Logger log = Logger.getLogger(NamingServices.class.getName());
-
- private Properties props = null;
-
- private CompoundKeyMap<InetAddress, String, NamingService> namingServices = new CompoundKeyMap<InetAddress, String, NamingService>();
-
-
- /**
- * Gets the Naming Service for the local interface address and the domain.
- *
- * @param localAddress The Internet address of the local interface
- * @param domain The domain
- * @return A Naming Service that represents all of the naming services registered for the local
- * interface address and the domain.
- */
- public NamingService getNamingService(InetAddress localAddress, String domain)
- {
- if (domain == null || domain.length() == 0)
- {
- return getDefaultNamingService(localAddress);
- }
-
- return namingServices.get(localAddress, domain);
- }
-
-
- /**
- * Returns the default Naming Service for the specified local address. Typically the Naming Service
- * Assigned by the OS to the Network Interface.
- *
- * @param localAddress THe IP address of the local network interface
- * @return The default Naming Service for the specified local address
- */
- public NamingService getDefaultNamingService(InetAddress localAddress)
- {
- NamingService defaultNamingService = namingServices.get(localAddress, NULL_DOMAIN);
-
- if (defaultNamingService == null)
- {
- try
- {
- defaultNamingService = new org.smpte._2071._2012.mdcd.naming.jndi.NamingServiceImpl();
- register(localAddress, null, defaultNamingService);
- } catch (Exception e)
- {
- Utils.log(log, Level.WARNING, "Could not create JNDI Naming Service, trying DHCP", Level.FINE, e);
- try
- {
- Set<InetSocketAddress> namingServerAddresses = new LinkedHashSet<InetSocketAddress>();
- Set<InetAddress> addresses = DHCPClient.resolveDHCPDomainNameServers(localAddress);
- if (addresses != null)
- {
- for (InetAddress address : addresses)
- {
- namingServerAddresses.add(new InetSocketAddress(address, 53));
- }
- }
-
- defaultNamingService = newNamingService(null, localAddress, namingServerAddresses);
- register(localAddress, null, defaultNamingService);
- } catch (Exception e1)
- {
- Utils.log(log, Level.SEVERE, "Could not create default Naming Service!", Level.FINE, e1);
- }
- }
- }
-
- return defaultNamingService;
- }
-
-
- /**
- * Returns the complete list of domain names registered with the Naming Services.
- *
- * @return The complete list of domain names registered with the Naming Services.
- */
- public Set<String> getDomains()
- {
- Set<String> allDomains = new LinkedHashSet<String>();
-
- Set<Map.Entry<InetAddress, Set<String>>> entries = namingServices.keyMap().entrySet();
- for (Map.Entry<InetAddress, Set<String>> entry : entries)
- {
- Set<String> domains = entry.getValue();
- for (String domain : domains)
- {
- if (domain.length() != 0)
- {
- allDomains.add(domain);
- }
- }
- }
- return allDomains;
- }
-
-
- /**
- * Returns the list of domain names registered for the local interface address.
- *
- * @param address The Internet address of the local interface
- * @return The list of domains registered for the local interface address.
- */
- public Set<String> getDomains(InetAddress address)
- {
- Set<String> domains = new LinkedHashSet<String>();
- for (String domain : namingServices.keyMap().get(address))
- {
- if (domain.length() != 0)
- {
- domains.add(domain);
- }
- }
- return domains;
- }
-
-
- /**
- * Registers the Naming Service for the Internet Address and Domain.
- *
- * @param address The Internet Address. A null Internet Address indicates the default Naming Service for the browse domain
- * @param domain The browse domain. A null domain indicates the default Naming Service for the Internet Address/Interface
- * @param naming The Naming Service to register. Cannot be null.
- * @throws NamingException
- */
- public void register(InetAddress address, String domain, NamingService naming)
- throws NamingException
- {
- domain = (domain == null || domain.length() == 0 ? NULL_DOMAIN : domain);
-
- log.fine("Registering Naming Service for domain \"" + domain + "\"");
-
- if (naming.getNamingType() != NAMING_TYPE.MULTICAST_DNS)
- {
- for (String linkLocalDomain : LOCALLINK_DNS_DOMAINS)
- {
- if (domain.equals(linkLocalDomain))
- {
- throw new NamingException("Cannot register a Unicast Naming Service to Multicast Domain!");
- }
- }
- }
-
- if (naming != null)
- {
- naming.associateToDomain(domain);
- naming.setLocalAddress(address);
-
- NamingService existingNaming = namingServices.get(address, domain);
- if (existingNaming != null)
- {
- if (sameNamingDomain(existingNaming, naming))
- {
- // Eliminate duplicate addresses
- Set<InetSocketAddress> namingAddresses = new HashSet<InetSocketAddress>(naming.getServerAddresses());
- namingAddresses.removeAll(existingNaming.getServerAddresses());
-
- if (namingAddresses.size() > 0)
- {
- try
- {
- existingNaming.addServerAddresses(namingAddresses);
- } catch (NamingException e)
- {
- Utils.log(log, Level.WARNING, "Error registering Naming Service for an existing interface domain with additional interfaces - " + e.getMessage(), Level.FINE, e);
- }
- } else
- {
- log.fine("A Naming Service matching " + naming + " already exists and was not registered.");
- }
- } else
- {
- if (existingNaming instanceof NamingFacade)
- {
- NamingFacade facade = (NamingFacade) existingNaming;
-
- log.fine("Adding Naming Service \"" + naming + "\" to facade \"" + facade + "\"");
- facade.addNamingService(naming);
- } else
- {
- NamingService testNaming = namingServices.get(address, domain);
- if (existingNaming != testNaming)
- {
- log.warning("Naming Service removed for domain \"" + domain + "\" on address \"" + address + "\" is not the same as the one we received with \"get\".");
- }
- NamingFacade facade = new NamingFacade(existingNaming, naming);
-
- log.fine("Adding Naming Service \"" + naming + "\" to facade \"" + facade + "\"");
- namingServices.put(address, domain, facade);
- }
- }
- } else
- {
- log.fine("Registering new Naming Service " + naming);
- namingServices.put(address, domain, naming);
- }
- }
- }
-
-
- private boolean sameNamingDomain(NamingService naming1, NamingService naming2)
- {
- Set<String> domains1 = naming1.getDomains();
- Set<String> domains2 = naming2.getDomains();
- return domains1.equals(domains2) && naming1.getLocalAddress().equals(naming2.getLocalAddress());
- }
- /**
- * Unregisters the Naming Service(s) for the Internet Address and Domain. If null, all Naming
- * Services for address and domain are removed.
- *
- * @param address The Internet Address. A null Internet Address indicates the default Naming Service for the browse domain
- * @param domain The browse domain. A null domain indicates the default Naming Service for the Internet Address/Interface
- * @param naming The Naming Service to remove. If null, all Naming Services for address and domain will be unregistered.
- * @return The Naming Service that was unregistered
- */
- public NamingService unregister(InetAddress address, String domain, NamingService naming)
- {
- domain = (domain == null || domain.length() == 0 ? NULL_DOMAIN : domain);
- if (naming == null)
- {
- naming = namingServices.remove(address, domain);
- if (naming != null)
- {
- try
- {
- naming.close();
- } catch (Exception e)
- {
- Utils.log(log, Level.INFO, e.getMessage(), Level.FINE, e);
- }
- }
-
- return naming;
- } else
- {
- NamingService existingNaming = namingServices.get(address, domain);
- if (existingNaming != null && existingNaming.isAssociatedToDomain((domain == null ? NULL_DOMAIN : domain)))
- {
- if (existingNaming instanceof NamingFacade)
- {
- NamingFacade facade = (NamingFacade) existingNaming;
- int numberOfNamingServices;
- int oldNumberOfNamingServices = facade.numberOfNamingServices();
- if (facade.removeNamingService(naming) && oldNumberOfNamingServices != (numberOfNamingServices = facade.numberOfNamingServices()))
- {
- switch (numberOfNamingServices)
- {
- case 0 :
- // No Naming Services Remain, Remove Facade and all Naming Services for Domain
- namingServices.remove(address, domain);
- break;
- case 1 :
- // Only 1 Naming Service Remains, Replace Facade with the Naming Service
- namingServices.put(address, domain, facade.getNamingService(0));
- break;
- }
-
- return naming;
- }
- } else
- {
- naming = namingServices.remove(address, domain);
- if (naming != null)
- {
- try
- {
- naming.close();
- } catch (Exception e)
- {
- Utils.log(log, Level.INFO, e.getMessage(), Level.FINE, e);
- }
- }
-
- return naming;
- }
- }
- }
-
- return null;
- }
-
-
- /**
- * Creates and returns a Naming Service bound to the specified local Internet Address and remote Naming Service Internet Addresses.
- *
- * @param namingServiceType The Type of Naming Service to create.
- * @param localAddress The local Internet Address to bind too
- * @param namingServerAddresses An optional list of Naming Server Socket Addressed (Internet Address & Port). If empty or null, the NICs default Name Servers are used.
- * @return A Naming Service bound to the specified Internet Address and remote Naming Services.
- * @throws NamingException Thrown if the Naming Service could not be created for any reason.
- */
- /*NamingService newNamingService(NAMING_TYPE namingServiceType, InetAddress localAddress, Set<InetSocketAddress> namingServerAddresses)
- throws NamingException
- {
- NamingService naming = newNamingService(namingServiceType);
- naming.setLocalAddress(localAddress);
- naming.addServerAddresses(namingServerAddresses);
- return naming;
- }*/
-
- /**
- * Creates and returns a new Naming Service bound and associated with the specified local Internet Address, Domain and remote Naming Service Internet Addresses.
- * Naming Services are cached and re-used by local Internet Address and Domain, via Naming.associateDomain and registerNamingService.
- *
- * @param domain The name of the domain that the Naming Service will service.
- * @param localAddress The local Internet Address to bind too
- * @param namingServerAddresses An optional list of Naming Server Socket Addressed (Internet Address & Port). If empty or null, the NICs default Name Servers are used.
- * @return A Naming Service bound to the specified Internet Address, Domain and remote Naming Services.
- * @throws NamingException Thrown if the Naming Service could not be created for any reason.
- */
- @SuppressWarnings("resource")
- public NamingService newNamingService(String domain, InetAddress localAddress, Set<InetSocketAddress> namingServerAddresses)
- throws NamingException
- {
- domain = (domain == null || domain.length() == 0 ? NULL_DOMAIN : domain);
-
- NamingService naming = null;
- if (isLocalLinkDomain(domain))
- {
- naming = newNamingService(NAMING_TYPE.MULTICAST_DNS);
- } else
- {
- naming = newNamingService(NAMING_TYPE.UNICAST_DNS);
- }
-
- naming.setLocalAddress(localAddress);
- naming.addServerAddresses(namingServerAddresses);
- naming.associateToDomain(domain);
- return naming;
- }
-
-
- public static boolean isLocalLinkDomain(String domain)
- {
- boolean multicast = false;
-
- for (String test : LOCALLINK_DNS_DOMAINS)
- {
- multicast = domain.matches("\\.?" + test + "\\.?");
- if (multicast)
- {
- break;
- }
- }
-
- return multicast;
- }
- /**
- * Creates and returns a new, unbound, Naming Service of the type specified.
- *
- * @param multicast Multicast or Unicast.
- * @return
- * @throws NamingException
- */
- private NamingService newNamingService(NAMING_TYPE type)
- throws NamingException
- {
- try
- {
- String className = findClassName(type);
- if (className != null)
- {
- @SuppressWarnings("unchecked")
- Class<NamingService> clazz = (Class<NamingService>) Class.forName(className);
- NamingService naming = clazz.newInstance();
- return naming;
- } else
- {
- throw new NamingException(type + " name resolution is not supported.");
- }
- } catch (NamingException ne)
- {
- throw ne;
- } catch (Exception e)
- {
- NamingException ne = new NamingException("Error loading module for " + type + " name resolution " + (e.getMessage() != null ? " - " + e.getMessage() : "."));
- ne.setStackTrace(e.getStackTrace());
- throw ne;
- }
- }
- String findClassName(NAMING_TYPE type)
- throws IOException
- {
- String className = null;
-
- if (props == null)
- {
- URL url = NamingServices.class.getResource(FACTORY_PROPERTIES);
- if (url == null)
- {
- url = NamingServices.class.getResource("/" + FACTORY_PROPERTIES);
- if (url == null)
- {
- url = ClassLoader.getSystemResource(FACTORY_PROPERTIES);
- if (url == null)
- {
- url = ClassLoader.getSystemResource("/" + FACTORY_PROPERTIES);
- }
- }
- }
-
- if (url != null)
- {
- InputStream in = url.openStream();
- Properties p = new Properties();
- p.load(in);
- props = p;
-
- try
- {
- in.close();
- } catch (Exception e)
- {
- // ignore, no one cares if you can close the stream, your done with it!
- }
- }
- }
-
- if (props != null)
- {
- className = (String) props.get(type.toString());
- }
-
- return className;
- }
- public void unregisterDomain(InetAddress address, String domain)
- {
- domain = (domain == null || domain.length() == 0 ? NULL_DOMAIN : domain);
- ArrayList<NamingService> list = new ArrayList<NamingService>(namingServices.values());
- for (NamingService naming : list)
- {
- try
- {
- naming.unassociateToDomain(domain);
- } catch (NamingException e)
- {
- Utils.log(log, Level.INFO, e.getMessage(), Level.FINE, e);
- }
- }
- }
- public void unregisterAll(InetAddress address)
- {
- Map<InetAddress, Set<String>> keyMap = namingServices.keyMap();
- if (keyMap != null)
- {
- ArrayList<String> domains = new ArrayList<String>(keyMap.get(address));
- for (String domain : domains)
- {
- unregisterDomain(address, domain);
- }
- }
- }
- public Collection<NamingService> getNamingServices()
- {
- return Collections.unmodifiableCollection(namingServices.values());
- }
- public String determineParentDomain(String domainName)
- throws NamingException
- {
- String largestMatchingDomain = null;
- Set<String> domains = getDomains();
-
- for (String domain : domains)
- {
- if (largestMatchingDomain == null)
- {
- if (domainName.endsWith(domain))
- {
- largestMatchingDomain = domain;
- }
- } else
- {
- if (largestMatchingDomain.length() < domain.length())
- {
- if (domainName.endsWith(domain))
- {
- largestMatchingDomain = domain;
- }
- }
- }
- }
-
- if (largestMatchingDomain == null)
- {
- try
- {
- StringBuilder builder = new StringBuilder(domainName.length());
- Name name = Name.fromString(domainName);
- int labels = name.labels();
- if (labels > 1)
- {
- for (int index = 1; index < labels; index++)
- {
- String labelString = name.getLabelString(index);
- // Skip Service Name Type components
- if (labelString.charAt(0) == '_')
- {
- continue;
- } else
- {
- builder.append(labelString);
- if (index < labels - 1)
- {
- builder.append(".");
- }
- }
- }
-
- builder.append(".");
-
- return builder.toString();
- } else
- {
- return null;
- }
- } catch (Exception e)
- {
- NamingException ne = new NamingException(e.getMessage());
- ne.setStackTrace(e.getStackTrace());
- throw ne;
- }
- } else
- {
- return largestMatchingDomain;
- }
- }
- public boolean contains(InetAddress localAddress, String domain, Set<InetSocketAddress> serverAddresses)
- {
- NamingService naming = getNamingService(localAddress, domain);
- Set<InetSocketAddress> testServerAddresses = naming.getServerAddresses();
- return testServerAddresses.containsAll(serverAddresses);
- }
- }