001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store.query; 019 020 import java.util.ArrayList; 021 import java.util.Collection; 022 import java.util.Collections; 023 import java.util.List; 024 import java.util.Map; 025 import java.util.Set; 026 027 import javax.jdo.PersistenceManager; 028 029 import org.cumulus4j.store.Cumulus4jStoreManager; 030 import org.cumulus4j.store.PersistenceManagerConnection; 031 import org.cumulus4j.store.crypto.CryptoContext; 032 import org.cumulus4j.store.model.ClassMeta; 033 import org.datanucleus.query.evaluator.JDOQLEvaluator; 034 import org.datanucleus.query.evaluator.JavaQueryEvaluator; 035 import org.datanucleus.store.ExecutionContext; 036 import org.datanucleus.store.StoreManager; 037 import org.datanucleus.store.connection.ManagedConnection; 038 import org.datanucleus.store.query.AbstractJDOQLQuery; 039 import org.datanucleus.util.NucleusLogger; 040 041 /** 042 * JDOQL query implementation. Delegates to the query-language-agnostic {@link QueryEvaluator} via 043 * its thin wrapper sub-class {@link JDOQueryEvaluator}. 044 * 045 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 046 */ 047 public class JDOQLQuery extends AbstractJDOQLQuery 048 { 049 private static final long serialVersionUID = 1L; 050 051 // BEGIN DataNucleus 3.0.0-m6 and 3.0.0-release 052 // public JDOQLQuery(ExecutionContext ec, AbstractJDOQLQuery q) { 053 // super(ec, q); 054 // } 055 // 056 // public JDOQLQuery(ExecutionContext ec, String query) { 057 // super(ec, query); 058 // } 059 // 060 // public JDOQLQuery(ExecutionContext ec) { 061 // super(ec); 062 // } 063 // END DataNucleus 3.0.0-m6 and 3.0.0-release 064 065 // BEGIN DataNucleus 3.0.1 and newer 066 public JDOQLQuery(StoreManager storeMgr, ExecutionContext ec, AbstractJDOQLQuery q) { 067 super(storeMgr, ec, q); 068 } 069 070 public JDOQLQuery(StoreManager storeMgr, ExecutionContext ec, String query) { 071 super(storeMgr, ec, query); 072 } 073 074 public JDOQLQuery(StoreManager storeMgr, ExecutionContext ec) { 075 super(storeMgr, ec); 076 } 077 // END DataNucleus 3.0.1 and newer 078 079 @Override 080 protected Object performExecute(@SuppressWarnings("rawtypes") Map parameters) 081 { 082 ManagedConnection mconn = ec.getStoreManager().getConnection(ec); 083 try { 084 PersistenceManagerConnection pmConn = (PersistenceManagerConnection)mconn.getConnection(); 085 PersistenceManager pmData = pmConn.getDataPM(); 086 087 Cumulus4jStoreManager storeManager = (Cumulus4jStoreManager) ec.getStoreManager(); 088 CryptoContext cryptoContext = new CryptoContext(storeManager.getEncryptionCoordinateSetManager(), storeManager.getKeyStoreRefManager(), ec, pmConn); 089 storeManager.getDatastoreVersionManager().applyOnce(cryptoContext); 090 091 boolean inMemory = evaluateInMemory(); 092 boolean inMemory_applyFilter = true; 093 List<Object> candidates = null; 094 if (this.candidateCollection != null) { 095 if (candidateCollection.isEmpty()) 096 { 097 return Collections.EMPTY_LIST; 098 } 099 100 @SuppressWarnings("unchecked") 101 Collection<? extends Object> c = this.candidateCollection; 102 candidates = new ArrayList<Object>(c); 103 } 104 else { 105 // http://sourceforge.net/tracker/?func=detail&aid=3514690&group_id=517465&atid=2102911 106 // Must NOT call this.setCandidateClass(...), because 1st it's already assigned and 2nd it clears the compilation. 107 // Marco :-) 108 // if (candidateExtent != null) { 109 // this.setCandidateClass(candidateExtent.getCandidateClass()); 110 // this.setSubclasses(candidateExtent.hasSubclasses()); 111 // } 112 113 if (inMemory) { 114 // Retrieve all candidates and perform all evaluation in-memory 115 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas(storeManager, 116 ec, candidateClass, subclasses); 117 candidates = QueryHelper.getAllPersistentObjectsForCandidateClasses(cryptoContext, pmData, classMetas); 118 } 119 else { 120 try 121 { 122 // Apply filter in datastore 123 @SuppressWarnings("unchecked") 124 Map<String, Object> parameterValues = parameters; 125 JDOQueryEvaluator queryEvaluator = new JDOQueryEvaluator(this, compilation, parameterValues, clr, pmConn, cryptoContext); 126 candidates = queryEvaluator.execute(); 127 if (queryEvaluator.isComplete()) { 128 inMemory_applyFilter = false; 129 } 130 else { 131 NucleusLogger.QUERY.debug("Query evaluation of filter in datastore was incomplete so doing further work in-memory"); 132 } 133 } 134 catch (UnsupportedOperationException uoe) { 135 // Some part of the filter is not yet supported, so fallback to in-memory evaluation 136 // Retrieve all candidates and perform all evaluation in-memory 137 NucleusLogger.QUERY.info("Query filter is not totally evaluatable in-datastore using Cumulus4j currently, so evaluating in-memory : "+uoe.getMessage()); 138 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas(storeManager, 139 ec, candidateClass, subclasses); 140 candidates = QueryHelper.getAllPersistentObjectsForCandidateClasses(cryptoContext, pmData, classMetas); 141 } 142 } 143 } 144 145 // Evaluate any remaining query components in-memory 146 JavaQueryEvaluator evaluator = new JDOQLEvaluator(this, candidates, compilation, parameters, ec.getClassLoaderResolver()); 147 return evaluator.execute(inMemory_applyFilter, true, true, true, true); 148 } finally { 149 mconn.release(); 150 } 151 } 152 153 }