Package net.jini.jeri.http

Source Code of net.jini.jeri.http.Constraints$Distilled

/*
* 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 net.jini.jeri.http;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
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.ConnectionAbsoluteTime;
import net.jini.core.constraint.ConnectionRelativeTime;
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.RelativeTimeConstraint;
import net.jini.core.constraint.ServerAuthentication;
import net.jini.core.constraint.ServerMinPrincipal;
import net.jini.io.UnsupportedConstraintException;

/**
* Constraint support for this transport provider.
*
* This code makes some significant simplifying assumptions:
*
* - The transport layer aspects of all constraints supported by this
*   provider are always satisfied by all open connections and
*   requests.
*
* - No combination of individual constraints supported by this
*   provider can contain conflicting constraints.
*
* @author Sun Microsystems, Inc.
**/
class Constraints {

    /**
     * indicates that this provider does not support implementing (or
     * does not understand how to implement) the transport layer
     * aspects of satisfying a given constraint
     **/
    private static final int NO_SUPPORT = 0;

    /**
     * indicates that this provider supports implementing all aspects
     * of satisfying a given constraint
     **/
    private static final int FULL_SUPPORT = 1;

    /**
     * indicates that this provider supports implementing the
     * transport layer aspects of satisfying a given constraint, but
     * at least partial implementation by higher layers is also needed
     * in order to fully satisfy the constraint
     **/
    private static final int PARTIAL_SUPPORT = 2;

    /**
     * maps constraint values that are supported to Boolean indicating
     * whether or not they must be at least partially implemented by
     * higher layers to be fully satisfied
     **/
    private static final Map supportedValues = new HashMap();
    static {
  supportedValues.put(Integrity.NO,    Boolean.TRUE);
  supportedValues.put(Confidentiality.NO,    Boolean.FALSE);
  supportedValues.put(ClientAuthentication.NO,  Boolean.FALSE);
  supportedValues.put(ServerAuthentication.NO,  Boolean.FALSE);
  supportedValues.put(Delegation.NO,    Boolean.FALSE);
    }

    /**
     * maps constraint classes that are supported to Boolean
     * indicating whether or not such constraints must be at least
     * partially implemented by higher layers to be fully satisfied
     **/
    private static final Map supportedClasses = new HashMap();
    static {
  // ConstraintAlternatives is supported but handled specially in code
  supportedClasses.put(ConnectionAbsoluteTime.class,  Boolean.FALSE);
  supportedClasses.put(ConnectionRelativeTime.class,  Boolean.FALSE);
  /*
   * The following classes are (trivially) supported just
   * because ClientAuthentication.YES, ServerAuthentication.YES,
   * and Delegation.YES are not supported.
   */
  supportedClasses.put(ClientMaxPrincipal.class,    Boolean.FALSE);
  supportedClasses.put(ClientMaxPrincipalType.class,  Boolean.FALSE);
  supportedClasses.put(ClientMinPrincipal.class,    Boolean.FALSE);
  supportedClasses.put(ClientMinPrincipalType.class,  Boolean.FALSE);
  supportedClasses.put(ServerMinPrincipal.class,    Boolean.FALSE);
  supportedClasses.put(DelegationAbsoluteTime.class,  Boolean.FALSE);
  supportedClasses.put(DelegationRelativeTime.class,  Boolean.FALSE);
    }

    /**
     * Returns this provider's general support for the given
     * constraint.
     **/
    private static int getSupport(InvocationConstraint c) {
  Boolean support = (Boolean) supportedValues.get(c);
  if (support == null) {
      support = (Boolean) supportedClasses.get(c.getClass());
  }
  return support == null ? NO_SUPPORT :
      support.booleanValue() ? PARTIAL_SUPPORT : FULL_SUPPORT;
    }

