/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.amber.query;
import com.caucho.amber.manager.AmberConnection;
import com.caucho.amber.type.EntityType;
import com.caucho.amber.type.AmberType;
import com.caucho.util.Alarm;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Represents the application's view of the query.
*/
public class CachedQuery {
private AmberSelectQuery _query;
private CachedQueryKey _key;
private ResultSetImpl _rs;
private AmberType []_argTypes;
private Object []_argValues;
private int _argLength = 0;
private long _loadTime;
private ArrayList<Object> _values = new ArrayList<Object>();
private volatile boolean _isLoading;
private volatile boolean _isValidLoad;
CachedQuery(UserQuery query)
{
_query = (AmberSelectQuery) query.getQuery();
AmberType []argTypes = query.getArgTypes();
Object []argValues = query.getArgValues();
_argLength = query.getArgLength();
if (_argLength > 0) {
_argTypes = new AmberType[_argLength];
_argValues = new Object[_argLength];
for (int i = _argLength - 1; i >= 0; i--) {
_argTypes[i] = argTypes[i];
_argValues[i] = argValues[i];
}
}
_key = new CachedQueryKey();
_key.init(_query.getQueryString(), _argValues, _argLength);
_query.registerUpdates(this);
}
/**
* returns the key.
*/
public CachedQueryKey getKey()
{
return _key;
}
/**
* Updates the query.
*/
public void update()
{
synchronized (this) {
_loadTime = 0;
_isValidLoad = false;
}
}
/**
* Executes the query, filling the list.
*/
public void list(List<Object> list, AmberConnection aConn, long maxAge)
throws SQLException
{
AmberType type = _query.getResultType(0);
EntityType entityType = (EntityType) type;
Class cl = entityType.getBeanClass();
synchronized (this) {
long now = Alarm.getCurrentTime();
if (now < _loadTime + maxAge || _isLoading && _loadTime > 0) {
int length = _values.size();
for (int i = 0; i < length; i++) {
Object key = _values.get(i);
list.add(aConn.loadLazy(cl.getName(), entityType.getName(), (java.io.Serializable) key));
}
return;
}
_isLoading = true;
_isValidLoad = true;
}
try {
ArrayList<Object> values = new ArrayList<Object>();
ResultSetImpl rs = executeQuery(aConn);
while (rs.next()) {
values.add(rs.getKey(1));
list.add(rs.getObject(1));
}
rs.close();
synchronized (this) {
if (_isValidLoad) {
_values = values;
_loadTime = Alarm.getCurrentTime();
}
}
} finally {
_isLoading = false;
}
}
/**
* Executes the query returning a result set.
*/
private ResultSetImpl executeQuery(AmberConnection aConn)
throws SQLException
{
if (_rs == null)
_rs = new ResultSetImpl();
PreparedStatement pstmt;
pstmt = aConn.prepareStatement(_query.getSQL());
pstmt.clearParameters();
for (int i = 0; i < _argLength; i++) {
if (_argValues[i] != null)
_argTypes[i].setParameter(pstmt, i + 1, _argValues[i]);
}
ResultSet rs = pstmt.executeQuery();
_rs.setResultSet(rs);
_rs.setQuery((AmberSelectQuery) _query);
_rs.setSession(aConn);
_rs.init();
return _rs;
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _query.getQueryString() + "]";
}
}