Package org.knopflerfish.framework.permissions

Source Code of org.knopflerfish.framework.permissions.ConditionalPermissionInfoImpl

/*
* Copyright (c) 2008-2010, KNOPFLERFISH project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
*   copyright notice, this list of conditions and the following
*   disclaimer in the documentation and/or other materials
*   provided with the distribution.
*
* - Neither the name of the KNOPFLERFISH project nor the names of its
*   contributors may be used to endorse or promote products derived
*   from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.knopflerfish.framework.permissions;

import java.lang.reflect.*;
import java.security.*;
import java.util.*;

import org.osgi.framework.Bundle;
import org.osgi.service.condpermadmin.*;
import org.osgi.service.permissionadmin.PermissionInfo;

import org.knopflerfish.framework.Debug;
import org.knopflerfish.framework.FrameworkContext;


/**
* A binding of a set of Conditions to a set of Permissions.
*
*/
class ConditionalPermissionInfoImpl implements ConditionalPermissionInfo
{
  private ConditionalPermissionInfoStorage cpis;

  final private ConditionInfo [] conditionInfos;
  final private PermissionInfo [] permissionInfos;
  final private String access;
  final private FrameworkContext framework;
  final private Debug debug;

  private String name;
  private PermissionCollection permissions;


  /**
   */
  ConditionalPermissionInfoImpl(ConditionalPermissionInfoStorage cpis, String name,
                                ConditionInfo [] conds, PermissionInfo [] perms,
                                String access, FrameworkContext fw) {
    this.cpis = cpis;
    this.name = name;
    conditionInfos = conds;
    permissionInfos = perms;
    this.access = access;
    framework = fw;
    debug = fw.debug;
    permissions = null;
  }


  /**
   */
  ConditionalPermissionInfoImpl(ConditionalPermissionInfoStorage cpis,
                                String encoded, FrameworkContext fw) {
    this.cpis = cpis;
    framework = fw;
    debug = fw.debug;
    try {
      char [] eca = encoded.toCharArray();
      int pos = PermUtil.skipWhite(eca, 0);
      if ((eca[pos] == 'A' || eca[pos] == 'a') &&
          (eca[pos+1] == 'L' || eca[pos+1] == 'l') &&
          (eca[pos+2] == 'L' || eca[pos+2] == 'l') &&
          (eca[pos+3] == 'O' || eca[pos+3] == 'o') &&
          (eca[pos+4] == 'W' || eca[pos+4] == 'w') && eca[pos+5] == ' ') {
        pos += 6;
        access = ConditionalPermissionInfo.ALLOW;
      } else if ((eca[pos] == 'D' || eca[pos] == 'd') &&
                 (eca[pos+1] == 'E' || eca[pos+1] == 'e') &&
                 (eca[pos+2] == 'N' || eca[pos+2] == 'n') &&
                 (eca[pos+3] == 'Y' || eca[pos+3] == 'y') && eca[pos+4] == ' ') {
        pos += 5;
        access = ConditionalPermissionInfo.DENY;
      } else {
        throw new IllegalArgumentException("Access must be allow or deny");
      }
      pos = PermUtil.skipWhite(eca, pos);
      if (eca[pos++] != '{') {
        throw new IllegalArgumentException("Missing open brace");
      }
      ArrayList cal = new ArrayList();
      ArrayList pal = new ArrayList();
      boolean seenPermInfo = false;
      while (true) {
        pos = PermUtil.skipWhite(eca, pos);
        char c = eca[pos];
        char ec;
        if (!seenPermInfo && c == '[') {
          ec = ']';
        } else if (c == '(') {
          ec = ')';
          seenPermInfo = true;
        } else if (c == '}') {
          pos++;
          break;
        } else {
          throw new IllegalArgumentException("Unexpected char '" + c + "' at pos " + pos);
        }
        int start_pos = pos++;
        do {
          c = eca[pos];
          if (c == '"') {
            pos = PermUtil.unquote(eca, pos, null);
          } else {
            pos++;
          }
        } while(c != ec);
        String info = new String(eca, start_pos, pos - start_pos);
        if (c == ']') {
          cal.add(new ConditionInfo(info));
        } else {
          pal.add(new PermissionInfo(info));
        }
      }
      if (!seenPermInfo) {
        throw new IllegalArgumentException("Permissions must contain atleast one element");
      }
      pos = PermUtil.endOfString(eca, pos, eca.length);
      if (pos != -1) {
        StringBuffer buf = new StringBuffer();
        pos = PermUtil.unquote(eca, pos, buf);
        name = buf.toString();
        if ((pos = PermUtil.endOfString(eca, pos, eca.length)) != -1) {
          throw new IllegalArgumentException("Unexpected characters at end of string: " +
                                             new String(eca, pos, eca.length - pos));
        }
      } else {
        name = null;
      }
      conditionInfos = (ConditionInfo [])cal.toArray(new ConditionInfo [cal.size()]);
      permissionInfos = (PermissionInfo [])pal.toArray(new PermissionInfo [pal.size()]);
    } catch (ArrayIndexOutOfBoundsException e) {
      throw new IllegalArgumentException("Unexpected end of string");
    }
  }

  // Interface ConditionalPermissionInfo

  /**
   * Returns the Condition Infos for the Conditions that must be satisfied to
   * enable the Permissions.
   *
   * @return The Condition Infos for the Conditions in this Conditional
   *         Permission Info.
   */
  public ConditionInfo[] getConditionInfos() {
    return conditionInfos;
  }