    /**
     * Checks that we support at least the transport layer aspects of
     * the given requirements (and throws an
     * UnsupportedConstraintException if not), and returns the
     * requirements that must be at least partially implemented by
     * higher layers and the supported preferences that must be at
     * least partially implemented by higher layers.
     *
     * [If this provider supported constraints whose transport layer
     * aspects were not always satisfied by open connections or
     * requests, then we would need a variant of this method that
     * checks the given constraints against an open connection or
     * request.  If this provider supported constraints that could
     * conflict with each other then (when not checking against an
     * open connection or request) we would need to check for possible
     * conflicts.]
     **/
    static InvocationConstraints check(InvocationConstraints constraints,
               boolean relativeOK)
  throws UnsupportedConstraintException
    {
  return distill(constraints, relativeOK).getUnfulfilledConstraints();
    }

    /**
     * Distills the given constraints to a form more directly usable
     * by this provider.  Throws an UnsupportedConstraintException if
     * we do not support at least the transport layer aspects of the
     * requirements.
     **/
    static Distilled distill(InvocationConstraints constraints,
           boolean relativeOK)
  throws UnsupportedConstraintException
    {
  return new Distilled(constraints, relativeOK);
    }

    private Constraints() { throw new AssertionError(); }

    /**
     * A distillation of constraints to a form more directly usable by
     * this provider.
     **/
    static class Distilled {

  /**
   * true if relative time constraints are allowed (in other
   * words, not for client-side use)
   */
  private final boolean relativeOK;

  private Collection unfulfilledRequirements = null; // lazily created
  private Collection unfulfilledPreferences = null; // lazily created

  private boolean hasConnectDeadline = false;
  private long connectDeadline;

  Distilled(InvocationConstraints constraints, boolean relativeOK)
      throws UnsupportedConstraintException
  {
      this.relativeOK = relativeOK;
      for (Iterator i = constraints.requirements().iterator();
     i.hasNext();)
      {
    addConstraint((InvocationConstraint) i.next(), true);
      }
      for (Iterator i = constraints.preferences().iterator();
     i.hasNext();)
      {
    addConstraint((InvocationConstraint) i.next(), false);
      }
  }

  /**
   * Returns the requirements and supported preferences that
   * must be at least partially implemented by higher layers.
   **/
  InvocationConstraints getUnfulfilledConstraints() {
      if (unfulfilledRequirements == null &&
    unfulfilledPreferences == null)
      {
    return InvocationConstraints.EMPTY;
      } else {
    return new InvocationConstraints(unfulfilledRequirements,
             unfulfilledPreferences);
      }
  }

  /**
   * Returns true if a there is a socket connect deadline.
   **/
  boolean hasConnectDeadline() {
      return hasConnectDeadline;
  }

  /**
   * Returns the absolute time of the socket connect deadline.
   **/
  long getConnectDeadline() {
      assert hasConnectDeadline;
      return connectDeadline;
  }

  /**
   * If "isRequirement" is true, throws an
   * UnsupportedConstraintException if we do not support at
   * least the transport layer aspects of the given constraint.
   *
   * If we do support at least the transport layer aspects of
   * the given constraint, then if appropriate, adds it to the
   * collection of requirements or preferences that must be at
   * least partially implemented by higher layers.
   **/
  private void addConstraint(InvocationConstraint constraint,
           boolean isRequirement)
      throws UnsupportedConstraintException
  {
      if (!(constraint instanceof ConstraintAlternatives)) {
    int support = getSupport(constraint);
    if (support == NO_SUPPORT ||
        (!relativeOK &&
         constraint instanceof RelativeTimeConstraint))
    {
        if (isRequirement) {
      throw new UnsupportedConstraintException(
          "cannot satisfy constraint: " + constraint);
        } else {
      return;
        }
    }
    if (support == PARTIAL_SUPPORT) {
        if (isRequirement) {
      if (unfulfilledRequirements == null) {
          unfulfilledRequirements = new ArrayList();
      }
      unfulfilledRequirements.add(constraint);
        } else {
      if (unfulfilledPreferences == null) {
          unfulfilledPreferences = new ArrayList();
      }
      unfulfilledPreferences.add(constraint);
        }
    }
    if (constraint instanceof ConnectionAbsoluteTime) {
        // REMIND: only bother with this on client side?
        addConnectDeadline(
      ((ConnectionAbsoluteTime) constraint).getTime());
    }
      } else {
    addAlternatives((ConstraintAlternatives) constraint,
        isRequirement);
      }
  }

