Package org.datanucleus.store.query

Source Code of org.datanucleus.store.query.QueryManager

/**********************************************************************
Copyright (c) 2007 Erik Bengtson and others. All rights reserved.
Licensed 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.

Contributors:
2008 Andy Jefferson - check on datastore when getting query support
2008 Andy Jefferson - query cache
     ...
***********************************************************************/
package org.datanucleus.store.query;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import org.datanucleus.OMFContext;
import org.datanucleus.ObjectManager;
import org.datanucleus.PersistenceConfiguration;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.management.ManagementManager;
import org.datanucleus.management.ManagementServer;
import org.datanucleus.management.runtime.QueryRuntime;
import org.datanucleus.query.compiler.QueryCompilation;
import org.datanucleus.query.evaluator.memory.InvocationEvaluator;
import org.datanucleus.store.query.cache.CachedQuery;
import org.datanucleus.store.query.cache.QueryCache;
import org.datanucleus.util.ClassUtils;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;

/**
* Manages the runtime, metadata and lifecycle of queries.
* Provides caching of query compilations.
*/
public class QueryManager
{
    /** Localisation of messages. */
    protected static final Localiser LOCALISER = Localiser.getInstance("org.datanucleus.Localisation",
        ObjectManager.class.getClassLoader());

    OMFContext omfCtx;

    /** Query Cache. */
    QueryCache cache = null;

    /** Cache of InvocationEvaluator objects keyed by the method name. */
    Map<String, Collection> queryMethodEvaluatorMap = new HashMap();

    /** Query Runtime. Used when providing management of services. */
    QueryRuntime queryRuntime = null;

    public QueryManager(OMFContext omfContext)
    {
        this.omfCtx = omfContext;
        if (omfContext.getJMXManager() != null)
        {
            // register MBean in MbeanServer
            ManagementManager mgmtMgr = omfContext.getJMXManager();
            ManagementServer mgntServer = omfContext.getJMXManager().getManagementServer();
            queryRuntime = new QueryRuntime();
            String mbeanName = mgmtMgr.getDomainName() + ":InstanceName=" + mgmtMgr.getInstanceName() +
                ",Type=" + ClassUtils.getClassNameForClass(queryRuntime.getClass())+
                ",Name=QueryRuntime";
            mgntServer.registerMBean(this.queryRuntime, mbeanName);
        }

        initialiseQueryCache();
    }

    /**
     * Method to find and initialise the query cache, for caching query compilations.
     * Uses the persistence property "datanucleus.cache.query.type" and if set and not set to "none"
     * will initialise the "cache" field.
     */
    protected void initialiseQueryCache()
    {
        // Find the query cache class name from its plugin name
        PersistenceConfiguration conf = omfCtx.getPersistenceConfiguration();
        String queryCacheType = conf.getStringProperty("datanucleus.cache.query.type");
        if (queryCacheType != null && !queryCacheType.equalsIgnoreCase("none"))
        {
            String queryCacheClassName = omfCtx.getPluginManager().getAttributeValueForExtension(
                "org.datanucleus.cache_query", "name", queryCacheType, "class-name");
            if (queryCacheClassName == null)
            {
                // Plugin of this name not found
                throw new NucleusUserException(LOCALISER.msg("021500", queryCacheType)).setFatal();
            }

            try
            {
                // Create an instance of the Query Cache
                Class level2CacheClass = Class.forName(queryCacheClassName);
                Class[] ctrArgsClasses = new Class[] {OMFContext.class};
                Object[] ctrArgs = new Object[] {omfCtx};
                Constructor ctr = level2CacheClass.getConstructor(ctrArgsClasses);
                cache = (QueryCache)ctr.newInstance(ctrArgs);
                if (NucleusLogger.CACHE.isDebugEnabled())
                {
                    NucleusLogger.CACHE.debug(LOCALISER.msg("021502", queryCacheClassName));
                }
            }
            catch (Exception e)
            {
                // Class name for this Query cache plugin is not found!
                throw new NucleusUserException(LOCALISER.msg("021501", queryCacheType, queryCacheClassName), e).setFatal();
            }
        }
    }