  /**
   * Returns the Permission Infos for the Permission in this Conditional
   * Permission Info.
   *
   * @return The Permission Infos for the Permission in this Conditional
   *         Permission Info.
   */
  public PermissionInfo[] getPermissionInfos() {
    return permissionInfos;
  }


  /**
   * Removes this Conditional Permission Info from the Conditional Permission
   * Admin.
   *
   * @throws SecurityException If the caller does not have
   *         <code>AllPermission</code>.
   */
  public void delete() {
    if (cpis == null) {
      throw new UnsupportedOperationException("Not in use");
    }
    cpis.remove(this);
  }


  /**
   * Returns the name of this Conditional Permission Info.
   *
   * @return The name of this Conditional Permission Info.
   */
  public String getName() {
    return name;
  }


  public String getAccessDecision() {
    return access;
  }


  public String getEncoded() {
    StringBuffer res = new StringBuffer(access);
    res.append(" { ");
    if (conditionInfos != null) {
      for (int i = 0; i < conditionInfos.length; i++) {
        res.append(conditionInfos[i].getEncoded());
        res.append(' ');
      }
    }
    if (permissionInfos != null) {
      for (int i = 0; i < permissionInfos.length; i++) {
        res.append(permissionInfos[i].getEncoded());
        res.append(' ');
      }
    }
    res.append('}');
    if (name != null) {
      res.append(' ');
      PermUtil.quote(name, res);
    }
    return res.toString();
  }


  /**
   * Returns a string representation of this object.
   *
   */
  public String toString() {
    return getEncoded();
  }


  /**
   *
   */
  public final boolean equals(Object obj) {
    if (obj == null) {
      return false;
    }
    if (obj == this) {
      return true;
    }
    ConditionalPermissionInfo cpi = (ConditionalPermissionInfo)obj;
    if (name == null ? cpi.getName() != null : !name.equals(cpi.getName())) {
      return false;
    }
    // NYI, we should allow permuted arrays, also affects hashCode.
    if (!Arrays.equals(permissionInfos, cpi.getPermissionInfos())) {
      return false;
    }
    if (!Arrays.equals(conditionInfos, cpi.getConditionInfos())) {
      return false;
    }
    return access == cpi.getAccessDecision();
  }

  /**
   *
   */
  public final int hashCode() {
    if (name != null) {
      return name.hashCode();
    }
    int res = conditionInfos != null && conditionInfos.length > 0
      ? conditionInfos[0].hashCode()
      : 0;
    return res + permissionInfos[0].hashCode();
  }

  //
  // Package methods
  //

  static final Class[] argClasses = new Class[] {Bundle.class, ConditionInfo.class};

  /**
   *
   */
  ConditionalPermission getConditionalPermission(Bundle bundle) {
    String me = "ConditionalPermissionInfoImpl.getConditionalPermission: ";

    ArrayList conds = new ArrayList(conditionInfos.length);
    for (int i = 0; i < conditionInfos.length; i++) {
      Class clazz;
      Condition c;
      try {
        clazz = Class.forName(conditionInfos[i].getType(),
                              true, framework.getClassLoader(null));
        Constructor cons = null;
        Method method = null;
        try {
          method = clazz.getMethod("getCondition", argClasses);
          if ((method.getModifiers() & Modifier.STATIC) == 0) {
            method = null;
          }
        } catch (NoSuchMethodException ignore) { }
        if (method != null) {
          if (debug.permissions) {
            debug.println(me + "Invoke, " + method + " for bundle " + bundle);
          }
          c = (Condition) method.invoke(null, new Object [] {bundle, conditionInfos[i]});
        } else {
          try {
            cons = clazz.getConstructor(argClasses);
          } catch (NoSuchMethodException ignore) { }
          if (cons != null) {
            if (debug.permissions) {
              debug.println(me + "Construct, " + cons + " for bundle " + bundle);
            }
            c = (Condition) cons.newInstance(new Object [] {bundle, conditionInfos[i]});
          } else {
            debug.println("NYI! Log faulty ConditionInfo object!?");
            continue;
          }
        }
        if (!c.isMutable()) {
          if (!c.isPostponed() /* || debug.tck401compat */ ) {
            if (c.isSatisfied()) {
              if (debug.permissions) {
                debug.println(me + "Immutable condition ok, continue");
              }
              continue;
            } else {
              if (debug.permissions) {
                debug.println(me + "Immutable condition NOT ok, abort");
              }
              return null;
            }
          }
        }
        conds.add(c);
      } catch (Throwable t) {
        debug.printStackTrace("NYI! Log failed Condition creation", t);
        return null;
      }
    }
    return new ConditionalPermission((Condition [])conds.toArray(new Condition[conds.size()]),
                                     getPermissions(), access, this);
  }


  /**
   *
   */
  PermissionCollection getPermissions() {
    if (permissions == null) {
      permissions = new PermissionInfoPermissions(framework, null, permissionInfos);
    }
    return permissions;
  }


  /**
   * Set storage for this Conditional Permission Info.
   *
   */
  void setPermissionInfoStorage(ConditionalPermissionInfoStorage storage) {
    cpis = storage;
  }


  /**
   * Set the name of this Conditional Permission Info.
   *
   */
  void setName(String newName) {
    name = newName;
  }

}
TOP

Related Classes of org.knopflerfish.framework.permissions.ConditionalPermissionInfoImpl

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.