/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.extension.httpsession.impl;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.seasar.extension.httpsession.SessionState;
import org.seasar.extension.httpsession.SessionStateManager;
import org.seasar.extension.jdbc.impl.BasicBatchHandler;
import org.seasar.extension.jdbc.impl.BasicSelectHandler;
import org.seasar.extension.jdbc.impl.BasicUpdateHandler;
import org.seasar.extension.jdbc.impl.MapListResultSetHandler;
import org.seasar.framework.util.SerializeUtil;
/**
* データベース用の {@link SessionStateManager}の実装クラスです。
*
* @author higa
*
*/
public class DbSessionStateManagerImpl implements SessionStateManager {
private static final String SELECT_SQL = "select name, value, last_access from s2session where session_id = ?";
private static final String INSERT_SQL = "insert into s2session values(?, ?, ?, ?)";
private static final String UPDATE_SQL = "update s2session set value = ?, last_access = ? where session_id = ? and name = ?";
private static final String DELETE_SQL = "delete from s2session where session_id = ? and name = ?";
private static final String DELETE_ALL_SQL = "delete from s2session where session_id = ?";
private DataSource dataSource;
private boolean batchUpdateDisabled;
/**
* {@link DbSessionStateManagerImpl}を作成します。
*/
public DbSessionStateManagerImpl() {
}
/**
* {@link DbSessionStateManagerImpl}を作成します。
*
* @param dataSource
* データソース
*/
public DbSessionStateManagerImpl(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* データソースを設定します。
*
* @param dataSource
* データソース
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* バッチ更新を無効にする場合<code>true</code>を設定します。
*
* @param batchUpdateDisabled
* バッチ更新を無効にする場合<code>true</code>
*/
public void setBatchUpdateDisabled(boolean batchUpdateDisabled) {
this.batchUpdateDisabled = batchUpdateDisabled;
}
public SessionState loadState(String sessionId) {
BasicSelectHandler handler = new BasicSelectHandler(dataSource,
SELECT_SQL, new MapListResultSetHandler());
List result = (List) handler.execute(new String[] { sessionId });
Map binaryData = new HashMap(result.size());
long lastAccessedTime = System.currentTimeMillis();
for (int i = 0; i < result.size(); i++) {
Map m = (Map) result.get(i);
binaryData.put(m.get("name"), m.get("value"));
final Timestamp lastAccess = (Timestamp) m.get("lastAccess");
if (lastAccess != null) {
lastAccessedTime = lastAccess.getTime();
}
}
return new SessionState(binaryData, lastAccessedTime);
}
public void removeState(String sessionId) {
BasicUpdateHandler handler = new BasicUpdateHandler(dataSource,
DELETE_ALL_SQL);
handler.execute(new Object[] { sessionId });
}
public void updateState(String sessionId, SessionState sessionState) {
List insertedData = new ArrayList();
List updatedData = new ArrayList();
List deletedData = new ArrayList();
Timestamp lastAccess = new Timestamp(new Date().getTime());
Enumeration e = sessionState.getAccessedAttributeNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
if (sessionState.needInsert(name)) {
byte[] value = SerializeUtil.fromObjectToBinary(sessionState
.getAttribute(name));
insertedData.add(new Object[] { sessionId, name, value,
lastAccess });
} else if (sessionState.needUpdate(name)) {
byte[] value = SerializeUtil.fromObjectToBinary(sessionState
.getAttribute(name));
updatedData.add(new Object[] { value, lastAccess, sessionId,
name });
} else if (sessionState.needDelete(name)) {
deletedData.add(new Object[] { sessionId, name });
}
}
execute(INSERT_SQL, insertedData);
execute(UPDATE_SQL, updatedData);
execute(DELETE_SQL, deletedData);
sessionState.persisted();
}
/**
* データを更新します。
*
* @param sql
* SQL
* @param data
* データ
*/
protected void execute(String sql, List data) {
if (data.size() == 0) {
return;
}
if (batchUpdateDisabled) {
executeUpdate(sql, data);
} else {
executeBatch(sql, data);
}
}
/**
* バッチ更新を行ないます。
*
* @param sql
* SQL
* @param data
* データ
*/
protected void executeBatch(String sql, List data) {
BasicBatchHandler handler = new BasicBatchHandler(dataSource, sql);
handler.execute(data);
}
/**
* 1行ずつ更新処理を行ないます。
*
* @param sql
* SQL
* @param data
* データ
*/
protected void executeUpdate(String sql, List data) {
BasicUpdateHandler handler = new BasicUpdateHandler(dataSource, sql);
for (Iterator i = data.iterator(); i.hasNext();) {
handler.execute((Object[]) i.next());
}
}
}