/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.services.binding; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; /** * Metadata about a {@link ServiceBinding} that management tools can use. Does * not represent the runtime binding information, but rather the metadata * used to create the binding. * * @author Brian Stansberry */ public class ServiceBindingMetadata implements Comparable<ServiceBindingMetadata> { /** * Checks if <code>serviceName</code> can be converted into an * ObjectName; if it can, converts it and returns its canonical form. * * @param serviceName the service name * @return the canonicalized form, or <code>serviceName</code> if it * cannot be converted into an ObjectName. */ public static String canonicalizeServiceName(String serviceName) { // If the serviceName looks like an object name, canonicalize it try { ObjectName oname = new ObjectName(serviceName); return oname.getCanonicalName(); } catch (MalformedObjectNameException e) { return serviceName; } } // ----------------------------------------------------------------- Fields /** * The name of the service to which the binding applies. */ private String serviceName; /** * The name of the binding. A null or empty name implies the default * binding for a service. */ private String bindingName; /** The virtual host name. This is the interface name used to construct the bindAddress value. A null value implies bind on any interface. */ private String hostName; /** The port the service should listen on. A 0 value implies an anonymous port. */ private int port; /** The ServiceBindingValueSource implementation class */ private String serviceBindingValueSourceClassName; /** The ServiceBindingValueSource */ private ServiceBindingValueSource serviceBindingValueSource; /** An aribtrary object used to configure the behavior of the ServiceBindingValueSource. An example would be an XML Element. */ private Object serviceBindingValueSourceConfig; /** * Whether runtime @{link ServiceBinding}s created from this metadata * can alter the port value based on the server on which the binding * is running. */ private boolean fixedPort; /** * Whether runtime @{link ServiceBinding}s created from this metadata * can alter the hostName value based on the server on which the binding * is running. */ private Boolean fixedHostName; /** Description of the binding that can be displayed by management tools */ private String description; // ------------------------------------------------------------ Constructors /** * Create a new ServiceBindingMetadata. */ public ServiceBindingMetadata() {} /** * Create a new ServiceBindingMetadata with given service name. * * @param serviceName the name of the service to which this binding applies. * Cannot be <code>null</code> * * @throws IllegalArgumentException if {@code serviceName} is <code>null</code> */ public ServiceBindingMetadata(String serviceName) { this(serviceName, null, null, 0, false, false); } /** * Create a new ServiceBindingMetadata with given service and binding names. * * @param serviceName the name of the service to which this binding applies. * Cannot be <code>null</code> * @param bindingName qualifier identifying which particular binding within * the service this is. May be <code>null</code> * * @throws IllegalArgumentException if {@code serviceName} is <code>null</code> */ public ServiceBindingMetadata(String serviceName, String bindingName) { this(serviceName, bindingName, null, 0, false, false); } /** * Create a new ServiceBindingMetadata with given property values and a * non-fixed {@link #isFixedPort() port}. The * {@link #isFixedHostName() hostname is fixed} if the provided {@code hostName} * is not <code>null</code>. * * @param serviceName the name of the service to which this binding applies. * Cannot be <code>null</code> * @param bindingName qualifier identifying which particular binding within * the service this is. May be <code>null</code> * @param hostName the host name or string notation IP address of the * interface to bind to * @param port the port to bind to * * @throws IllegalArgumentException if {@code serviceName} is <code>null</code> */ public ServiceBindingMetadata(String serviceName, String bindingName, String hostName, int port) { this(serviceName, bindingName, hostName, port, false, hostName != null); } /** * Create a new ServiceBindingMetadata with given property values. * * @param serviceName the name of the service to which this binding applies. * Cannot be <code>null</code> * @param bindingName qualifier identifying which particular binding within * the service this is. May be <code>null</code> * @param hostName the host name or string notation IP address of the * interface to bind to * @param port the port to bind to * @param fixedPort whether runtime @{link ServiceBinding}s created from this * metadata can alter the port value based on the server * on which the binding is running. * @param fixedHostName whether runtime @{link ServiceBinding}s created from * this metadata can alter the hostName value based on * the server on which the binding is running. * * @throws IllegalArgumentException if {@code serviceName} is <code>null</code> */ public ServiceBindingMetadata(String serviceName, String bindingName, String hostName, int port, boolean fixedPort, boolean fixedHostName) { setServiceName(serviceName); setBindingName(bindingName); setHostName(hostName); setPort(port); setFixedPort(fixedPort); setFixedHostName(fixedHostName); } /** * Create a new ServiceBindingMetadata from a runtime ServiceBinding. The * resulting object has a fixed port and host name. * * @param binding the binding. Cannot be <code>null</code> */ public ServiceBindingMetadata(ServiceBinding binding) { this(binding.getServiceName(), binding.getBindingName(), binding.getHostName(), binding.getPort(), true, true); setServiceBindingValueSource(binding.getServiceBindingValueSource()); if (this.serviceBindingValueSourceClassName == null) { setServiceBindingValueSourceClassName(binding.getServiceBindingValueSourceClassName()); } setServiceBindingValueSourceConfig(binding.getServiceBindingValueSourceConfig()); } /** * Copy constructor. * * @param binding the metadata to copy. Cannot be <code>null</code> */ public ServiceBindingMetadata(ServiceBindingMetadata binding) { this(binding.getServiceName(), binding.getBindingName(), binding.getHostName(), binding.getPort(), binding.isFixedHostName(), binding.isFixedPort()); setServiceBindingValueSource(binding.getServiceBindingValueSource()); if (this.serviceBindingValueSourceClassName == null) { setServiceBindingValueSourceClassName(binding.getServiceBindingValueSourceClassName()); } setServiceBindingValueSourceConfig(binding.getServiceBindingValueSourceConfig()); } // ------------------------------------------------------------ Properties /** * Gets the name of the service to which this binding applies. * * @return the name. */ public String getServiceName() { return serviceName; } /** * Sets the name of the service to which this binding applies. * * @param serviceName the name. Cannot be <code>null</code>. * * @throws IllegalArgumentException if {@code serviceName} is <code>null</code> */ public void setServiceName(String serviceName) { if (serviceName == null) { throw new IllegalArgumentException("serviceName is null"); } this.serviceName = canonicalizeServiceName(serviceName); } /** * Gets a qualifier identifying which particular binding within * {@link #getServiceName() the service} this is. * * @return the name, or <code>null</code> if this is an unnamed default binding * for the service. */ public String getBindingName() { return this.bindingName; } /** * Sets a qualifier identifying which particular binding within * {@link #getServiceName() the service} this is. * * @param bindingName the name, or <code>null</code> if this is an unnamed * default binding for the service. */ public void setBindingName(String bindingName) { this.bindingName = bindingName; } /** * Gets the fully qualified binding name. * * @return the {@link #getServiceName() serviceName}:{@link #getBindingName() bindingName} or * just the service name if the binding name is <code>null</code>. * * @throws IllegalStateException if {@link #getServiceName() serviceName} is <code>null</code> */ public String getFullyQualifiedName() { if (this.serviceName == null) { throw new IllegalStateException("Must set serviceName"); } else if (this.bindingName == null) { return this.serviceName; } else { StringBuilder sb = new StringBuilder(this.serviceName); if (this.bindingName != null) { sb.append(':'); sb.append(this.bindingName); } return sb.toString(); } } /** * Gets the host name or string notation IP address to use for the binding. * * @return the hostname or address. May be <code>null</code> */ public String getHostName() { return hostName; } /** * Sets the host name or string notation IP address to use for the binding. * * @param hostName the hostname or address. May be <code>null</code> */ public void setHostName(String hostName) { this.hostName = hostName; // Assume that setting a host name means it's meant to be fixed if (this.fixedHostName == null) { setFixedHostName(hostName == null); } } public int getPort() { return port; } /** * Sets the port to use for the binding. * * @param port the port */ public void setPort(int port) { this.port = port; } /** * Gets a description of the binding suitable for display by management tools. * * @return the description, or <code>null</code> if there isn't one */ public String getDescription() { return description; } /** * Sets a description of the binding suitable for display by management tools. * * @param description the description; may be <code>null</code> */ public void setDescription(String description) { this.description = description; } /** * Gets the object that can return this ServiceBinding's values in formats * usable by consumers. If unset (the norm), {@link ServiceBindingManager} will use * reasonable defaults based on the format requested by the consumer. * * @return the ServiceBindingValueSource; may be <code>null</code> */ public synchronized ServiceBindingValueSource getServiceBindingValueSource() { return this.serviceBindingValueSource; } /** * Sets the object that can return this ServiceBinding's values in formats * usable by consumers. * * @param serviceBindingValueSource the ServiceBindingValueSource; may be <code>null</code> */ public void setServiceBindingValueSource(ServiceBindingValueSource serviceBindingValueSource) { this.serviceBindingValueSource = serviceBindingValueSource; if (serviceBindingValueSource != null) { setServiceBindingValueSourceClassName(serviceBindingValueSource.getClass().getName()); } } /** * Gets the fully qualified class name of the {@link #getServiceBindingValueSource() serviceBindingValueSource}. * * @return the binding value source class, or <code>null</code> */ public String getServiceBindingValueSourceClassName() { return serviceBindingValueSourceClassName; } /** * Sets the fully qualified class name of the {@link #getServiceBindingValueSource() serviceBindingValueSource}. * * @param serviceBindingValueSourceClassName the binding value source class, or <code>null</code> */ public void setServiceBindingValueSourceClassName(String serviceBindingValueSourceClassName) { this.serviceBindingValueSourceClassName = serviceBindingValueSourceClassName; } /** * Gets the configuration object the {@link #getServiceBindingValueSource() serviceBindingValueSource} * should use. * * @return the configuration object, or <code>null</code> */ public Object getServiceBindingValueSourceConfig() { return serviceBindingValueSourceConfig; } /** * Sets the configuration object the {@link #getServiceBindingValueSource() serviceBindingValueSource} * should use. * * @param serviceBindingValueSourceConfig the configuration object, or <code>null</code> */ public void setServiceBindingValueSourceConfig(Object serviceBindingValueSourceConfig) { this.serviceBindingValueSourceConfig = serviceBindingValueSourceConfig; } /** * Gets whether runtime @{link ServiceBinding}s created from this metadata * can alter the port value based on the server on which the binding * is running. * * @return <code>true</code> if the {@link #getPort()} value from this * object must be respected; <code>false</code> if it can be * altered. */ public boolean isFixedPort() { return fixedPort; } /** * Sets whether runtime @{link ServiceBinding}s created from this metadata * can alter the port value based on the server on which the binding * is running. * * param fixedPort <code>true</code> if the {@link #getPort()} value from this * object must be respected; <code>false</code> if it can be * altered. */ public void setFixedPort(boolean fixedPort) { this.fixedPort = fixedPort; } /** * Gets whether runtime @{link ServiceBinding}s created from this metadata * can alter the hostName value based on the server on which the binding * is running. * * @return <code>true</code> if the {@link #getHostName()} value from this * object must be respected; <code>false</code> if it can be * altered. */ public boolean isFixedHostName() { return (this.fixedHostName == null ? this.hostName != null : this.fixedHostName.booleanValue()); } /** * Sets whether runtime @{link ServiceBinding}s created from this metadata * can alter the hostName value based on the server on which the binding * is running. * * param fixedHostName <code>true</code> if the {@link #getHostName()} value * from this object must be respected; <code>false</code> * if it can be altered. */ public void setFixedHostName(boolean fixedHostName) { this.fixedHostName = Boolean.valueOf(fixedHostName); } // ------------------------------------------------------------- Comparable public int compareTo(ServiceBindingMetadata other) { return getFullyQualifiedName().compareTo(other.getFullyQualifiedName()); } // -------------------------------------------------------------- Overrides /** * Equality is based on our serviceName and our bindingName. */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj instanceof ServiceBindingMetadata) { ServiceBindingMetadata other = (ServiceBindingMetadata) obj; return (this.serviceName != null && this.serviceName.equals(other.serviceName) && safeEquals(this.bindingName, other.bindingName)); } return false; } /** * Hashcode is based on our serviceName and our bindingName. */ @Override public int hashCode() { int result = 19; result += 29 * this.serviceName.hashCode(); result += 29 * (this.bindingName == null ? 0 : this.bindingName.hashCode()); return result; } /** * Create string representation of the service descriptor * * @return String containing service descriptor properties */ public String toString() { StringBuffer sBuf = new StringBuffer("ServiceBindingMetadata [serviceName="); sBuf.append(this.serviceName); sBuf.append(";bindingName="); sBuf.append(this.getBindingName()); sBuf.append(";hostName="); String host = getHostName(); if (hostName == null) { host = "<ANY>"; } sBuf.append(host); sBuf.append(";port="); sBuf.append(this.getPort()); sBuf.append("]"); return sBuf.toString(); } // ---------------------------------------------------------------- Private private boolean safeEquals(Object a, Object b) { return (a == b || (a != null && a.equals(b))); } }