  /**
   * If "isRequirement" is true, throws an
   * UnsupportedConstraintException if we do not support at
   * least the transport layer aspects of at least one of the
   * constraints in the given alternatives.
   *
   * If we do support at least the transport layer aspects of at
   * least one of the constraints in the given alternatives,
   * then if appropriate, adds a ConstraintAlternatives of the
   * supported alternatives to the collection of requirements or
   * preferences that must be at least partially implemented by
   * higher layers.
   *
   * If all of the supported alternatives need at least partial
   * implementation by higher layers, then adds a
   * ConstraintAlternatives with all of the supported
   * alternatives to the unfulfilled collection or preferences,
   * because higher layers must support at least one of them.
   * But if at least one of the supported alternatives can be
   * fully satisfied by the transport layer, then add nothing to
   * the unfulfilled collection, because it is possible that
   * higher layers need not support any of them (and there is no
   * way to express no constraint).
   *
   * The weakest connect deadline (with no deadline being the
   * the weakest possibility) is chosen among alternatives.
   **/
  private void addAlternatives(ConstraintAlternatives constraint,
             boolean isRequirement)
      throws UnsupportedConstraintException
  {
      Collection alts = constraint.elements();
      boolean supported = false;
      long maxConnectDeadline = Long.MIN_VALUE;
      Collection unfulfilledAlts = null; // lazily created
      boolean forgetUnfulfilled = false;
      for (Iterator i = alts.iterator(); i.hasNext();) {
    InvocationConstraint c = (InvocationConstraint) i.next();

    // nested ConstraintAlternatives not allowed
    int support = getSupport(c);
    if (support == NO_SUPPORT ||
        (!relativeOK && c instanceof RelativeTimeConstraint))
    {
        continue;
    }
    supported = true// we support at least one
    if (!forgetUnfulfilled) {
        if (support == PARTIAL_SUPPORT) {
      if (unfulfilledAlts == null) {
          unfulfilledAlts = new ArrayList();
      }
      unfulfilledAlts.add(c);
        } else {
      assert support == FULL_SUPPORT;
      unfulfilledAlts = null;
      forgetUnfulfilled = true;
        }
    }
    if (c instanceof ConnectionAbsoluteTime) {
        assert support == FULL_SUPPORT; // else more care required
        maxConnectDeadline =
      Math.max(maxConnectDeadline,
         ((ConnectionAbsoluteTime) c).getTime());
    } else {
        maxConnectDeadline = Long.MAX_VALUE;
    }
      }
      if (!supported) {
    if (isRequirement) {
        throw new UnsupportedConstraintException(
      "cannot satisfy constraint: " + constraint);
    } else {
        return; // maxConnectDeadline is bogus in this case
    }
      }
      if (!forgetUnfulfilled && unfulfilledAlts != null) {
    if (isRequirement) {
        if (unfulfilledRequirements == null) {
      unfulfilledRequirements = new ArrayList();
        }
        unfulfilledRequirements.add(
      ConstraintAlternatives.create(unfulfilledAlts));
    } else {
        if (unfulfilledPreferences == null) {
      unfulfilledPreferences = new ArrayList();
        }
        unfulfilledPreferences.add(
      ConstraintAlternatives.create(unfulfilledAlts));
    }
      }
      if (maxConnectDeadline < Long.MAX_VALUE) {
    assert maxConnectDeadline != Long.MIN_VALUE;
    addConnectDeadline(maxConnectDeadline);
      }
  }

  /**
   * Adds the given connect deadline to this object's state.
   * The earliest connect deadline is what gets remembered.
   **/
  private void addConnectDeadline(long deadline) {
      if (!hasConnectDeadline) {
    hasConnectDeadline = true;
    connectDeadline = deadline;
      } else {
    connectDeadline = Math.min(connectDeadline, deadline);
      }
  }
    }
}
TOP

Related Classes of net.jini.jeri.http.Constraints$Distilled

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.