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

Source Code of org.apache.clerezza.rdf.core.access.TcManager

/*
* 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;

import java.security.AccessControlException;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;

import org.apache.clerezza.rdf.core.Graph;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.TripleCollection;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.security.TcAccessController;
import org.apache.clerezza.rdf.core.impl.WriteBlockedMGraph;
import org.apache.clerezza.rdf.core.impl.WriteBlockedTripleCollection;
import org.apache.clerezza.rdf.core.sparql.NoQueryEngineException;
import org.apache.clerezza.rdf.core.sparql.ParseException;
import org.apache.clerezza.rdf.core.sparql.QueryEngine;
import org.apache.clerezza.rdf.core.sparql.ResultSet;
import org.apache.clerezza.rdf.core.sparql.SparqlPreParser;
import org.apache.clerezza.rdf.core.sparql.query.AskQuery;
import org.apache.clerezza.rdf.core.sparql.query.ConstructQuery;
import org.apache.clerezza.rdf.core.sparql.query.DescribeQuery;
import org.apache.clerezza.rdf.core.sparql.query.Query;
import org.apache.clerezza.rdf.core.sparql.query.SelectQuery;
import org.apache.clerezza.rdf.core.sparql.query.impl.SimpleStringQuerySerializer;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;

/**
* This class implements
* <code>TcManager</code>, delegating the actual provision and creation of
* Graphs or MGraphs to registered
* <code>TcProvider</code>s. The class attempts to satisfy the request using the
* register
* <code>WeightedTcProvider</code> in decreasing order of weight. If multiple
* providers have the same weight the lexicographical order of the fully
* qualified class name determines which one is used, namely the one that occurs
* earlier. If a call to a registered provider causes an
* <code>IllegalArgumentException</code>,
* <code>NoSuchEntityException</code> or
* <code>UnsupportedOperationException</code> then the call is delegated to the
* next provider.
*
* Only one instance of this class should exist in a system, the public no
* argument constructor is meant for initialization by dependency injection
* systems such as OSGi-DS. Applications should use the static
* <code>getInstance()</code> method if they aren't using a framework that
* injects them the instance.
*
* This class returns
* <code>LockableMGraph</code>s a subtype of
* <code>MGraph</code> that allows read/write locks.
*
* This class also registers all TripleCollections as services with the property
* 'name' indicating there name.
*
* Security checks are done when a TripleCollection is retrieved. The returned
* TripleCollection will do no further security checks. Because of this it
* should not be passed to a context where different access control applies. If
* an MGraph is retrieved without having write permission the returned mGraph
* will be read-only.
*
* If a TripleCollections needs to passed around across different security
* contexts the one retrieved from the OSGi service whiteboard should be used as
* this performs access control on every access.
*
* @author reto, mir, hasan
*
*/
@Component
@Service(TcManager.class)
@Reference(name = "weightedTcProvider", policy = ReferencePolicy.DYNAMIC,
        referenceInterface = WeightedTcProvider.class,
        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE)
public class TcManager extends TcProviderMultiplexer {

