|
ActiveMQ example source code file (ServiceInfo.java)
The ActiveMQ ServiceInfo.java source code/** * Copyright 2003-2005 Arthur van Hoff, Rick Blair * * 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.activemq.jmdns; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.util.Enumeration; import java.util.Hashtable; import java.util.TimerTask; import java.util.Vector; import java.util.logging.Logger; /** * JmDNS service information. * * @version %I%, %G% * @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer */ public class ServiceInfo implements DNSListener { private static Logger logger = Logger.getLogger(ServiceInfo.class.toString()); public final static byte[] NO_VALUE = new byte[0]; JmDNS dns; // State machine /** * The state of this service info. * This is used only for services announced by JmDNS. * <p/> * For proper handling of concurrency, this variable must be * changed only using methods advanceState(), revertState() and cancel(). */ private DNSState state = DNSState.PROBING_1; /** * Task associated to this service info. * Possible tasks are JmDNS.Prober, JmDNS.Announcer, JmDNS.Responder, * JmDNS.Canceler. */ TimerTask task; String type; private String name; String server; int port; int weight; int priority; byte text[]; Hashtable props; InetAddress addr; /** * Construct a service description for registrating with JmDNS. * * @param type fully qualified service type name, such as <code>_http._tcp.local.. * @param name unqualified service instance name, such as <code>foobar * @param port the local port on which the service runs * @param text string describing the service */ public ServiceInfo(String type, String name, int port, String text) { this(type, name, port, 0, 0, text); } /** * Construct a service description for registrating with JmDNS. * * @param type fully qualified service type name, such as <code>_http._tcp.local.. * @param name unqualified service instance name, such as <code>foobar * @param port the local port on which the service runs * @param weight weight of the service * @param priority priority of the service * @param text string describing the service */ public ServiceInfo(String type, String name, int port, int weight, int priority, String text) { this(type, name, port, weight, priority, (byte[]) null); try { ByteArrayOutputStream out = new ByteArrayOutputStream(text.length()); writeUTF(out, text); this.text = out.toByteArray(); } catch (IOException e) { throw new RuntimeException("unexpected exception: " + e); } } /** * Construct a service description for registrating with JmDNS. The properties hashtable must * map property names to either Strings or byte arrays describing the property values. * * @param type fully qualified service type name, such as <code>_http._tcp.local.. * @param name unqualified service instance name, such as <code>foobar * @param port the local port on which the service runs * @param weight weight of the service * @param priority priority of the service * @param props properties describing the service */ public ServiceInfo(String type, String name, int port, int weight, int priority, Hashtable props) { this(type, name, port, weight, priority, new byte[0]); if (props != null) { try { ByteArrayOutputStream out = new ByteArrayOutputStream(256); for (Enumeration e = props.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); Object val = props.get(key); ByteArrayOutputStream out2 = new ByteArrayOutputStream(100); writeUTF(out2, key); if (val instanceof String) { out2.write('='); writeUTF(out2, (String) val); } else { if (val instanceof byte[]) { out2.write('='); byte[] bval = (byte[]) val; out2.write(bval, 0, bval.length); } else { if (val != NO_VALUE) { throw new IllegalArgumentException("invalid property value: " + val); } } } byte data[] = out2.toByteArray(); out.write(data.length); out.write(data, 0, data.length); } this.text = out.toByteArray(); } catch (IOException e) { throw new RuntimeException("unexpected exception: " + e); } } } /** * Construct a service description for registrating with JmDNS. * * @param type fully qualified service type name, such as <code>_http._tcp.local.. * @param name unqualified service instance name, such as <code>foobar * @param port the local port on which the service runs * @param weight weight of the service * @param priority priority of the service * @param text bytes describing the service */ public ServiceInfo(String type, String name, int port, int weight, int priority, byte text[]) { this.type = type; this.name = name; this.port = port; this.weight = weight; this.priority = priority; this.text = text; } /** * Construct a service record during service discovery. */ ServiceInfo(String type, String name) { if (!type.endsWith(".")) { throw new IllegalArgumentException("type must be fully qualified DNS name ending in '.': " + type); } this.type = type; this.name = name; } /** * During recovery we need to duplicate service info to reregister them */ ServiceInfo(ServiceInfo info) { if (info != null) { this.type = info.type; this.name = info.name; this.port = info.port; this.weight = info.weight; this.priority = info.priority; this.text = info.text; } } /** * Fully qualified service type name, such as <code>_http._tcp.local. . */ public String getType() { return type; } /** * Unqualified service instance name, such as <code>foobar . */ public String getName() { return name; } /** * Sets the service instance name. * * @param name unqualified service instance name, such as <code>foobar */ void setName(String name) { this.name = name; } /** * Fully qualified service name, such as <code>foobar._http._tcp.local. . */ public String getQualifiedName() { return name + "." + type; } /** * Get the name of the server. */ public String getServer() { return server; } /** * Get the host address of the service (ie X.X.X.X). */ public String getHostAddress() { return (addr != null ? addr.getHostAddress() : ""); } public InetAddress getAddress() { return addr; } /** * Get the InetAddress of the service. */ public InetAddress getInetAddress() { return addr; } /** * Get the port for the service. */ public int getPort() { return port; } /** * Get the priority of the service. */ public int getPriority() { return priority; } /** * Get the weight of the service. */ public int getWeight() { return weight; } /** * Get the text for the serivce as raw bytes. */ public byte[] getTextBytes() { return text; } /** * Get the text for the service. This will interpret the text bytes * as a UTF8 encoded string. Will return null if the bytes are not * a valid UTF8 encoded string. */ public String getTextString() { if ((text == null) || (text.length == 0) || ((text.length == 1) && (text[0] == 0))) { return null; } return readUTF(text, 0, text.length); } /** * Get the URL for this service. An http URL is created by * combining the address, port, and path properties. */ public String getURL() { return getURL("http"); } /** * Get the URL for this service. An URL is created by * combining the protocol, address, port, and path properties. */ public String getURL(String protocol) { String url = protocol + "://" + getAddress() + ":" + getPort(); String path = getPropertyString("path"); if (path != null) { if (path.indexOf("://") >= 0) { url = path; } else { url += path.startsWith("/") ? path : "/" + path; } } return url; } /** * Get a property of the service. This involves decoding the * text bytes into a property list. Returns null if the property * is not found or the text data could not be decoded correctly. */ public synchronized byte[] getPropertyBytes(String name) { return (byte[]) getProperties().get(name); } /** * Get a property of the service. This involves decoding the * text bytes into a property list. Returns null if the property * is not found, the text data could not be decoded correctly, or * the resulting bytes are not a valid UTF8 string. */ public synchronized String getPropertyString(String name) { byte data[] = (byte[]) getProperties().get(name); if (data == null) { return null; } if (data == NO_VALUE) { return "true"; } return readUTF(data, 0, data.length); } /** * Enumeration of the property names. */ public Enumeration getPropertyNames() { Hashtable props = getProperties(); return (props != null) ? props.keys() : new Vector().elements(); } /** * Write a UTF string with a length to a stream. */ void writeUTF(OutputStream out, String str) throws IOException { for (int i = 0, len = str.length(); i < len; i++) { int c = str.charAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { out.write(c); } else { if (c > 0x07FF) { out.write(0xE0 | ((c >> 12) & 0x0F)); out.write(0x80 | ((c >> 6) & 0x3F)); out.write(0x80 | ((c >> 0) & 0x3F)); } else { out.write(0xC0 | ((c >> 6) & 0x1F)); out.write(0x80 | ((c >> 0) & 0x3F)); } } } } /** * Read data bytes as a UTF stream. */ String readUTF(byte data[], int off, int len) { StringBuffer buf = new StringBuffer(); for (int end = off + len; off < end;) { int ch = data[off++] & 0xFF; switch (ch >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx break; case 12: case 13: if (off >= len) { return null; } // 110x xxxx 10xx xxxx ch = ((ch & 0x1F) << 6) | (data[off++] & 0x3F); break; case 14: if (off + 2 >= len) { return null; } // 1110 xxxx 10xx xxxx 10xx xxxx ch = ((ch & 0x0f) << 12) | ((data[off++] & 0x3F) << 6) | (data[off++] & 0x3F); break; default: if (off + 1 >= len) { return null; } // 10xx xxxx, 1111 xxxx ch = ((ch & 0x3F) << 4) | (data[off++] & 0x0f); break; } buf.append((char) ch); } return buf.toString(); } synchronized Hashtable getProperties() { if ((props == null) && (text != null)) { Hashtable props = new Hashtable(); int off = 0; while (off < text.length) { // length of the next key value pair int len = text[off++] & 0xFF; if ((len == 0) || (off + len > text.length)) { props.clear(); break; } // look for the '=' int i = 0; for (; (i < len) && (text[off + i] != '='); i++) { ; } // get the property name String name = readUTF(text, off, i); if (name == null) { props.clear(); break; } if (i == len) { props.put(name, NO_VALUE); } else { byte value[] = new byte[len - ++i]; System.arraycopy(text, off + i, value, 0, len - i); props.put(name, value); off += len; } } this.props = props; } return props; } // REMIND: Oops, this shouldn't be public! /** * JmDNS callback to update a DNS record. */ public void updateRecord(JmDNS jmdns, long now, DNSRecord rec) { if ((rec != null) && !rec.isExpired(now)) { switch (rec.type) { case DNSConstants.TYPE_A: // IPv4 case DNSConstants.TYPE_AAAA: // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested if (rec.name.equals(server)) { addr = ((DNSRecord.Address) rec).getAddress(); } break; case DNSConstants.TYPE_SRV: if (rec.name.equals(getQualifiedName())) { DNSRecord.Service srv = (DNSRecord.Service) rec; server = srv.server; port = srv.port; weight = srv.weight; priority = srv.priority; addr = null; // changed to use getCache() instead - jeffs // updateRecord(jmdns, now, (DNSRecord)jmdns.cache.get(server, TYPE_A, CLASS_IN)); updateRecord(jmdns, now, (DNSRecord) jmdns.getCache().get(server, DNSConstants.TYPE_A, DNSConstants.CLASS_IN)); } break; case DNSConstants.TYPE_TXT: if (rec.name.equals(getQualifiedName())) { DNSRecord.Text txt = (DNSRecord.Text) rec; text = txt.text; } break; } // Future Design Pattern // This is done, to notify the wait loop in method // JmDNS.getServiceInfo(type, name, timeout); if (hasData() && dns != null) { dns.handleServiceResolved(this); dns = null; } synchronized (this) { notifyAll(); } } } /** * Returns true if the service info is filled with data. */ boolean hasData() { return server != null && addr != null && text != null; } // State machine /** * Sets the state and notifies all objects that wait on the ServiceInfo. */ synchronized void advanceState() { state = state.advance(); notifyAll(); } /** * Sets the state and notifies all objects that wait on the ServiceInfo. */ synchronized void revertState() { state = state.revert(); notifyAll(); } /** * Sets the state and notifies all objects that wait on the ServiceInfo. */ synchronized void cancel() { state = DNSState.CANCELED; notifyAll(); } /** * Returns the current state of this info. */ DNSState getState() { return state; } public int hashCode() { return getQualifiedName().hashCode(); } public boolean equals(Object obj) { return (obj instanceof ServiceInfo) && getQualifiedName().equals(((ServiceInfo) obj).getQualifiedName()); } public String getNiceTextString() { StringBuffer buf = new StringBuffer(); for (int i = 0, len = text.length; i < len; i++) { if (i >= 20) { buf.append("..."); break; } int ch = text[i] & 0xFF; if ((ch < ' ') || (ch > 127)) { buf.append("\\0"); buf.append(Integer.toString(ch, 8)); } else { buf.append((char) ch); } } return buf.toString(); } public String toString() { StringBuffer buf = new StringBuffer(); buf.append("service["); buf.append(getQualifiedName()); buf.append(','); buf.append(getAddress()); buf.append(':'); buf.append(port); buf.append(','); buf.append(getNiceTextString()); buf.append(']'); return buf.toString(); } } Other ActiveMQ examples (source code examples)Here is a short list of links related to this ActiveMQ ServiceInfo.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.