    public void close()
    {
        if (cache != null)
        {
            cache.close();
            cache = null;
        }

        queryMethodEvaluatorMap.clear();
        queryMethodEvaluatorMap = null;
        queryRuntime = null;
    }

    public QueryRuntime getQueryRuntime()
    {
        return queryRuntime;
    }
   
    /**
     * Method to generate a new query using the passed query as basis.
     * @param language The query language
     * @param om The Object Manager
     * @param query The query filter (String) or a previous Query
     * @return The Query
     */
    public Query newQuery(String language, ObjectManager om, Object query)
    {
        if (language == null)
        {
            return null;
        }

        // Ability to override the implementation of JDOQL/JPQL to use
        String languageImpl = language;
        if (language.equalsIgnoreCase("JDOQL"))
        {
            String impl = omfCtx.getPersistenceConfiguration().getStringProperty("datanucleus.query.JDOQL.implementation");
            if (impl != null)
            {
                languageImpl = impl;
            }
        }
        else if (language.equalsIgnoreCase("JPQL"))
        {
            String impl = omfCtx.getPersistenceConfiguration().getStringProperty("datanucleus.query.JPQL.implementation");
            if (impl != null)
            {
                languageImpl = impl;
            }
        }

        // Find the query support for this language and this datastore
        try
        {
            if (query == null)
            {
                Class[] argsClass = new Class[] {org.datanucleus.ObjectManager.class};
                Object[] args = new Object[] {om};
                Query q = (Query) om.getOMFContext().getPluginManager().createExecutableExtension(
                    "org.datanucleus.store_query_query", new String[] {"name", "datastore"},
                    new String[] {languageImpl, om.getStoreManager().getStoreManagerKey()},
                    "class-name", argsClass, args);
                if (q == null)
                {
                    // No query support for this language
                    throw new NucleusException("DataNucleus doesnt currently support queries of language " + language + " for this datastore");
                }
                return q;
            }
            else
            {
                Query q = null;
                if (query instanceof String)
                {
                    // Try XXXQuery(ObjectManager, String);
                    Class[] argsClass = new Class[]{org.datanucleus.ObjectManager.class, String.class};
                    Object[] args = new Object[]{om, query};
                    q = (Query) om.getOMFContext().getPluginManager().createExecutableExtension(
                        "org.datanucleus.store_query_query", new String[] {"name", "datastore"},
                        new String[] {languageImpl, om.getStoreManager().getStoreManagerKey()},
                        "class-name", argsClass, args);
                    if (q == null)
                    {
                        // No query support for this language
                        throw new NucleusException("DataNucleus doesnt currently support queries of language " + language + " for this datastore");
                    }
                }
                else if (query instanceof Query)
                {
                    // Try XXXQuery(ObjectManager, Query.class);
                    Class[] argsClass = new Class[]{org.datanucleus.ObjectManager.class, query.getClass()};
                    Object[] args = new Object[]{om, query};
                    q = (Query) om.getOMFContext().getPluginManager().createExecutableExtension(
                        "org.datanucleus.store_query_query", new String[] {"name", "datastore"},
                        new String[] {languageImpl, om.getStoreManager().getStoreManagerKey()},
                        "class-name", argsClass, args);
                    if (q == null)
                    {
                        // No query support for this language
                        throw new NucleusException("DataNucleus doesnt currently support queries of language " + language + " for this datastore");
                    }
                }
                else
                {
                    // Try XXXQuery(ObjectManager, Object);
                    Class[] argsClass = new Class[]{org.datanucleus.ObjectManager.class, Object.class};
                    Object[] args = new Object[]{om, query};
                    q = (Query) om.getOMFContext().getPluginManager().createExecutableExtension(
                        "org.datanucleus.store_query_query", new String[] {"name", "datastore"},
                        new String[] {languageImpl, om.getStoreManager().getStoreManagerKey()},
                        "class-name", argsClass, args);
                    if (q == null)
                    {
                        // No query support for this language
                        throw new NucleusException("DataNucleus doesnt currently support queries of language " + language + " for this datastore");
                    }
                }
                return q;
            }
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getTargetException();
            if (t instanceof RuntimeException)
            {
                throw (RuntimeException) t;
            }
            else if (t instanceof Error)
            {
                throw (Error) t;
            }
            else
            {
                throw new NucleusException(t.getMessage(), t).setFatal();
            }
        }
        catch (Exception e)
        {
            throw new NucleusException(e.getMessage(), e).setFatal();
        }
    }

