package org.distributeme.core; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import net.anotheria.util.StringUtils; import org.configureme.ConfigurationManager; import org.configureme.annotations.Configure; import org.configureme.annotations.ConfigureMe; import org.configureme.annotations.Set; import org.configureme.annotations.SetAll; import org.distributeme.core.ServiceDescriptor.Protocol; import org.distributeme.core.util.BaseRegistryUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Utilities for communication with the registry over http protocol. * * @author lrosenberg * @version $Id: $Id */ public class RegistryUtil extends BaseRegistryUtil{ /** * Connector for a concrete registry implementation. */ private static RegistryConnector registryConnector = new DistributemeRegistryConnector(); /** * Logger. */ private static Logger log = LoggerFactory.getLogger(RegistryUtil.class); /** * Registry configuration. */ private static final Configurable configuration; static{ configuration = new Configurable(); try{ ConfigurationManager.INSTANCE.configure(configuration); }catch(Exception ignored){ log.error("Error while reading configuration ! ", ignored); } log.info("Initializing registry connector with configuration: "+ configuration); String registryConnectorClazz = configuration.getRegistryConnectorClazz(); if(!StringUtils.isEmpty(registryConnectorClazz)) { try { registryConnector = (RegistryConnector)Class.forName(registryConnectorClazz).newInstance(); registryConnector.setTagableSystemProperties(configuration.getTagableSystemProperties()); registryConnector.setCustomTagProviderClassList(configuration.getCustomTagProviderClassList()); } catch (Exception e) { log.error("Could not initiate registry connector " + registryConnectorClazz, e); } } } /** * Binds a service. * * @param service a {@link org.distributeme.core.ServiceDescriptor} object. * @return true if sucessful, false otherwise. */ public static boolean bind(ServiceDescriptor service){ return registryConnector.bind(service); } /** * Pings a location. This is part of the cluster management. * * @param location location to ping. * @return a {@link java.lang.String} object. */ public static String ping(Location location){ String url = createRegistryOperationUrl(location, "ping", ""); byte data[] = getUrlContent(url, true); if (data == null ) return null; String reply = new String(data, Charset.defaultCharset()); return "ERROR".equals(reply) ? null : reply; } /** * <p>notifyBind.</p> * * @param location a {@link org.distributeme.core.Location} object. * @param descriptor a {@link org.distributeme.core.ServiceDescriptor} object. * @return a boolean. */ public static boolean notifyBind(Location location, ServiceDescriptor descriptor){ return registryConnector.notifyBind(location, descriptor); } /** * <p>notifyUnbind.</p> * * @param location a {@link org.distributeme.core.Location} object. * @param descriptor a {@link org.distributeme.core.ServiceDescriptor} object. * @return a boolean. */ public static boolean notifyUnbind(Location location, ServiceDescriptor descriptor){ return registryConnector.notifyUnbind(location, descriptor); } /** * Unbinds a service. * * @param service a {@link org.distributeme.core.ServiceDescriptor} object. * @return a boolean. */ public static boolean unbind(ServiceDescriptor service){ return registryConnector.unbind(service); } /** * Resolves a service descriptor at a specified location. * * @param toResolve a {@link org.distributeme.core.ServiceDescriptor} object. * @param loc a {@link org.distributeme.core.Location} object. * @return a {@link org.distributeme.core.ServiceDescriptor} object. */ public static ServiceDescriptor resolve(ServiceDescriptor toResolve, Location loc){ return registryConnector.resolve(toResolve, loc); } /** * Helper methods that creates the url for given operation and parameters. * * @param operation the operation which should be executed. For example BIND,UNBIND etc. * @param parameters the parameters to the operation. * @return a {@link java.lang.String} object. */ public static String createRegistryOperationUrl(String operation, String parameters){ return getRegistryBaseUrl()+operation+"?"+parameters; } /** * Helper methods that creates the url for given operation and parameters. * * @param loc location of the registry. * @param operation the operation which should be executed. For example BIND,UNBIND etc. * @param parameters the parameters to the operation. * @return a {@link java.lang.String} object. */ public static String createRegistryOperationUrl(Location loc, String operation, String parameters){ return getRegistryBaseUrl(loc)+operation+"?"+parameters; } /** * Returns the list of services as xml-string. * * @return a {@link java.lang.String} object. */ public static String getXMLServiceList(){ return getXMLServiceList(registryLocation); } /** * Returns the list of services from a specified location. * * @param loc a {@link org.distributeme.core.Location} object. * @return a {@link java.lang.String} object. */ @SuppressFBWarnings("DM_DEFAULT_ENCODING") public static String getXMLServiceList(Location loc){ String url = getRegistryBaseUrl(loc)+"list"; byte data[] = getUrlContent(url); if (data == null ) return null; String reply = new String(data); return reply; } /** * Resolves a service request. * * @param toResolve parameter descriptor which contains the serviceid to be resolved. * @return resolved service descriptor which points to a concrete service instance or null if no service has been found. */ public static ServiceDescriptor resolve(ServiceDescriptor toResolve){ return resolve(toResolve, registryLocation); } /** * Get registry url for internal use. * * @return a {@link java.lang.String} object. */ protected static String getRegistryBaseUrl(){ return getRegistryBaseUrl(DistributemeRegistryConnector.APP); } /** * Get registry url for internal use. * * @param location registry location. * @return a {@link java.lang.String} object. */ protected static String getRegistryBaseUrl(Location location){ return getRegistryBaseUrl(DistributemeRegistryConnector.APP, location.getHost(), location.getPort(), location.getProtocol(), location.getContext()); } /** * <p>createLocalServiceDescription.</p> * * @param protocol a {@link org.distributeme.core.ServiceDescriptor.Protocol} object. * @param serviceId a {@link java.lang.String} object. * @param instanceId a {@link java.lang.String} object. * @param port a int. * @return a {@link org.distributeme.core.ServiceDescriptor} object. */ public static ServiceDescriptor createLocalServiceDescription(Protocol protocol, String serviceId, String instanceId, int port){ return new ServiceDescriptor(protocol, serviceId, instanceId, getHostName(), port); } private static String getHostName(){ try{ InetAddress localhost = InetAddress.getLocalHost(); String host = localhost.getHostAddress(); HashMap<String, String> mappings = configuration.getMappings(); String mappedHost = mappings.get(host); return mappedHost == null ? host : mappedHost; }catch(UnknownHostException e){ return "unknown"; } } /** * Inner configuration holder class. * @author lrosenberg */ @ConfigureMe(name="distributeme",watch=true) public static class Configurable{ /** * IP Mappings. */ private volatile HashMap<String, String> mappings = new HashMap<String, String>(); /** * List of custom Tag provider classes */ private volatile List<String> customTagProviderClassList = new ArrayList<>(); @Configure private String registryConnectorClazz = DistributemeRegistryConnector.class.getName(); @Configure private String systemPropertiesToTags; private Map<String, String> tagableSystemProperties = new HashMap<>(); @Set("customTagProviderClasses") public void setCustomTagProviderClasses(final String customTagProviderClasses) { customTagProviderClassList = new ArrayList<>(); String[] fullQualifiedClassName = StringUtils.tokenize(customTagProviderClasses, ','); for (String pair : fullQualifiedClassName) { customTagProviderClassList.add(pair.trim()); } } public List<String> getCustomTagProviderClassList() { return customTagProviderClassList; } @Set("registrationIpMapping") public void setRegistrationIpMapping(String registrationIpMapping) { log.info("registrationIpMappingSet: "+registrationIpMapping); try{ HashMap<String, String> newMappings = new HashMap<String, String>(); String[] pairs = StringUtils.tokenize(registrationIpMapping, ','); for (String p : pairs){ String ips[] = StringUtils.tokenize(p, ':'); newMappings.put(ips[0], ips[1]); } mappings = newMappings; }catch(Exception e){ log.warn("setRegistrationIpMapping("+registrationIpMapping+"), e"); } } @SetAll public void debug(String key, String value){ log.debug("Config "+key+"="+value); } public HashMap<String, String> getMappings(){ return mappings; } @Override public String toString() { return "Configurable{" + "mappings=" + mappings + ", customTagProviderClassList=" + customTagProviderClassList + ", registryConnectorClazz='" + registryConnectorClazz + '\'' + ", systemPropertiesToTags='" + systemPropertiesToTags + '\'' + ", tagableSystemProperties=" + tagableSystemProperties + '}'; } public String getRegistryConnectorClazz() { return registryConnectorClazz; } public void setRegistryConnectorClazz(String registryConnectorClazz) { this.registryConnectorClazz = registryConnectorClazz; } public String getSystemPropertiesToTags() { return systemPropertiesToTags; } public void setSystemPropertiesToTags(String systemPropertiesToTags) { this.systemPropertiesToTags = systemPropertiesToTags; String[] properties = StringUtils.tokenize(systemPropertiesToTags, ','); Map<String, String> newTagableSystemProperties = new HashMap(); for(String property: properties) { property = property.trim(); String value = System.getProperty(property); if(value != null) { newTagableSystemProperties.put(property, value); } } tagableSystemProperties = newTagableSystemProperties; } public Map<String, String> getTagableSystemProperties() { return tagableSystemProperties; } } public static final String describeRegistry(){ return registryConnector.describeRegistry(); } }