Package org.apache.clerezza.rdf.core.access.security

Source Code of org.apache.clerezza.rdf.core.access.security.TcAccessController

/*
* 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.clerezza.rdf.core.access.security;

import java.security.AccessControlException;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.locks.Lock;
import org.apache.clerezza.rdf.core.BNode;
import org.apache.clerezza.rdf.core.LiteralFactory;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.Resource;
import org.apache.clerezza.rdf.core.Triple;
import org.apache.clerezza.rdf.core.TypedLiteral;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.LockableMGraph;
import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
import org.apache.clerezza.rdf.core.access.TcManager;
import org.apache.clerezza.rdf.core.impl.TripleImpl;
import org.apache.clerezza.utils.security.PermissionParser;

/**
* Controls the permissions needed to access a triple collection provided by
* <code>TcManager</code>.
*
* Clients with a ConfigureTcAcessPermission can set the permissions required to
* access a TripleCollection. These permissions are stored persistently in an
* MGraph named urn:x-localinstance:/graph-access.graph
*
* @author reto
*/
public class TcAccessController {

  private final TcManager tcManager;
  private final UriRef permissionGraphName = new UriRef("urn:x-localinstance:/graph-access.graph");
  //we can't rely on ontology plugin in rdf core
  private String ontologyNamespace = "http://clerezza.apache.org/2010/07/10/graphpermssions#";
  private final UriRef readPermissionListProperty = new UriRef(ontologyNamespace + "readPermissionList");
  private final UriRef readWritePermissionListProperty = new UriRef(ontologyNamespace + "readWritePermissionList");
  /**
   * The first item in the subject RDF list.
   */
  public static final UriRef first = new UriRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#first");
  /**
   * The rest of the subject RDF list after the first item.
   */
  public static final UriRef rest = new UriRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest");
  public static final UriRef rdfNil = new UriRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
  private final Map<UriRef, Collection<Permission>> readPermissionCache =
      Collections.synchronizedMap(new HashMap<UriRef, Collection<Permission>>());
  private final Map<UriRef, Collection<Permission>> readWritePermissionCache =
      Collections.synchronizedMap(new HashMap<UriRef, Collection<Permission>>());

  /**
   *
   * @param tcManager the tcManager used to locate urn:x-localinstance:/graph-access.graph
   */
  public TcAccessController(TcManager tcManager) {
    this.tcManager = tcManager;
  }