    /**
     * Method to store the compilation for a query.
     * @param language Language of the query
     * @param query The query string
     * @param compilation The compilation of this query
     */
    public synchronized void addQueryCompilation(String language, String query, QueryCompilation compilation)
    {
        if (cache != null)
        {
            String queryKey = language + ":" + query;
            CachedQuery cachedQuery = new CachedQuery(compilation);
            cache.put(queryKey, cachedQuery);
        }
    }

    /**
     * Accessor for a Query compilation for the specified query and language.
     * @param language Language of the query
     * @param query Query string
     * @return The compilation (if present)
     */
    public synchronized QueryCompilation getQueryCompilationForQuery(String language, String query)
    {
        if (cache != null)
        {
            String queryKey = language + ":" + query;
            CachedQuery cachedQuery = cache.get(queryKey);
            if (cachedQuery != null)
            {
                return cachedQuery.getCompilation();
            }
        }
        return null;
    }

    /**
     * Method to store the datastore-specific compilation for a query.
     * @param datastore The datastore identifier
     * @param language The query language
     * @param query The query (string form)
     * @param compilation The compiled information
     */
    public synchronized void addDatastoreQueryCompilation(String datastore, String language, String query, Object compilation)
    {
        if (cache != null)
        {
            String queryKey = language + ":" + query;
            CachedQuery cachedQuery = cache.get(queryKey);
            if (cachedQuery != null)
            {
                cachedQuery.addDatastoreCompilation(datastore, compilation);
            }
        }
    }

    /**
     * Accessor for the datastore-specific compilation for a query.
     * @param datastore The datastore identifier
     * @param language The query language
     * @param query The query (string form)
     * @return The compiled information (if available)
     */
    public synchronized Object getDatastoreQueryCompilation(String datastore, String language, String query)
    {
        if (cache != null)
        {
            String queryKey = language + ":" + query;
            CachedQuery cachedQuery = cache.get(queryKey);
            if (cachedQuery != null)
            {
                return cachedQuery.getDatastoreCompilation(datastore);
            }
        }
        return null;
    }

    /**
     * Accessor for an evaluator for invocation of the specified method.
     * If it is not a supported method then returns null.
     * @param methodName Name of the method
     * @return Evaluator suitable for this type with this method name
     */
    public InvocationEvaluator getInMemoryEvaluatorForMethod(Class type, String methodName)
    {
        Collection methods = queryMethodEvaluatorMap.get(methodName);
        if (methods != null)
        {
            Iterator evaluatorIter = methods.iterator();
            while (evaluatorIter.hasNext())
            {
                InvocationEvaluator eval = (InvocationEvaluator)evaluatorIter.next();
                if (eval.supportsType(type))
                {
                    return eval;
                }
            }
        }
        else
        {
            // Not yet loaded for this method
            String[] evaluatorNames = omfCtx.getPluginManager().getAttributeValuesForExtension(
                "org.datanucleus.store_query_methods", "name", methodName, "memory-evaluator");
            if (evaluatorNames != null)
            {
                Collection evaluators = new HashSet();
                InvocationEvaluator evalToUse = null;
                for (int i=0;i<evaluatorNames.length;i++)
                {
                    try
                    {
                        Class evalCls = omfCtx.getClassLoaderResolver(null).classForName(evaluatorNames[i]);
                        InvocationEvaluator eval = (InvocationEvaluator)evalCls.newInstance();
                        evaluators.add(eval);
                        if (eval.supportsType(type))
                        {
                            evalToUse = eval;
                        }
                    }
                    catch (Exception e)
                    {
                        NucleusLogger.QUERY.warn("Extension org.datanucleus.store_query_methods has method=" +
                            methodName + " referencing evaluator " + evaluatorNames[i] +
                            " but an error occurred in construction : " + e.getMessage());
                    }
                }
                queryMethodEvaluatorMap.put(methodName, evaluators);
                return evalToUse;
            }
        }
        return null;
    }
}
TOP

Related Classes of org.datanucleus.store.query.QueryManager

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.