/* * Copyright 2016 the original author or authors. * * 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 ro.pippo.session.jdbc; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ro.pippo.core.PippoRuntimeException; import ro.pippo.session.SerializationSessionDataTranscoder; import ro.pippo.session.SessionData; import ro.pippo.session.SessionDataStorage; import ro.pippo.session.SessionDataTranscoder; /** * SessionDataStorage implementation with JDBC. * * @author Herman Barrantes */ public class JDBCSessionDataStorage implements SessionDataStorage { // Logger private static final Logger log = LoggerFactory.getLogger(JDBCSessionDataStorage.class); // CRUD Statements public static final String SELECT = "select data from session where id = ?"; public static final String INSERT = "insert into session (id, time, data) values (?, ?, ?)"; public static final String UPDATE = "update session set time = ?, data = ? where id = ?"; public static final String DELETE = "delete from session where id = ?"; // Variables private final DataSource dataSource; private final String select; private final String insert; private final String update; private final String delete; private final SessionDataTranscoder transcoder; public JDBCSessionDataStorage(DataSource dataSource) { this(dataSource, SELECT, INSERT, UPDATE, DELETE, new SerializationSessionDataTranscoder()); } public JDBCSessionDataStorage(DataSource dataSource, String select, String insert, String update, String delete) { this(dataSource, select, insert, update, delete, new SerializationSessionDataTranscoder()); } public JDBCSessionDataStorage(DataSource dataSource, String select, String insert, String update, String delete, SessionDataTranscoder transcoder) { this.dataSource = dataSource; this.select = select; this.insert = insert; this.update = update; this.delete = delete; this.transcoder = transcoder; } @Override public SessionData create() { return new SessionData(); } @Override public void save(SessionData sessionData) { String id = sessionData.getId(); Timestamp time = new Timestamp(System.currentTimeMillis()); String data = transcoder.encode(sessionData); if (executeUpdate(update, time, data, id) == 0) { executeUpdate(insert, id, time, data); } } @Override public SessionData get(String sessionId) { String sessionStored = executeSelect(select, sessionId); if (sessionStored == null) { return null; } SessionData sessionData = transcoder.decode(sessionStored); return sessionData; } @Override public void delete(String sessionId) { executeUpdate(delete, sessionId); } protected String executeSelect(String query, Object... parameters) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); preparedStatement = connection.prepareStatement(query); for (int i = 0; i < parameters.length; i++) { preparedStatement.setObject(i + 1, parameters[i]); } resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { return resultSet.getString(1); } } catch (SQLException ex) { log.error("Error executing the statement", ex); throw new PippoRuntimeException(ex); } finally { close(resultSet); close(preparedStatement); close(connection); } return null; } protected int executeUpdate(String query, Object... parameters) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = dataSource.getConnection(); preparedStatement = connection.prepareStatement(query); for (int i = 0; i < parameters.length; i++) { preparedStatement.setObject(i + 1, parameters[i]); } return preparedStatement.executeUpdate(); } catch (SQLException ex) { log.error("Error executing the statement", ex); throw new PippoRuntimeException(ex); } finally { close(preparedStatement); close(connection); } } protected void close(AutoCloseable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception ex) { log.error("Error closing resource", ex); } } } }