public QueryExecutor < S > executor ( Filter < S > filter , OrderingList < S > ordering , QueryHints hints ) throws RepositoryException { final Key < S > key = new Key < S > ( filter , ordering , hints ) ; synchronized ( mPrimaryCache ) { QueryExecutor < S > executor = mPrimaryCache . get ( key ) ; if ( executor != null ) { return executor ; } } // Fallback to second level cache, which may still have the executor because // garbage collection has not reclaimed it yet. It also allows some concurrent // executor creation, by using filter-specific locks. SoftValuedCache < Object , QueryExecutor < S > > cache ; synchronized ( mFilterToExecutor ) { cache = mFilterToExecutor . get ( filter ) ; if ( cache == null ) { cache = SoftValuedCache . newCache ( 7 ) ; mFilterToExecutor . put ( filter , cache ) ; } } Object subKey ; if ( hints == null || hints . isEmpty ( ) ) { subKey = ordering ; } else { // Don't construct key with filter. It is not needed here and it would prevent // garbage collection of filters. subKey = new Key ( null , ordering , hints ) ; } QueryExecutor < S > executor ; synchronized ( cache ) { executor = cache . get ( subKey ) ; if ( executor == null ) { executor = mFactory . executor ( filter , ordering , hints ) ; cache . put ( subKey , executor ) ; } } synchronized ( mPrimaryCache ) { mPrimaryCache . put ( key , executor ) ; } return executor ; }
Returns an executor from the cache .