package org.infinispan.query.remote.impl; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.infinispan.AdvancedCache; import org.infinispan.commons.logging.LogFactory; import org.infinispan.protostream.ProtobufUtil; import org.infinispan.protostream.WrappedMessage; import org.infinispan.query.dsl.impl.BaseQuery; import org.infinispan.query.remote.client.QueryRequest; import org.infinispan.query.remote.client.QueryResponse; import org.infinispan.query.remote.impl.logging.Log; import org.infinispan.server.core.QueryFacade; import org.kohsuke.MetaInfServices; /** * A query facade implementation for both Lucene based queries and non-indexed in-memory queries. * All work is delegated to {@link RemoteQueryEngine}. * * @author anistor@redhat.com * @since 6.0 */ @MetaInfServices public final class QueryFacadeImpl implements QueryFacade { private static final Log log = LogFactory.getLog(QueryFacadeImpl.class, Log.class); /** * A special 'hidden' Lucene document field that holds the actual protobuf type name. */ public static final String TYPE_FIELD_NAME = "$type$"; @Override public byte[] query(AdvancedCache<byte[], byte[]> cache, byte[] query) { BaseRemoteQueryEngine queryEngine = SecurityActions.getCacheComponentRegistry(cache).getComponent(BaseRemoteQueryEngine.class); if (queryEngine == null) { throw log.queryingNotEnabled(cache.getName()); } try { // decode the query request object QueryRequest request = ProtobufUtil.fromByteArray(queryEngine.getSerializationContext(), query, 0, query.length, QueryRequest.class); long startOffset = request.getStartOffset() == null ? -1 : request.getStartOffset(); int maxResults = request.getMaxResults() == null ? -1 : request.getMaxResults(); // create the query BaseQuery q = queryEngine.makeQuery(request.getQueryString(), request.getNamedParametersMap(), startOffset, maxResults); // execute query and make the response object QueryResponse response = makeResponse(q); return ProtobufUtil.toByteArray(queryEngine.getSerializationContext(), response); } catch (IOException e) { throw log.errorExecutingQuery(e); } } private QueryResponse makeResponse(BaseQuery query) { List<?> list = query.list(); int numResults = list.size(); String[] projection = query.getProjection(); int projSize = projection != null ? projection.length : 0; List<WrappedMessage> results = new ArrayList<>(projSize == 0 ? numResults : numResults * projSize); for (Object o : list) { if (projSize == 0) { results.add(new WrappedMessage(o)); } else { Object[] row = (Object[]) o; for (int i = 0; i < projSize; i++) { results.add(new WrappedMessage(row[i])); } } } QueryResponse response = new QueryResponse(); response.setTotalResults(query.getResultSize()); response.setNumResults(numResults); response.setProjectionSize(projSize); response.setResults(results); return response; } }