    private static volatile TcManager instance;
    private TcAccessController tcAccessController = new TcAccessController(this);
    private Map<UriRef, ServiceRegistration> serviceRegistrations = Collections
            .synchronizedMap(new HashMap<UriRef, ServiceRegistration>());
    @Reference(policy = ReferencePolicy.DYNAMIC,
            cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected QueryEngine queryEngine;

    private ComponentContext componentContext;
    private Collection<UriRef> mGraphsToRegisterOnActivation = new HashSet<UriRef>();
    private Collection<UriRef> graphsToRegisterOnActivation = new HashSet<UriRef>();

    /**
     * the constructor sets the singleton instance to allow instantiation by
     * OSGi-DS. This constructor should not be called except by OSGi-DS,
     * otherwise the static
     * <code>getInstance</code> method should be used.
     */
    public TcManager() {
        TcManager.instance = this;
    }

    /**
     * This returns the singleton instance. If an instance has been previously
     * created (e.g. by OSGi declarative services) this instance is returned,
     * otherwise a new instance is created and providers are injected using the
     * service provider interface (META-INF/services/)
     *
     * @return the singleton instance
     */
    public static TcManager getInstance() {
        if (instance == null) {
            synchronized (TcManager.class) {
                if (instance == null) {
                    instance = new TcManager();
                    Iterator<WeightedTcProvider> weightedProviders = ServiceLoader
                            .load(WeightedTcProvider.class).iterator();
                    while (weightedProviders.hasNext()) {
                        WeightedTcProvider weightedProvider = weightedProviders
                                .next();
                        instance
                                .bindWeightedTcProvider(weightedProvider);
                    }
                    Iterator<QueryEngine> queryEngines = ServiceLoader.load(
                            QueryEngine.class).iterator();
                    System.out.println("looking for QE");
                    if (queryEngines.hasNext()) {
                        instance.queryEngine = queryEngines.next();
                        System.out.println("QE: "
                                + instance.queryEngine.getClass());
                    }
                }
            }
        }
        return instance;
    }

    protected void activate(final ComponentContext componentContext) {
        this.componentContext = componentContext;
        for (UriRef name : mGraphsToRegisterOnActivation) {
            registerTripleCollectionAsService(name, true);
        }
        for (UriRef name : graphsToRegisterOnActivation) {
            registerTripleCollectionAsService(name, false);
        }
    }

    protected void deactivate(final ComponentContext componentContext) {
        for (ServiceRegistration registration : serviceRegistrations.values()) {
            registration.unregister();
        }
        serviceRegistrations.clear();
        this.componentContext = null;
    }

    @Override
    public Graph getGraph(UriRef name) throws NoSuchEntityException {
        tcAccessController.checkReadPermission(name);
        return super.getGraph(name);
    }

    @Override
    public LockableMGraph getMGraph(UriRef name) {
        try {
            tcAccessController.checkReadWritePermission(name);
        } catch (AccessControlException e) {
            tcAccessController.checkReadPermission(name);
            return new WriteBlockedMGraph(super.getMGraph(name));
        }
        return super.getMGraph(name);
    }

    @Override
    public TripleCollection getTriples(UriRef name) {
        try {
            tcAccessController.checkReadWritePermission(name);
        } catch (AccessControlException e) {
            tcAccessController.checkReadPermission(name);
            return new WriteBlockedTripleCollection(
                    super.getTriples(name));
        }
        return super.getTriples(name);
    }

    @Override
    public LockableMGraph createMGraph(UriRef name)
            throws UnsupportedOperationException {
        tcAccessController.checkReadWritePermission(name);
        return super.createMGraph(name);
    }

    @Override
    public Graph createGraph(UriRef name, TripleCollection triples) {
        tcAccessController.checkReadWritePermission(name);
        return super.createGraph(name, triples);
    }

    @Override
    public void deleteTripleCollection(UriRef name) {
        tcAccessController.checkReadWritePermission(name);
        super.deleteTripleCollection(name);
    }

    @Override
    public Set<UriRef> getNames(Graph graph) {
        return super.getNames(graph);
    }

    @Override
    public Set<UriRef> listGraphs() {
        Set<UriRef> result = super.listGraphs();
        return excludeNonReadable(result);
    }

    @Override
    public Set<UriRef> listMGraphs() {
        Set<UriRef> result = super.listMGraphs();
        return excludeNonReadable(result);
    }

    @Override
    public Set<UriRef> listTripleCollections() {
        Set<UriRef> result = super.listTripleCollections();
        return excludeNonReadable(result);
    }

    private Set<UriRef> excludeNonReadable(Set<UriRef> tcNames) {
        SecurityManager security = System.getSecurityManager();
        if (security == null) {
            return tcNames;
        }
        Set<UriRef> result = new HashSet<UriRef>();
        for (UriRef name : tcNames) {
            try {
                tcAccessController.checkReadPermission(name);
            } catch (AccessControlException e) {
                continue;
            }
            result.add(name);
        }
        return result;
    }

    /**
     * Executes any sparql query. The type of the result object will vary
     * depending on the type of the query. If the defaultGraph is available
     * in this TcManages executeSparqlQuery(String, UriRef) should be used instead.
     *
     * @param query the sparql query to execute
     * @param defaultGraph the default graph against which to execute the query
     * if no FROM clause is present
     * @return the resulting ResultSet, Graph or Boolean value
     */
    public Object executeSparqlQuery(String query, TripleCollection defaultGraph) throws ParseException {
        final UriRef defaultGraphName = new UriRef("urn:x-temp:/kjsfadfhfasdffds");
        SparqlPreParser sparqlPreParser = new SparqlPreParser(this);
        final Set<UriRef> referencedGraphs = sparqlPreParser.getReferredGraphs(query, defaultGraphName);
        TcProvider singleTargetTcProvider = null;
        if ((referencedGraphs != null) && (!referencedGraphs.contains(defaultGraphName))) {
            singleTargetTcProvider = getSingleTargetTcProvider(referencedGraphs);
        }
        if ((singleTargetTcProvider != null) && (singleTargetTcProvider instanceof QueryableTcProvider)) {
            return ((QueryableTcProvider)singleTargetTcProvider).executeSparqlQuery(query, null);
        }
        final QueryEngine queryEngine = this.queryEngine;
        if (queryEngine != null) {
            return queryEngine.execute(this, defaultGraph, query);
        } else {
            throw new NoQueryEngineException();
        }
    }
   
    public Object executeSparqlQuery(String query, UriRef defaultGraphName) throws ParseException {
        SparqlPreParser sparqlPreParser = new SparqlPreParser(this);
        final Set<UriRef> referencedGraphs = sparqlPreParser.getReferredGraphs(query, defaultGraphName);
        TcProvider singleTargetTcProvider = null;
        if ((referencedGraphs != null)) {
            singleTargetTcProvider = getSingleTargetTcProvider(referencedGraphs);
        }
        if ((singleTargetTcProvider != null) && (singleTargetTcProvider instanceof QueryableTcProvider)) {
            return ((QueryableTcProvider)singleTargetTcProvider).executeSparqlQuery(query, defaultGraphName);
        }
        final QueryEngine queryEngine = this.queryEngine;
        if (queryEngine != null) {
            return queryEngine.execute(this, this.getTriples(defaultGraphName), query);
        } else {
            throw new NoQueryEngineException();
        }
    }

    /**
     * Executes any sparql query. The type of the result object will vary
     * depending on the type of the query.
     *
     * @param query the sparql query to execute
     * @param defaultGraph the default graph against which to execute the query
     * if no FROM clause is present
     * @return the resulting ResultSet, Graph or Boolean value
     *
     * @deprecated Query is discontinued
     */
    @Deprecated
    public Object executeSparqlQuery(Query query, TripleCollection defaultGraph) {
        final QueryEngine queryEngine = this.queryEngine;
        if (queryEngine != null) {
            return queryEngine.execute(this, defaultGraph, query);
        } else {
            throw new NoQueryEngineException();
        }
    }

    /**
     * Executes a sparql SELECT query.
     *
     * @param query the sparql SELECT query to execute
     * @param defaultGraph the default graph against which to execute the query
     * if not FROM clause is present
     * @return the resulting ResultSet
     * @deprecated Query is discontinued
     */
    @Deprecated
    public ResultSet executeSparqlQuery(SelectQuery query,
            TripleCollection defaultGraph) {
        return (ResultSet) executeSparqlQuery((Query) query, defaultGraph);
    }

    /**
     * Executes a sparql ASK query.
     *
     * @param query the sparql ASK query to execute
     * @param defaultGraph the default graph against which to execute the query
     * if not FROM clause is present
     * @return the boolean value this query evaluates to
     * @deprecated Query is discontinued
     */
    @Deprecated
    public boolean executeSparqlQuery(AskQuery query,
            TripleCollection defaultGraph) {
        return (Boolean) executeSparqlQuery((Query) query, defaultGraph);
    }

    /**
     * Executes a sparql DESCRIBE query.
     *
     * @param query the sparql DESCRIBE query to execute
     * @param defaultGraph the default graph against which to execute the query
     * if not FROM clause is present
     * @return the resulting Graph
     * @deprecated Query is discontinued
     */
    @Deprecated
    public Graph executeSparqlQuery(DescribeQuery query,
            TripleCollection defaultGraph) {
        return (Graph) executeSparqlQuery((Query) query, defaultGraph);
    }

    /**
     * Executes a sparql CONSTRUCT query.
     *
     * @param query the sparql CONSTRUCT query to execute
     * @param defaultGraph the default graph against which to execute the query
     * if not FROM clause is present
     * @return the resulting Graph
     * @deprecated Query is discontinued
     */
    @Deprecated
    public Graph executeSparqlQuery(ConstructQuery query,
            TripleCollection defaultGraph) {
        return (Graph) executeSparqlQuery((Query) query, defaultGraph);
    }

    /**
     * @return the TcAccessController that can be used to set the permissions
     * needed to access a Triple Collection
     */
    public TcAccessController getTcAccessController() {
        return tcAccessController;
    }

    /**
     * Registers a provider
     *
     * @param provider the provider to be registered
     */
    protected void bindWeightedTcProvider(WeightedTcProvider provider) {
        addWeightedTcProvider(provider);
    }

    /**
     * Unregister a provider
     *
     * @param provider the provider to be deregistered
     */
    protected void unbindWeightedTcProvider(
            WeightedTcProvider provider) {
        removeWeightedTcProvider(provider);
    }

    @Override
    protected void mGraphAppears(UriRef name) {
        if (componentContext == null) {
            mGraphsToRegisterOnActivation.add(name);
        } else {
            registerTripleCollectionAsService(name, true);
        }
    }

    @Override
    protected void graphAppears(UriRef name) {
        if (componentContext == null) {
            graphsToRegisterOnActivation.add(name);
        } else {
            registerTripleCollectionAsService(name, false);
        }
    }

    private void registerTripleCollectionAsService(UriRef name, boolean isMGraph) {
        Dictionary props = new Properties();
        props.put("name", name.getUnicodeString());
        String[] interfaceNames;
        Object service;
        if (isMGraph) {
            interfaceNames = new String[]{
                MGraph.class.getName(),
                LockableMGraph.class.getName()
            };
            service = new MGraphServiceFactory(this, name, tcAccessController);
        } else {
            interfaceNames = new String[]{Graph.class.getName()};
            service = new GraphServiceFactory(this, name, tcAccessController);
        }
        final int bundleState = componentContext.getBundleContext().getBundle().getState();
        if ((bundleState == Bundle.ACTIVE) || (bundleState == Bundle.STARTING)) {
            ServiceRegistration serviceReg = componentContext.getBundleContext()
                    .registerService(interfaceNames, service, props);
            serviceRegistrations.put(name, serviceReg);
        }
    }

    @Override
    protected void tcDisappears(UriRef name) {
        mGraphsToRegisterOnActivation.remove(name);
        graphsToRegisterOnActivation.remove(name);
        ServiceRegistration reg = serviceRegistrations.get(name);
        if (reg != null) {
            reg.unregister();
            serviceRegistrations.remove(name);
        }
    }

    private TcProvider getSingleTargetTcProvider(final Set<UriRef> referencedGraphs) {
        TcProvider singleTargetTcProvider = null;
        for (WeightedTcProvider provider : providerList) {
            final Set<UriRef> providerTripleCollections = provider.listTripleCollections();
            if (providerTripleCollections.containsAll(referencedGraphs)) {
               singleTargetTcProvider = provider;
               break; //success
            }
            for (UriRef graphName : referencedGraphs) {
                if (providerTripleCollections.contains(graphName)) {
                    break; //failure
                }
            }     
        }
        return singleTargetTcProvider;
    }
}
TOP

Related Classes of org.apache.clerezza.rdf.core.access.TcManager

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.