alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

ActiveMQ example source code file (ServiceInfo.java)

This example ActiveMQ source code file (ServiceInfo.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - ActiveMQ tags/keywords

bytearrayoutputstream, enumeration, hashtable, hashtable, inetaddress, io, ioexception, log, logging, net, network, no_value, runtimeexception, serviceinfo, serviceinfo, string, string, stringbuffer, stringbuffer, util

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

 

new blog posts

 

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.