/*
* Copyright (C) 2015 Jörg Prante
*
* 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.xbib.elasticsearch.jdbc.strategy.standard;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.xbib.elasticsearch.common.util.LocaleUtil;
import org.xbib.elasticsearch.jdbc.strategy.Context;
import org.xbib.elasticsearch.jdbc.strategy.JDBCSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.UUID;
public abstract class AbstractSourceTest extends Assert {
protected final static Logger logger = LogManager.getLogger("test.source");
protected static JDBCSource source;
public abstract JDBCSource newSource();
public abstract Context newContext();
@BeforeMethod
@Parameters({"starturl", "user", "password", "create"})
public void beforeMethod(String starturl, String user, String password, @Optional String resourceName)
throws Exception {
logger.info("nodes started");
source = newSource()
.setUrl(starturl)
.setUser(user)
.setPassword(password)
.setLocale(Locale.getDefault())
.setTimeZone(TimeZone.getDefault());
logger.info("create table {}", resourceName);
if (resourceName == null || "".equals(resourceName)) {
return;
}
Connection connection = source.getConnectionForWriting();
if (connection == null) {
throw new IOException("no connection");
}
sqlScript(connection, resourceName);
source.closeWriting();
}
@AfterMethod
@Parameters({"stopurl", "user", "password", "delete"})
public void afterMethod(String stopurl, String user, String password, @Optional String resourceName)
throws Exception {
logger.info("remove table {}", resourceName);
if (resourceName == null || "".equals(resourceName)) {
return;
}
// before dropping tables, open read connection must be closed to avoid hangs in mysql/postgresql
logger.debug("closing reads...");
source.closeReading();
logger.debug("connecting for close...");
Connection connection = source.getConnectionForWriting();
if (connection == null) {
throw new IOException("no connection");
}
logger.debug("cleaning...");
// clean up tables
sqlScript(connection, resourceName);
logger.debug("closing writes...");
source.closeWriting();
// we can drop database by a magic 'stop' URL
source = newSource()
.setUrl(stopurl)
.setUser(user)
.setPassword(password)
.setLocale(Locale.getDefault())
.setTimeZone(TimeZone.getDefault());
try {
logger.info("connecting to stop URL...");
// activate stop URL
source.getConnectionForWriting();
} catch (Exception e) {
// exception is expected, ignore
}
// close open write connection
source.closeWriting();
}
/*protected Context createContext(String resource) throws Exception {
InputStream in = getClass().getResourceAsStream(resource);
logger.info("creating context");
Settings settings = ImmutableSettings.settingsBuilder()
.loadFromStream("test", in)
.build().getAsSettings("jdbc");
Context context = newContext();
context.setSettings(settings);
return context;
}*/
protected void createRandomProducts(String sql, int size)
throws SQLException {
Connection connection = source.getConnectionForWriting();
for (int i = 0; i < size; i++) {
long amount = Math.round(Math.random() * 1000);
double price = (Math.random() * 10000) / 100.00;
add(connection, sql, UUID.randomUUID().toString().substring(0, 32), amount, price);
}
if (!connection.getAutoCommit()) {
connection.commit();
}
source.closeWriting();
}
protected void createTimestampedLogs(String sql, int size, String locale, String timezone)
throws SQLException {
Connection connection = source.getConnectionForWriting();
Locale l = LocaleUtil.toLocale(locale);
TimeZone t = TimeZone.getTimeZone(timezone);
source.setTimeZone(t).setLocale(l);
Calendar cal = Calendar.getInstance(t, l);
// half of log in the past, half of it in the future
cal.add(Calendar.HOUR, -(size / 2));
for (int i = 0; i < size; i++) {
Timestamp modified = new Timestamp(cal.getTimeInMillis());
String message = "Hello world";
add(connection, sql, modified, message);
cal.add(Calendar.HOUR, 1);
}
if (!connection.getAutoCommit()) {
connection.commit();
}
source.closeWriting();
}
private void add(Connection connection, String sql, final String name, final long amount, final double price)
throws SQLException {
PreparedStatement stmt = connection.prepareStatement(sql);
List<Object> params = new ArrayList<Object>() {{
add(name);
add(amount);
add(price);
}};
source.bind(stmt, params);
stmt.execute();
}
private void add(Connection connection, String sql, final Timestamp ts, final String message)
throws SQLException {
PreparedStatement stmt = connection.prepareStatement(sql);
List<Object> params = new ArrayList<Object>() {{
add(ts);
add(message);
}};
source.bind(stmt, params);
stmt.execute();
}
protected void createRandomProductsJob(String sql, int size)
throws SQLException {
Connection connection = source.getConnectionForWriting();
for (int i = 0; i < size; i++) {
long amount = Math.round(Math.random() * 1000);
double price = (Math.random() * 10000) / 100.00;
long job = 0L;
add(connection, sql, job, UUID.randomUUID().toString().substring(0, 32), amount, price);
}
if (!connection.getAutoCommit()) {
connection.commit();
}
source.closeWriting();
}
private void add(Connection connection, String sql, final long job, final String name, final long amount, final double price)
throws SQLException {
PreparedStatement stmt = connection.prepareStatement(sql);
List<Object> params = new ArrayList<Object>() {
{
add(job);
add(name);
add(amount);
add(price);
}
};
source.bind(stmt, params);
stmt.execute();
}
private void sqlScript(Connection connection, String resourceName) throws Exception {
InputStream in = getClass().getResourceAsStream(resourceName);
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String sql;
while ((sql = br.readLine()) != null) {
try {
logger.trace("executing {}", sql);
Statement p = connection.createStatement();
p.execute(sql);
p.close();
} catch (SQLException e) {
// ignore
logger.error(sql + " failed. Reason: " + e.getMessage());
} finally {
connection.commit();
}
}
br.close();
}
}