  public void checkReadPermission(UriRef tripleCollectionUri) {
    if (tripleCollectionUri.equals(permissionGraphName)) {
      //This is world readable, as this prevents as from doingf things as
      //priviledged during verfification
      return;
    }
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
      //will AllPermissions the rest is obsolete
      try {
        AccessController.checkPermission(new AllPermission());
      } catch (AccessControlException e) {
        Collection<Permission> perms = getRequiredReadPermissions(tripleCollectionUri);
        if (perms.size() > 0) {
          for (Permission permission : perms) {
            AccessController.checkPermission(permission);
          }
        } else {
          AccessController.checkPermission(new TcPermission(
              tripleCollectionUri.getUnicodeString(), TcPermission.READ));
        }
      }
    }
  }

  public void checkReadWritePermission(UriRef tripleCollectionUri) {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
      //will AllPermissions the rest is obsolete
      try {
        AccessController.checkPermission(new AllPermission());
      } catch (AccessControlException e) {
        if (tripleCollectionUri.equals(permissionGraphName)) {
          AccessController.checkPermission(new TcPermission(
              tripleCollectionUri.getUnicodeString(), TcPermission.READWRITE));
        } else {
          Collection<Permission> perms = getRequiredReadWritePermissions(tripleCollectionUri);
          if (perms.size() > 0) {
            for (Permission permission : perms) {
              AccessController.checkPermission(permission);
            }
          } else {
            AccessController.checkPermission(new TcPermission(
                tripleCollectionUri.getUnicodeString(), TcPermission.READWRITE));
          }
        }
      }
    }
  }

  /**
   * Set the set of permissions required for read access to a triple-collection, if
   * the set is non-empty the default TCPermisson is no longer required.
   *
   * @param tripleCollectionUri
   * @param permissionDescriptions
   */
  public void setRequiredReadPermissionStrings(UriRef tripleCollectionUri,
      Collection<String> permissionDescriptions) {
    readPermissionCache.remove(tripleCollectionUri);
    final LockableMGraph permissionMGraph = getOrCreatePermisionGraph();
    Lock l = permissionMGraph.getLock().writeLock();
    l.lock();
    try {
      removeExistingRequiredReadPermissions(tripleCollectionUri, permissionMGraph);
      final NonLiteral permissionList = createList(permissionDescriptions.iterator(), permissionMGraph);
      permissionMGraph.add(new TripleImpl(tripleCollectionUri,
          readPermissionListProperty, permissionList));
    } finally {
      l.unlock();
    }
  }

  /**
   * Set the set of permissions required for read access to a triple-collection, if
   * the set is non-empty the default TCPermisson is no longer required.
   *
   * @param tripleCollectionUri
   * @param permissionDescriptions
   */
  public void setRequiredReadPermissions(UriRef tripleCollectionUri,
      Collection<Permission> permissions) {
    Collection<String> permissionStrings = new ArrayList<String>();
    for (Permission permission : permissions) {
      permissionStrings.add(permission.toString());
    }
    setRequiredReadPermissionStrings(tripleCollectionUri, permissionStrings);
  }

  /**
   * Set the set of permissions required for read-write access to a
   * triple-collection, if
   * the set is non-empty the default TCPermisson is no longer required.
   *
   * @param tripleCollectionUri
   * @param permissionDescriptions
   */
  public void setRequiredReadWritePermissionStrings(UriRef tripleCollectionUri,
      Collection<String> permissionDescriptions) {
    readWritePermissionCache.remove(tripleCollectionUri);
    final LockableMGraph permissionMGraph = getOrCreatePermisionGraph();
    Lock l = permissionMGraph.getLock().writeLock();
    l.lock();
    try {
      removeExistingRequiredReadPermissions(tripleCollectionUri, permissionMGraph);
      final NonLiteral permissionList = createList(permissionDescriptions.iterator(), permissionMGraph);
      permissionMGraph.add(new TripleImpl(tripleCollectionUri,
          readWritePermissionListProperty, permissionList));
    } finally {
      l.unlock();
    }
  }

  /**
   * Set the set of permissions required for read-write access to a
   * triple-collection, if
   * the set is non-empty the default TCPermisson is no longer required.
   *
   * @param tripleCollectionUri
   * @param permissionDescriptions
   */
  public void setRequiredReadWritePermissions(UriRef tripleCollectionUri,
      Collection<Permission> permissions) {
    Collection<String> permissionStrings = new ArrayList<String>();
    for (Permission permission : permissions) {
      permissionStrings.add(permission.toString());
    }
    setRequiredReadWritePermissionStrings(tripleCollectionUri, permissionStrings);
  }

  /**
   * Get the set of permissions required for read access to the
   * triple-collection, the set may be empty meaning that the default
   * TCPermission is required.
   *
   * @param tripleCollectionUri
   * @return the collection of permissions
   */
  public Collection<Permission> getRequiredReadPermissions(UriRef tripleCollectionUri) {
    Collection<Permission> result = readPermissionCache.get(tripleCollectionUri);
    if (result == null) {
      result = new ArrayList<Permission>();
      Collection<String> permissionStrings = getRequiredReadPermissionStrings(tripleCollectionUri);
      for (String string : permissionStrings) {
        result.add(PermissionParser.getPermission(string, getClass().getClassLoader()));
      }
      readPermissionCache.put(tripleCollectionUri, result);
    }
    return result;
  }

  /**
   * Get the set of permissions required for read-write access to the
   * triple-collection, the set may be empty meaning that the default
   * TCPermission is required.
   *
   * @param tripleCollectionUri
   * @return the collection of permissions
   */
  public Collection<Permission> getRequiredReadWritePermissions(UriRef tripleCollectionUri) {
    Collection<Permission> result = readWritePermissionCache.get(tripleCollectionUri);
    if (result == null) {
      result = new ArrayList<Permission>();
      Collection<String> permissionStrings = getRequiredReadWritePermissionStrings(tripleCollectionUri);
      for (String string : permissionStrings) {
        result.add(PermissionParser.getPermission(string, getClass().getClassLoader()));
      }
      readWritePermissionCache.put(tripleCollectionUri, result);
    }
    return result;
  }

  private NonLiteral createList(Iterator<String> iterator, LockableMGraph permissionMGraph) {
    if (!iterator.hasNext()) {
      return rdfNil;
    }
    final BNode result = new BNode();
    permissionMGraph.add(new TripleImpl(result, first,
        LiteralFactory.getInstance().createTypedLiteral(iterator.next())));
    permissionMGraph.add(new TripleImpl(result, rest,
        createList(iterator, permissionMGraph)));
    return result;

  }

  //called withiong write-lock
  private void removeExistingRequiredReadPermissions(UriRef tripleCollectionUri,
      LockableMGraph permissionMGraph) {
    try {
      Triple t = permissionMGraph.filter(tripleCollectionUri, readPermissionListProperty, null).next();
      Resource list = t.getObject();
      removeList((NonLiteral) list, permissionMGraph);
      permissionMGraph.remove(t);
    } catch (NoSuchElementException e) {
      //There was no existing to remove
    }
  }

  private void removeList(NonLiteral list, LockableMGraph permissionMGraph) {
    try {
      Triple t = permissionMGraph.filter(list, rest, null).next();
      Resource restList = t.getObject();
      removeList((NonLiteral) restList, permissionMGraph);
      permissionMGraph.remove(t);
      Iterator<Triple> iter = permissionMGraph.filter(list, first, null);
      iter.next();
      iter.remove();
    } catch (NoSuchElementException e) {
      //if it has no rest its rdf:NIL and has no first
    }
  }

  private Collection<String> getRequiredReadWritePermissionStrings(final UriRef tripleCollectionUri) {
    return getRequiredPermissionStrings(tripleCollectionUri, readWritePermissionListProperty);
  }
  private Collection<String> getRequiredReadPermissionStrings(final UriRef tripleCollectionUri) {
    return getRequiredPermissionStrings(tripleCollectionUri, readPermissionListProperty);
  }
  private Collection<String> getRequiredPermissionStrings(final UriRef tripleCollectionUri, UriRef property) {
    try {
      final LockableMGraph permissionMGraph = tcManager.getMGraph(permissionGraphName);
      Lock l = permissionMGraph.getLock().readLock();
      l.lock();
      try {
        Triple t = permissionMGraph.filter(tripleCollectionUri, property, null).next();
        NonLiteral list = (NonLiteral) t.getObject();
        LinkedList<String> result = new LinkedList<String>();
        readList(list, permissionMGraph, result);
        return result;
      } catch (NoSuchElementException e) {
        return new ArrayList<String>(0);
      } finally {
        l.unlock();
      }
    } catch (NoSuchEntityException e) {
      return new ArrayList<String>(0);
    }
  }

  private void readList(NonLiteral list, LockableMGraph permissionMGraph, LinkedList<String> target) {
    if (list.equals(rdfNil)) {
      return;
    }
    Triple restTriple = permissionMGraph.filter(list, rest, null).next();
    NonLiteral restList = (NonLiteral) restTriple.getObject();
    readList(restList, permissionMGraph, target);
    Triple firstTriple = permissionMGraph.filter(list, first, null).next();
    TypedLiteral firstValue = (TypedLiteral) firstTriple.getObject();
    String value = LiteralFactory.getInstance().createObject(String.class, firstValue);
    target.addFirst(value);
  }

  private LockableMGraph getOrCreatePermisionGraph() {
    try {
      return tcManager.getMGraph(permissionGraphName);
    } catch (NoSuchEntityException e) {
      return tcManager.createMGraph(permissionGraphName);
    }
  }
}
TOP

Related Classes of org.apache.clerezza.rdf.core.access.security.TcAccessController

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.