All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.addc.commons.slp.ServiceURL Maven / Gradle / Ivy

Go to download

The addc-slp library supplies client classes for registering objects with a Service Location Protocol Daemon and for looking theses objects up later.

There is a newer version: 2.6
Show newest version
package com.addc.commons.slp;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.addc.commons.ObjectEquals;
import com.addc.commons.slp.configuration.SLPConfig;

/**
 * Implementation of the SLP ServiceURL class defined in RFC 2614.
 */
public class ServiceURL {
    private final List authBlocks= new ArrayList<>();
    private final SLPConfig config;
    private String url;
    private int lifetime;
    private ServiceType type;
    private String host;
    private String transport;
    private int port;
    private String path;

    /**
     * Create a new ServiceURL
     * 
     * @param config
     *            The configuration to use
     * @param url
     *            The service URL
     * @param lifetime
     *            The lifetime in seconds
     * @throws ServiceLocationException
     *             If fails.
     */
    public ServiceURL(SLPConfig config, String url, int lifetime) throws ServiceLocationException {
        this.url= url;
        this.lifetime= lifetime;
        this.config= config;

        try {
            parse();
        } catch (Exception ex) {
            throw new ServiceLocationException("Malformed service url [" + url + "]. ", ex, SLPConstants.PARSE_ERROR);
        }
    }

    /**
     * Create a new ServiceURL for reading from data input stream
     * 
     * @param config
     *            The configuration to use
     */
    public ServiceURL(SLPConfig config) {
        this.config= config;
    }

    /**
     * Sign the URL
     * 
     * @throws ServiceLocationException
     *             If signing fails.
     */
    public void sign() throws ServiceLocationException {
        if (config.isSecurityEnabled()) {
            try {
                String[] spis= StringUtils.split(config.getSPI(), ",");
                authBlocks.clear();
                for (String spIndex : spis) {
                    int timestamp= ServiceLocationManager.getTimestamp();
                    timestamp+= lifetime;
                    byte[] data= getAuthData(spIndex, timestamp);
                    authBlocks.add(new AuthenticationBlock(config, 2, spIndex, timestamp, data));
                }
            } catch (IOException e) {
                throw new ServiceLocationException("Could not sign URL", e, SLPConstants.AUTHENTICATION_FAILED);
            }
        }
    }

    /**
     * Verify the URL.
     * 
     * @return true if valid
     */
    public boolean verify() {
        if (config.isSecurityEnabled()) {
            for (AuthenticationBlock authBlock : authBlocks) {
                try {
                    byte[] data= getAuthData(authBlock.getSPI(), authBlock.getTimestamp());
                    if (!authBlock.verify(data)) {
                        return false;
                    }
                } catch (@SuppressWarnings("unused") IOException | ServiceLocationException e) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Get the Service Type.
     * 
     * @return the Service Type.
     */
    public ServiceType getServiceType() {
        return type;
    }

    /**
     * Get the transport.
     * 
     * @return the transport.
     */
    public String getTransport() {
        return transport;
    }

    /**
     * Get the host.
     * 
     * @return the host.
     */
    public String getHost() {
        return host;
    }

    /**
     * Get the port.
     * 
     * @return the port.
     */
    public int getPort() {
        return port;
    }

    /**
     * Get the URL path.
     * 
     * @return the URL path.
     */
    public String getURLPath() {
        return path;
    }

    /**
     * Get the lifetime.
     * 
     * @return the lifetime.
     */
    public int getLifetime() {
        return lifetime;
    }

    /**
     * Get the URL.
     * 
     * @return the URL.
     */
    public String getURL() {
        return url;
    }

    /**
     * Read the Service URL from a Data input stream
     * 
     * @param dataIn
     *            The DataInputStream to read from
     * @throws IOException
     *             If there is an IO error
     */
    public void readExternal(DataInputStream dataIn) throws IOException {
        dataIn.readByte();
        lifetime= dataIn.readShort();
        url= dataIn.readUTF();

        int numBlks= dataIn.readByte();
        for (int i= 0; i < numBlks; i++) {
            authBlocks.add(AuthenticationBlock.readBlock(config, dataIn));
        }

        parse();
    }

    /**
     * Write the Service URL to a data output stream
     * 
     * @param out
     *            The DataOutStream to write to
     * @throws IOException
     *             If there is an IO error
     */
    public void writeExternal(DataOutputStream out) throws IOException {
        out.writeByte(0);
        out.writeShort(lifetime);

        out.writeUTF(this.toString());
        out.writeByte(authBlocks.size());

        for (AuthenticationBlock authBlock : authBlocks) {
            authBlock.writeBlock(out);
        }
    }

    /**
     * calculate the size
     * 
     * @return the size
     */
    public int calcSize() {
        int size= 6 + this.toString().length();
        for (AuthenticationBlock authBlock : authBlocks) {
            size+= authBlock.calcSize();
        }
        return size;
    }

    /**
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime= 31;
        int result= 1;
        result= prime * result + ((host == null) ? 0 : host.hashCode());
        result= prime * result + ((path == null) ? 0 : path.hashCode());
        result= prime * result + port;
        result= prime * result + ((transport == null) ? 0 : transport.hashCode());
        result= prime * result + ((type == null) ? 0 : type.hashCode());
        return result;
    }

    /**
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof ServiceURL)) {
            return false;
        }
        ServiceURL other= (ServiceURL) obj;
        return (ObjectEquals.areFieldsEqual(host, other.host) && ObjectEquals.areFieldsEqual(path, other.path)
                && (port == other.port) && ObjectEquals.areFieldsEqual(transport, other.transport)
                && ObjectEquals.areFieldsEqual(type, other.type));
    }

    @Override
    public String toString() {
        StringBuilder sb= new StringBuilder();
        sb.append(type).append(":/").append(transport).append('/').append(host);
        if (port != SLPConstants.NO_PORT) {
            sb.append(':').append(port);
        }
        sb.append(path);
        return sb.toString();
    }

    private void parse() {
        int transportSlash1= url.indexOf(":/");

        type= new ServiceType(url.substring(0, transportSlash1++));

        int transportSlash2= url.indexOf("/", transportSlash1 + 1);
        transport= url.substring(transportSlash1, transportSlash2 - 1);

        int hostEnd= -1;
        if ("".equals(transport)) {
            hostEnd= url.indexOf(':', transportSlash2 + 1);
        }

        int pathStart;
        if (hostEnd == -1) {
            port= SLPConstants.NO_PORT;
            pathStart= url.indexOf('/', transportSlash2 + 1);
            hostEnd= pathStart;
        } else {
            pathStart= url.indexOf('/', hostEnd + 1);
            if (pathStart == -1) {
                port= Integer.parseInt(url.substring(hostEnd + 1));
            } else {
                port= Integer.parseInt(url.substring(hostEnd + 1, pathStart));
            }
        }

        if (hostEnd == -1) {
            host= url.substring(transportSlash2 + 1);
        } else {
            host= url.substring(transportSlash2 + 1, hostEnd);
        }

        if (pathStart == -1) {
            path= "";
        } else {
            path= url.substring(pathStart);
        }
    }

    private byte[] getAuthData(String spi, int timestamp) throws IOException {
        ByteArrayOutputStream bos= new ByteArrayOutputStream();
        DataOutputStream dos= new DataOutputStream(bos);

        dos.writeUTF(spi);
        dos.writeUTF(this.toString());
        dos.writeInt(timestamp);
        return bos.toByteArray();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy