Package com.sun.jini.discovery.internal

Source Code of com.sun.jini.discovery.internal.Plaintext

/*
* 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 com.sun.jini.discovery.internal;

import com.sun.jini.discovery.DatagramBufferFactory;
import com.sun.jini.discovery.DiscoveryProtocolException;
import com.sun.jini.discovery.MulticastAnnouncement;
import com.sun.jini.discovery.MulticastRequest;
import com.sun.jini.discovery.UnicastResponse;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.UTFDataFormatException;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CoderResult;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import net.jini.core.constraint.ClientAuthentication;
import net.jini.core.constraint.ClientMaxPrincipal;
import net.jini.core.constraint.ClientMaxPrincipalType;
import net.jini.core.constraint.ClientMinPrincipal;
import net.jini.core.constraint.ClientMinPrincipalType;
import net.jini.core.constraint.Confidentiality;
import net.jini.core.constraint.ConstraintAlternatives;
import net.jini.core.constraint.Delegation;
import net.jini.core.constraint.DelegationAbsoluteTime;
import net.jini.core.constraint.DelegationRelativeTime;
import net.jini.core.constraint.Integrity;
import net.jini.core.constraint.InvocationConstraint;
import net.jini.core.constraint.InvocationConstraints;
import net.jini.core.constraint.ServerAuthentication;
import net.jini.core.constraint.ServerMinPrincipal;
import net.jini.core.lookup.ServiceID;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.io.MarshalledInstance;
import net.jini.io.UnsupportedConstraintException;

/**
* Provides utility methods for plaintext data operations.
*/
public class Plaintext {

    private static final int MAX_USHORT = 0xFFFF;
    private static final int SHORT_LEN = 2;
    private static final int SERVICE_ID_LEN = 16;

    private static final Charset utf = Charset.forName("UTF-8");
    private static final Set supportedConstraints = new HashSet();
    static {
  supportedConstraints.add(Integrity.NO);
  supportedConstraints.add(Confidentiality.NO);
  supportedConstraints.add(ClientAuthentication.NO);
  supportedConstraints.add(ServerAuthentication.NO);
  supportedConstraints.add(Delegation.NO);
  supportedConstraints.add(ClientMaxPrincipal.class);
  supportedConstraints.add(ClientMaxPrincipalType.class);
  supportedConstraints.add(ClientMinPrincipal.class);
  supportedConstraints.add(ClientMinPrincipalType.class);
  supportedConstraints.add(ServerMinPrincipal.class);
  supportedConstraints.add(DelegationAbsoluteTime.class);
  supportedConstraints.add(DelegationRelativeTime.class);
    }

    /* Uninstantiable */
    private Plaintext() {
    }

    /**
     * Returns the given integer value as an unsigned short, throwing an
     * IllegalArgumentException if the value is negative or too large.
     */
    public static short intToUshort(int i) {
  if (i < 0 || i > MAX_USHORT) {
      throw new IllegalArgumentException("invalid value: " + i);
  }
  return (short) i;
    }

    /**
     * Returns an integer with the unsigned value of the given short.
     */
    public static int ushortToInt(short s) {
  return s & MAX_USHORT;
    }

    /**
     * Returns a byte array containing the UTF encoding of the given string.
     */
    public static byte[] toUtf(String s) throws UTFDataFormatException {
  try {
      ByteArrayOutputStream bout = new ByteArrayOutputStream(s.length());
      DataOutput dout = new DataOutputStream(bout);
      dout.writeUTF(s);
      return bout.toByteArray();
  } catch (UTFDataFormatException e) {
      throw e;
  } catch (IOException e) {
      throw new AssertionError(e);
  }
    }

    /**
     * Writes the given string to the provided buffer in UTF format, starting
     * at the buffer's current position and not exceeding its limit.  If the
     * encoding of the given string exceeds the buffer's limit, then a
     * BufferOverflowException is thrown and the position of the buffer is left
     * unchanged from its initial value.
     */
    public static void putUtf(ByteBuffer buf, String s)
  throws UTFDataFormatException
    {
  ByteBuffer dup = buf.duplicate();
  dup.putShort((short) 0);
  int start = dup.position();
  CoderResult cr =
      utf.newEncoder().encode(CharBuffer.wrap(s), dup, true);
  if (cr.isUnderflow()) {
      buf.putShort(intToUshort(dup.position() - start));
      buf.position(dup.position());
  } else if (cr.isOverflow()) {
      throw new BufferOverflowException();
  } else {
      throw new UTFDataFormatException(cr.toString());
  }
    }

    /**
     * Returns string read from the given buffer in UTF format , starting at
     * the buffer's current position and not exceeding its limit.  If the
     * string's encoding extends past the buffer's limit, then a
     * BufferUnderflowException is thrown and the position of the buffer is
     * left unchanged from its initial value.
     */
    public static String getUtf(ByteBuffer buf) throws UTFDataFormatException {
  ByteBuffer dup = buf.duplicate();
  int len = ushortToInt(dup.getShort());
  if (len > dup.remaining()) {
      throw new BufferUnderflowException();
  }
  dup.limit(dup.position() + len);
  try {
      String s = utf.newDecoder().decode(dup).toString();
      buf.position(dup.position());
      return s;
  } catch (CharacterCodingException e) {
      throw (UTFDataFormatException)
    new UTFDataFormatException().initCause(e);
  }
    }

    /**
     * Returns normally if the given constraints can be satisfied by a
     * plaintext-based format/protocol (such as net.jini.discovery.plaintext,
     * or version 1 of the discovery protocols); otherwise, throws an
     * UnsupportedConstraintException .  Null constraints are considered
     * equivalent to empty constraints.
     */
    public static void checkConstraints(InvocationConstraints constraints)
  throws UnsupportedConstraintException
    {
  if (constraints == null) {
      return;
  }
  for (Iterator i = constraints.requirements().iterator(); i.hasNext(); )
  {
      InvocationConstraint c = (InvocationConstraint) i.next();
      if (!supported(c)) {
    throw new UnsupportedConstraintException(
            "unsupported constraint: " + c);
      }
  }
    }

    /**
     * Encodes multicast request according to the net.jini.discovery.plaintext
     * format.
     */
    public static void encodeMulticastRequest(MulticastRequest request,
                DatagramBufferFactory bufs)
  throws IOException
    {
  try {
      LinkedList groups = new LinkedList();
      groups.addAll(Arrays.asList(request.getGroups()));
      do {
    ByteBuffer buf = bufs.newBuffer();

    // write client host
    putUtf(buf, request.getHost());

    // write client port
    buf.putShort(intToUshort(request.getPort()));

    // write first lookup group
    int ngroups = 0;
    int ngroupsPos = buf.position();
    buf.putShort((short) 0);
    if (!groups.isEmpty()) {
        putUtf(buf, (String) groups.removeFirst());
        ngroups++;
    }

    // calculate size of known service ID list
    ServiceID[] ids = request.getServiceIDs();
    int maxIds = Math.min(ids.length, MAX_USHORT);
    int maxIdsLen = SHORT_LEN + maxIds * SERVICE_ID_LEN;

    // write additional lookup groups, as space allows
    if (buf.remaining() > maxIdsLen && !groups.isEmpty()) {
        int slim = buf.limit();
        buf.limit(slim - maxIdsLen);
        try {
      do {
          putUtf(buf, (String) groups.getFirst());
          groups.removeFirst();
          ngroups++;
      } while (!groups.isEmpty() && ngroups < MAX_USHORT);
        } catch (BufferOverflowException e) {
        }
        buf.limit(slim);
    }
    buf.putShort(ngroupsPos, intToUshort(ngroups));

    // write known service IDs
    int nids = Math.min(
        maxIds,
        (buf.remaining() - SHORT_LEN) / SERVICE_ID_LEN);
    buf.putShort(intToUshort(nids));
    for (int i = 0; i < nids; i++) {
        ServiceID id = ids[i];
        buf.putLong(id.getMostSignificantBits());
        buf.putLong(id.getLeastSignificantBits());
    }
      } while (!groups.isEmpty());

  } catch (RuntimeException e) {
      throw new DiscoveryProtocolException(null, e);
  }
    }

    /**
     * Decodes multicast request according to the net.jini.discovery.plaintext
     * format.
     */
    public static MulticastRequest decodeMulticastRequest(ByteBuffer buf)
  throws IOException
    {
  try {
      // read client host
      String host = getUtf(buf);

      // read client port
      int port = ushortToInt(buf.getShort());

      // read lookup groups
      String[] groups = new String[ushortToInt(buf.getShort())];
      for (int i = 0; i < groups.length; i++) {
    groups[i] = getUtf(buf);
      }

      // read known service IDs
      ServiceID[] ids = new ServiceID[ushortToInt(buf.getShort())];
      for (int i = 0; i < ids.length; i++) {
    long hi = buf.getLong();
    long lo = buf.getLong();
    ids[i] = new ServiceID(hi, lo);
      }

      return new MulticastRequest(host, port, groups, ids);

  } catch (RuntimeException e) {
      throw new DiscoveryProtocolException(null, e);
  }
    }

    /**
     * Encodes multicast announcement according to the
     * net.jini.discovery.plaintext format.
     */
    public static void encodeMulticastAnnouncement(
              MulticastAnnouncement announcement,
              DatagramBufferFactory bufs)
  throws IOException
    {
  try {
      LinkedList groups = new LinkedList();
      groups.addAll(Arrays.asList(announcement.getGroups()));
      do {
    ByteBuffer buf = bufs.newBuffer();
    int slim = buf.limit();
    buf.limit(slim - SERVICE_ID_LEN);

    // write sequence number
    buf.putLong(announcement.getSequenceNumber());

    // write LUS host
    putUtf(buf, announcement.getHost());

    // write LUS port
    buf.putShort(intToUshort(announcement.getPort()));

    // write LUS member groups, as space allows
    int ngroups = 0;
    int ngroupsPos = buf.position();
    buf.putShort((short) 0);
    try {
        while (!groups.isEmpty() && ngroups < MAX_USHORT) {
      putUtf(buf, (String) groups.getFirst());
      groups.removeFirst();
      ngroups++;
        }
    } catch (BufferOverflowException e) {
        if (ngroups == 0) {
      throw e;
        }
    }
    buf.putShort(ngroupsPos, intToUshort(ngroups));

    // write LUS service ID
    ServiceID id = announcement.getServiceID();
    buf.limit(slim);
    buf.putLong(id.getMostSignificantBits());
    buf.putLong(id.getLeastSignificantBits());

      } while (!groups.isEmpty());

  } catch (RuntimeException e) {
      throw new DiscoveryProtocolException(null, e);
  }
    }

    /**
     * Decodes multicast announcement according to the
     * net.jini.discovery.plaintext format.
     */
    public static MulticastAnnouncement decodeMulticastAnnouncement(
                  ByteBuffer buf)
  throws IOException
    {
  try {
      // read sequence number
      long seq = buf.getLong();

      // read LUS host
      String host = getUtf(buf);

      // read LUS port
      int port = ushortToInt(buf.getShort());

      // read LUS member groups
      String[] groups = new String[ushortToInt(buf.getShort())];
      for (int i = 0; i < groups.length; i++) {
    groups[i] = getUtf(buf);
      }

      // read LUS service ID
      long idhi = buf.getLong();
      long idlo = buf.getLong();

      return new MulticastAnnouncement(
    seq, host, port, groups, new ServiceID(idhi, idlo));

  } catch (RuntimeException e) {
      throw new DiscoveryProtocolException(null, e);
  }
    }

    /**
     * Writes unicast response according to the net.jini.discovery.plaintext
     * format.
     */
    public static void writeUnicastResponse(OutputStream out,
              UnicastResponse response,
              Collection context)
  throws IOException
    {
  try {
      DataOutput dout = new DataOutputStream(out);

      // write LUS host
      dout.writeUTF(response.getHost());

      // write LUS port
      dout.writeShort(intToUshort(response.getPort()));

      // write LUS member groups
      String[] groups = response.getGroups();
      dout.writeInt(groups.length);
      for (int i = 0; i < groups.length; i++) {
    dout.writeUTF(groups[i]);
      }

      // write LUS proxy
      new ObjectOutputStream(out).writeObject(
    new MarshalledInstance(response.getRegistrar(), context));
  } catch (RuntimeException e) {
      throw new DiscoveryProtocolException(null, e);
  }
    }

    /**
     * Reads unicast response according to the net.jini.discovery.plaintext
     * format.
     */
    public static UnicastResponse readUnicastResponse(
              InputStream in,
              ClassLoader defaultLoader,
              boolean verifyCodebaseIntegrity,
              ClassLoader verifierLoader,
              Collection context)
  throws IOException, ClassNotFoundException
    {
  try {
      DataInput din = new DataInputStream(in);

      // read LUS host
      String host = din.readUTF();

      // read LUS port
      int port = din.readUnsignedShort();

      // read LUS member groups
      String[] groups = new String[din.readInt()];
      for (int i = 0; i < groups.length; i++) {
    groups[i] = din.readUTF();
      }

      // read LUS proxy
      MarshalledInstance mi =
    (MarshalledInstance) new ObjectInputStream(in).readObject();
      ServiceRegistrar reg = (ServiceRegistrar) mi.get(
    defaultLoader,
    verifyCodebaseIntegrity,
    verifierLoader,
    context);

      return new UnicastResponse(host, port, groups, reg);

  } catch (RuntimeException e) {
      throw new DiscoveryProtocolException(null, e);
  }
    }

    private static boolean supported(InvocationConstraint ic) {
  if (ic instanceof ConstraintAlternatives) {
      ConstraintAlternatives ca = (ConstraintAlternatives) ic;
      for (Iterator i = ca.elements().iterator(); i.hasNext(); ) {
    if (supported((InvocationConstraint) i.next())) {
        return true;
    }
      }
      return false;
  }
  return supportedConstraints.contains(ic) ||
         supportedConstraints.contains(ic.getClass());
    }
}
TOP

Related Classes of com.sun.jini.discovery.internal.Plaintext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.