org.globus.mds.bigindex.impl.QueryRPProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.globus.mds.bigindex.impl.QueryRPProvider.java

Source

/*
 * Portions of this file Copyright 1999-2005 University of Chicago
 * Portions of this file Copyright 1999-2005 The University of Southern California.
 *
 * This file or a portion of this file is licensed under the
 * terms of the Globus Toolkit Public License, found at
 * http://www.globus.org/toolkit/download/license.html.
 * If you redistribute this file, with or without
 * modifications, you must include this notice in the file.
 */
package org.globus.mds.bigindex.impl;

import java.rmi.RemoteException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.globus.wsrf.Constants;
import org.globus.wsrf.WSRFConstants;
import org.globus.wsrf.ResourceProperties;
import org.globus.wsrf.ResourcePropertySet;
import org.globus.wsrf.ResourceContext;
import org.globus.wsrf.NoSuchResourceException;
import org.globus.wsrf.query.QueryEngine;
import org.globus.wsrf.query.UnsupportedQueryDialectException;
import org.globus.wsrf.query.QueryException;
import org.globus.wsrf.query.QueryEvaluationException;
import org.globus.wsrf.query.InvalidQueryExpressionException;
import org.globus.wsrf.utils.AnyHelper;
import org.globus.wsrf.utils.FaultHelper;
import org.globus.wsrf.utils.Resources;
import org.globus.wsrf.impl.servicegroup.ServiceGroupConstants;
import org.globus.wsrf.impl.properties.QueryResourcePropertiesProvider;
import org.globus.util.I18n;

import org.oasis.wsrf.properties.InvalidQueryExpressionFaultType;
import org.oasis.wsrf.properties.InvalidResourcePropertyQNameFaultType;
import org.oasis.wsrf.properties.QueryEvaluationErrorFaultType;
import org.oasis.wsrf.properties.QueryExpressionType;
import org.oasis.wsrf.properties.ResourceUnknownFaultType;
import org.oasis.wsrf.properties.UnknownQueryExpressionDialectFaultType;
import org.oasis.wsrf.properties.QueryResourceProperties_Element;
import org.oasis.wsrf.properties.QueryResourcePropertiesResponse;

import org.globus.mds.bigindex.impl.database.xml.xindice.XindiceIndexDatabase;

/**
 * QueryResourceProperties operation implementation.  Directly queries the 
 * database using XPath when the Entry resource property is queried, otherwise 
 * falls back to the existing implementation for all other resource properties.  
 * Since not all Entry resource property data is necessarily stored in-memory, 
 * what can be returned from this method may be different than what is returned 
 * from GetResourceProperty directly on the Entry resource property.
 */
public class QueryRPProvider extends QueryResourcePropertiesProvider {

    static Log logger = LogFactory.getLog(QueryRPProvider.class.getName());

    private static I18n i18n = I18n.getI18n(Resources.class.getName());

    public QueryResourcePropertiesResponse queryResourceProperties(QueryResourceProperties_Element request)
            throws RemoteException, InvalidResourcePropertyQNameFaultType, ResourceUnknownFaultType,
            InvalidQueryExpressionFaultType, QueryEvaluationErrorFaultType, UnknownQueryExpressionDialectFaultType {

        if (request == null) {
            throw new RemoteException(i18n.getMessage("nullArgument", "request"));
        }

        BigIndexResource resource = null;
        try {
            resource = (BigIndexResource) ResourceContext.getResourceContext().getResource();
        } catch (NoSuchResourceException e) {
            ResourceUnknownFaultType fault = new ResourceUnknownFaultType();
            FaultHelper faultHelper = new FaultHelper(fault);
            faultHelper.addFaultCause(e);
            throw fault;
        } catch (Exception e) {
            throw new RemoteException(i18n.getMessage("resourceDisoveryFailed"), e);
        }

        QueryExpressionType query = request.getQueryExpression();
        String queryStr;
        try {
            queryStr = this.getQueryString(query);
        } catch (Exception e) {
            throw new RemoteException("Query string parsing error", e);
        }

        if (this.isDatabaseQuery(queryStr)) {
            // get db instance
            XindiceIndexDatabase db = resource.getDatabase();
            if (db == null) {
                throw new RemoteException("Error: database instance is null");
            }

            List results = null;
            try {
                results = db.query(queryStr, null);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RemoteException("Query error", e);
            }

            QueryResourcePropertiesResponse response = new QueryResourcePropertiesResponse();
            AnyHelper.setAny(response, results);

            return response;
        } else {
            return super.queryResourceProperties(request);
        }

    }

    private String getQueryString(QueryExpressionType expression) throws Exception {
        if (expression == null) {
            throw new QueryException(i18n.getMessage("noQuery"));
        }
        if (expression.getDialect() == null) {
            throw new QueryException(i18n.getMessage("nullArgument", "expression.dialect"));
        }
        String dialect = expression.getDialect().toString();
        if (!(dialect.equals(WSRFConstants.XPATH_1_DIALECT))) {
            throw new UnsupportedQueryDialectException(i18n.getMessage("invalidQueryExpressionDialect"));
        }

        if (expression.getValue() == null || expression.getValue().toString().trim().length() == 0) {
            throw new InvalidQueryExpressionException(i18n.getMessage("noQueryString"));
        }

        String query = expression.getValue().toString().trim();

        if (logger.isDebugEnabled()) {
            logger.debug("Query: " + query);
        }

        return query;
    }

    /*
     * This pattern matching is imperfect as it will fail with any potential
     * wildcard queries against child elements that may exist in the database,
     * but where the parent or ancestor element names(s) of that child are not 
     * found in the query string.
     *
     * This limitation exists for backward compatibilty reasons. Moving forward 
     * we need to implement a separate query dialect in order to automatically 
     * dereference and search Content from the database.  
     * 
     * For now, such wildcarded queries are supported via the service-specific 
     * query interface implemented in QueryProvider.
     */
    private boolean isDatabaseQuery(String query) {
        boolean isDatabaseQuery = false;

        if (query.length() == 0) {
            return isDatabaseQuery;
        }

        /*
         * TODO: find out which is more efficient: default to search root of
         * Entry or start with Content (and specific children)?
         *
         * Starting with Content will cause less database hits, but will force 
         * the complete resource document to be serialized more often for 
         * queries against Entry that don't explicitly include Content or 
         * one of the other Content child elements listed below.
         *
         */
        isDatabaseQuery = (
        //(query.indexOf("'Entry'")>-1) || 
        //(query.indexOf(":Entry")>-1) ||
        //(query.indexOf(ServiceGroupConstants.WSSG_NS)>-1) || 
        (query.indexOf("'AggregatorData'") > -1) || (query.indexOf(":AggregatorData") > -1)
                || (query.indexOf("'AggregatorConfig'") > -1) || (query.indexOf(":AggregatorConfig") > -1)
                || (query.indexOf("'Content'") > -1) || (query.indexOf(":Content") > -1));

        return isDatabaseQuery;
    }
}