Commit 11d73eb0 authored by guus's avatar guus

Makes it all compile nicely. Added db-util sources (that are included in...

Makes it all compile nicely. Added db-util sources (that are included in Openfire as a JAR). Note that we need a Java 1.6 compiler to compile - a 1.7 compiler won't work because of java.sql extensions in db-utils.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/branches/maven-externalsbased@13066 b35dd754-fafc-0310-a699-88a17e54d16e
parent 17d73b00
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>org.igniterealtime.openfire</groupId>
<version>4.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>dbutil</artifactId>
</project>
\ No newline at end of file
/**
* $RCSfile$
* $Revision: 37 $
* $Date: 2004-10-20 23:08:43 -0700 (Wed, 20 Oct 2004) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import java.sql.*;
import java.util.Map;
import java.util.Properties;
/**
* An implementation of the Connection interface that wraps an underlying
* Connection object.
*
* @author Gaston Dombiak
*/
public abstract class AbstractConnection implements Connection {
protected Connection connection;
public AbstractConnection(Connection connection) {
this.connection = connection;
}
public <T> T unwrap(Class<T> iface) throws SQLException {
return connection.unwrap(iface);
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return connection.isWrapperFor(iface);
}
public Statement createStatement() throws SQLException {
return connection.createStatement();
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
return connection.prepareStatement(sql);
}
public CallableStatement prepareCall(String sql) throws SQLException {
return connection.prepareCall(sql);
}
public String nativeSQL(String sql) throws SQLException {
return connection.nativeSQL(sql);
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
connection.setAutoCommit(autoCommit);
}
public boolean getAutoCommit() throws SQLException {
return connection.getAutoCommit();
}
public void commit() throws SQLException {
connection.commit();
}
public void rollback() throws SQLException {
connection.rollback();
}
public void close() throws SQLException {
connection.close();
}
public boolean isClosed() throws SQLException {
return connection.isClosed();
}
public DatabaseMetaData getMetaData() throws SQLException {
return connection.getMetaData();
}
public void setReadOnly(boolean readOnly) throws SQLException {
connection.setReadOnly(readOnly);
}
public boolean isReadOnly() throws SQLException {
return connection.isReadOnly();
}
public void setCatalog(String catalog) throws SQLException {
connection.setCatalog(catalog);
}
public String getCatalog() throws SQLException {
return connection.getCatalog();
}
public void setTransactionIsolation(int level) throws SQLException {
connection.setTransactionIsolation(level);
}
public int getTransactionIsolation() throws SQLException {
return connection.getTransactionIsolation();
}
public SQLWarning getWarnings() throws SQLException {
return connection.getWarnings();
}
public void clearWarnings() throws SQLException {
connection.clearWarnings();
}
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return connection.createStatement(resultSetType, resultSetConcurrency);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
}
public Map<String, Class<?>> getTypeMap() throws SQLException {
return connection.getTypeMap();
}
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
connection.setTypeMap(map);
}
public void setHoldability(int holdability) throws SQLException {
connection.setHoldability(holdability);
}
public int getHoldability() throws SQLException {
return connection.getHoldability();
}
public Savepoint setSavepoint() throws SQLException {
return connection.setSavepoint();
}
public Savepoint setSavepoint(String name) throws SQLException {
return connection.setSavepoint(name);
}
public void rollback(Savepoint savepoint) throws SQLException {
connection.rollback(savepoint);
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
connection.releaseSavepoint(savepoint);
}
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return connection.prepareStatement(sql, autoGeneratedKeys);
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return connection.prepareStatement(sql, columnIndexes);
}
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return connection.prepareStatement(sql, columnNames);
}
public Clob createClob() throws SQLException {
return connection.createClob();
}
public Blob createBlob() throws SQLException {
return connection.createBlob();
}
public NClob createNClob() throws SQLException {
return connection.createNClob();
}
public SQLXML createSQLXML() throws SQLException {
return connection.createSQLXML();
}
public boolean isValid(int timeout) throws SQLException {
return connection.isValid(timeout);
}
public void setClientInfo(String name, String value) throws SQLClientInfoException {
connection.setClientInfo(name, value);
}
public void setClientInfo(Properties properties) throws SQLClientInfoException {
connection.setClientInfo(properties);
}
public String getClientInfo(String name) throws SQLException {
return connection.getClientInfo(name);
}
public Properties getClientInfo() throws SQLException {
return connection.getClientInfo();
}
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return connection.createArrayOf(typeName, elements);
}
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return connection.createStruct(typeName, attributes);
}
}
/**
* $RCSfile$
* $Revision: 37 $
* $Date: 2004-10-20 23:08:43 -0700 (Wed, 20 Oct 2004) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import java.sql.*;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Calendar;
import java.net.URL;
import java.io.InputStream;
import java.io.Reader;
/**
* An implementation of the CallableStatement interface that wraps an underlying
* CallableStatement object.
*
* @author Gaston Dombiak
*/
public abstract class CallableStatementWrapper extends StatementWrapper
implements CallableStatement {
protected CallableStatement cstmt;
public ResultSet executeQuery(String sql) throws SQLException {
return cstmt.executeQuery(sql);
}
public <T> T unwrap(Class<T> iface) throws SQLException {
return cstmt.unwrap(iface);
}
public ResultSet executeQuery() throws SQLException {
return cstmt.executeQuery();
}
public int executeUpdate(String sql) throws SQLException {
return cstmt.executeUpdate(sql);
}
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
cstmt.registerOutParameter(parameterIndex, sqlType);
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return cstmt.isWrapperFor(iface);
}
public int executeUpdate() throws SQLException {
return cstmt.executeUpdate();
}
public void close() throws SQLException {
cstmt.close();
}
public void setNull(int parameterIndex, int sqlType) throws SQLException {
cstmt.setNull(parameterIndex, sqlType);
}
public int getMaxFieldSize() throws SQLException {
return cstmt.getMaxFieldSize();
}
public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {
cstmt.registerOutParameter(parameterIndex, sqlType, scale);
}
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
cstmt.setBoolean(parameterIndex, x);
}
public void setMaxFieldSize(int max) throws SQLException {
cstmt.setMaxFieldSize(max);
}
public void setByte(int parameterIndex, byte x) throws SQLException {
cstmt.setByte(parameterIndex, x);
}
public void setShort(int parameterIndex, short x) throws SQLException {
cstmt.setShort(parameterIndex, x);
}
public int getMaxRows() throws SQLException {
return cstmt.getMaxRows();
}
public boolean wasNull() throws SQLException {
return cstmt.wasNull();
}
public void setInt(int parameterIndex, int x) throws SQLException {
cstmt.setInt(parameterIndex, x);
}
public void setMaxRows(int max) throws SQLException {
cstmt.setMaxRows(max);
}
public String getString(int parameterIndex) throws SQLException {
return cstmt.getString(parameterIndex);
}
public void setLong(int parameterIndex, long x) throws SQLException {
cstmt.setLong(parameterIndex, x);
}
public void setEscapeProcessing(boolean enable) throws SQLException {
cstmt.setEscapeProcessing(enable);
}
public boolean getBoolean(int parameterIndex) throws SQLException {
return cstmt.getBoolean(parameterIndex);
}
public void setFloat(int parameterIndex, float x) throws SQLException {
cstmt.setFloat(parameterIndex, x);
}
public int getQueryTimeout() throws SQLException {
return cstmt.getQueryTimeout();
}
public void setDouble(int parameterIndex, double x) throws SQLException {
cstmt.setDouble(parameterIndex, x);
}
public byte getByte(int parameterIndex) throws SQLException {
return cstmt.getByte(parameterIndex);
}
public void setQueryTimeout(int seconds) throws SQLException {
cstmt.setQueryTimeout(seconds);
}
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
cstmt.setBigDecimal(parameterIndex, x);
}
public short getShort(int parameterIndex) throws SQLException {
return cstmt.getShort(parameterIndex);
}
public void cancel() throws SQLException {
cstmt.cancel();
}
public void setString(int parameterIndex, String x) throws SQLException {
cstmt.setString(parameterIndex, x);
}
public int getInt(int parameterIndex) throws SQLException {
return cstmt.getInt(parameterIndex);
}
public SQLWarning getWarnings() throws SQLException {
return cstmt.getWarnings();
}
public long getLong(int parameterIndex) throws SQLException {
return cstmt.getLong(parameterIndex);
}
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
cstmt.setBytes(parameterIndex, x);
}
public float getFloat(int parameterIndex) throws SQLException {
return cstmt.getFloat(parameterIndex);
}
public void clearWarnings() throws SQLException {
cstmt.clearWarnings();
}
public void setDate(int parameterIndex, Date x) throws SQLException {
cstmt.setDate(parameterIndex, x);
}
public void setCursorName(String name) throws SQLException {
cstmt.setCursorName(name);
}
public double getDouble(int parameterIndex) throws SQLException {
return cstmt.getDouble(parameterIndex);
}
public void setTime(int parameterIndex, Time x) throws SQLException {
cstmt.setTime(parameterIndex, x);
}
@Deprecated
public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {
return cstmt.getBigDecimal(parameterIndex, scale);
}
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
cstmt.setTimestamp(parameterIndex, x);
}
public boolean execute(String sql) throws SQLException {
return cstmt.execute(sql);
}
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
cstmt.setAsciiStream(parameterIndex, x, length);
}
public byte[] getBytes(int parameterIndex) throws SQLException {
return cstmt.getBytes(parameterIndex);
}
public Date getDate(int parameterIndex) throws SQLException {
return cstmt.getDate(parameterIndex);
}
public ResultSet getResultSet() throws SQLException {
return cstmt.getResultSet();
}
@Deprecated
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
cstmt.setUnicodeStream(parameterIndex, x, length);
}
public Time getTime(int parameterIndex) throws SQLException {
return cstmt.getTime(parameterIndex);
}
public int getUpdateCount() throws SQLException {
return cstmt.getUpdateCount();
}
public Timestamp getTimestamp(int parameterIndex) throws SQLException {
return cstmt.getTimestamp(parameterIndex);
}
public boolean getMoreResults() throws SQLException {
return cstmt.getMoreResults();
}
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
cstmt.setBinaryStream(parameterIndex, x, length);
}
public Object getObject(int parameterIndex) throws SQLException {
return cstmt.getObject(parameterIndex);
}
public void setFetchDirection(int direction) throws SQLException {
cstmt.setFetchDirection(direction);
}
public void clearParameters() throws SQLException {
cstmt.clearParameters();
}
public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
return cstmt.getBigDecimal(parameterIndex);
}
public int getFetchDirection() throws SQLException {
return cstmt.getFetchDirection();
}
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
cstmt.setObject(parameterIndex, x, targetSqlType);
}
public Object getObject(int parameterIndex, Map<String, Class<?>> map) throws SQLException {
return cstmt.getObject(parameterIndex, map);
}
public void setFetchSize(int rows) throws SQLException {
cstmt.setFetchSize(rows);
}
public int getFetchSize() throws SQLException {
return cstmt.getFetchSize();
}
public void setObject(int parameterIndex, Object x) throws SQLException {
cstmt.setObject(parameterIndex, x);
}
public Ref getRef(int parameterIndex) throws SQLException {
return cstmt.getRef(parameterIndex);
}
public int getResultSetConcurrency() throws SQLException {
return cstmt.getResultSetConcurrency();
}
public Blob getBlob(int parameterIndex) throws SQLException {
return cstmt.getBlob(parameterIndex);
}
public int getResultSetType() throws SQLException {
return cstmt.getResultSetType();
}
public void addBatch(String sql) throws SQLException {
cstmt.addBatch(sql);
}
public Clob getClob(int parameterIndex) throws SQLException {
return cstmt.getClob(parameterIndex);
}
public void clearBatch() throws SQLException {
cstmt.clearBatch();
}
public boolean execute() throws SQLException {
return cstmt.execute();
}
public Array getArray(int parameterIndex) throws SQLException {
return cstmt.getArray(parameterIndex);
}
public int[] executeBatch() throws SQLException {
return cstmt.executeBatch();
}
public Date getDate(int parameterIndex, Calendar cal) throws SQLException {
return cstmt.getDate(parameterIndex, cal);
}
public void addBatch() throws SQLException {
cstmt.addBatch();
}
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
cstmt.setCharacterStream(parameterIndex, reader, length);
}
public Time getTime(int parameterIndex, Calendar cal) throws SQLException {
return cstmt.getTime(parameterIndex, cal);
}
public void setRef(int parameterIndex, Ref x) throws SQLException {
cstmt.setRef(parameterIndex, x);
}
public Connection getConnection() throws SQLException {
return cstmt.getConnection();
}
public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {
return cstmt.getTimestamp(parameterIndex, cal);
}
public void setBlob(int parameterIndex, Blob x) throws SQLException {
cstmt.setBlob(parameterIndex, x);
}
public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {
cstmt.registerOutParameter(parameterIndex, sqlType, typeName);
}
public void setClob(int parameterIndex, Clob x) throws SQLException {
cstmt.setClob(parameterIndex, x);
}
public boolean getMoreResults(int current) throws SQLException {
return cstmt.getMoreResults(current);
}
public void setArray(int parameterIndex, Array x) throws SQLException {
cstmt.setArray(parameterIndex, x);
}
public ResultSetMetaData getMetaData() throws SQLException {
return cstmt.getMetaData();
}
public void registerOutParameter(String parameterName, int sqlType) throws SQLException {
cstmt.registerOutParameter(parameterName, sqlType);
}
public ResultSet getGeneratedKeys() throws SQLException {
return cstmt.getGeneratedKeys();
}
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
cstmt.setDate(parameterIndex, x, cal);
}
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return cstmt.executeUpdate(sql, autoGeneratedKeys);
}
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
cstmt.setTime(parameterIndex, x, cal);
}
public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {
cstmt.registerOutParameter(parameterName, sqlType, scale);
}
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
return cstmt.executeUpdate(sql, columnIndexes);
}
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
cstmt.setTimestamp(parameterIndex, x, cal);
}
public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {
cstmt.registerOutParameter(parameterName, sqlType, typeName);
}
public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
cstmt.setNull(parameterIndex, sqlType, typeName);
}
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
return cstmt.executeUpdate(sql, columnNames);
}
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
return cstmt.execute(sql, autoGeneratedKeys);
}
public URL getURL(int parameterIndex) throws SQLException {
return cstmt.getURL(parameterIndex);
}
public void setURL(int parameterIndex, URL x) throws SQLException {
cstmt.setURL(parameterIndex, x);
}
public void setURL(String parameterName, URL val) throws SQLException {
cstmt.setURL(parameterName, val);
}
public ParameterMetaData getParameterMetaData() throws SQLException {
return cstmt.getParameterMetaData();
}
public void setNull(String parameterName, int sqlType) throws SQLException {
cstmt.setNull(parameterName, sqlType);
}
public void setRowId(int parameterIndex, RowId x) throws SQLException {
cstmt.setRowId(parameterIndex, x);
}
public boolean execute(String sql, int[] columnIndexes) throws SQLException {
return cstmt.execute(sql, columnIndexes);
}
public void setBoolean(String parameterName, boolean x) throws SQLException {
cstmt.setBoolean(parameterName, x);
}
public void setNString(int parameterIndex, String value) throws SQLException {
cstmt.setNString(parameterIndex, value);
}
public void setByte(String parameterName, byte x) throws SQLException {
cstmt.setByte(parameterName, x);
}
public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
cstmt.setNCharacterStream(parameterIndex, value, length);
}
public void setShort(String parameterName, short x) throws SQLException {
cstmt.setShort(parameterName, x);
}
public void setInt(String parameterName, int x) throws SQLException {
cstmt.setInt(parameterName, x);
}
public boolean execute(String sql, String[] columnNames) throws SQLException {
return cstmt.execute(sql, columnNames);
}
public void setNClob(int parameterIndex, NClob value) throws SQLException {
cstmt.setNClob(parameterIndex, value);
}
public void setLong(String parameterName, long x) throws SQLException {
cstmt.setLong(parameterName, x);
}
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
cstmt.setClob(parameterIndex, reader, length);
}
public void setFloat(String parameterName, float x) throws SQLException {
cstmt.setFloat(parameterName, x);
}
public void setDouble(String parameterName, double x) throws SQLException {
cstmt.setDouble(parameterName, x);
}
public int getResultSetHoldability() throws SQLException {
return cstmt.getResultSetHoldability();
}
public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
cstmt.setBlob(parameterIndex, inputStream, length);
}
public boolean isClosed() throws SQLException {
return cstmt.isClosed();
}
public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {
cstmt.setBigDecimal(parameterName, x);
}
public void setPoolable(boolean poolable) throws SQLException {
cstmt.setPoolable(poolable);
}
public void setString(String parameterName, String x) throws SQLException {
cstmt.setString(parameterName, x);
}
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
cstmt.setNClob(parameterIndex, reader, length);
}
public boolean isPoolable() throws SQLException {
return cstmt.isPoolable();
}
public void setBytes(String parameterName, byte[] x) throws SQLException {
cstmt.setBytes(parameterName, x);
}
public void setDate(String parameterName, Date x) throws SQLException {
cstmt.setDate(parameterName, x);
}
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
cstmt.setSQLXML(parameterIndex, xmlObject);
}
public void setTime(String parameterName, Time x) throws SQLException {
cstmt.setTime(parameterName, x);
}
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
cstmt.setObject(parameterIndex, x, targetSqlType, scaleOrLength);
}
public void setTimestamp(String parameterName, Timestamp x) throws SQLException {
cstmt.setTimestamp(parameterName, x);
}
public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {
cstmt.setAsciiStream(parameterName, x, length);
}
public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {
cstmt.setBinaryStream(parameterName, x, length);
}
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
cstmt.setAsciiStream(parameterIndex, x, length);
}
public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {
cstmt.setObject(parameterName, x, targetSqlType, scale);
}
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
cstmt.setBinaryStream(parameterIndex, x, length);
}
public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
cstmt.setCharacterStream(parameterIndex, reader, length);
}
public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {
cstmt.setObject(parameterName, x, targetSqlType);
}
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
cstmt.setAsciiStream(parameterIndex, x);
}
public void setObject(String parameterName, Object x) throws SQLException {
cstmt.setObject(parameterName, x);
}
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
cstmt.setBinaryStream(parameterIndex, x);
}
public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException {
cstmt.setCharacterStream(parameterName, reader, length);
}
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
cstmt.setCharacterStream(parameterIndex, reader);
}
public void setDate(String parameterName, Date x, Calendar cal) throws SQLException {
cstmt.setDate(parameterName, x, cal);
}
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
cstmt.setNCharacterStream(parameterIndex, value);
}
public void setTime(String parameterName, Time x, Calendar cal) throws SQLException {
cstmt.setTime(parameterName, x, cal);
}
public void setClob(int parameterIndex, Reader reader) throws SQLException {
cstmt.setClob(parameterIndex, reader);
}
public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {
cstmt.setTimestamp(parameterName, x, cal);
}
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
cstmt.setBlob(parameterIndex, inputStream);
}
public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {
cstmt.setNull(parameterName, sqlType, typeName);
}
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
cstmt.setNClob(parameterIndex, reader);
}
public String getString(String parameterName) throws SQLException {
return cstmt.getString(parameterName);
}
public boolean getBoolean(String parameterName) throws SQLException {
return cstmt.getBoolean(parameterName);
}
public byte getByte(String parameterName) throws SQLException {
return cstmt.getByte(parameterName);
}
public short getShort(String parameterName) throws SQLException {
return cstmt.getShort(parameterName);
}
public int getInt(String parameterName) throws SQLException {
return cstmt.getInt(parameterName);
}
public long getLong(String parameterName) throws SQLException {
return cstmt.getLong(parameterName);
}
public float getFloat(String parameterName) throws SQLException {
return cstmt.getFloat(parameterName);
}
public double getDouble(String parameterName) throws SQLException {
return cstmt.getDouble(parameterName);
}
public byte[] getBytes(String parameterName) throws SQLException {
return cstmt.getBytes(parameterName);
}
public Date getDate(String parameterName) throws SQLException {
return cstmt.getDate(parameterName);
}
public Time getTime(String parameterName) throws SQLException {
return cstmt.getTime(parameterName);
}
public Timestamp getTimestamp(String parameterName) throws SQLException {
return cstmt.getTimestamp(parameterName);
}
public Object getObject(String parameterName) throws SQLException {
return cstmt.getObject(parameterName);
}
public BigDecimal getBigDecimal(String parameterName) throws SQLException {
return cstmt.getBigDecimal(parameterName);
}
public Object getObject(String parameterName, Map<String, Class<?>> map) throws SQLException {
return cstmt.getObject(parameterName, map);
}
public Ref getRef(String parameterName) throws SQLException {
return cstmt.getRef(parameterName);
}
public Blob getBlob(String parameterName) throws SQLException {
return cstmt.getBlob(parameterName);
}
public Clob getClob(String parameterName) throws SQLException {
return cstmt.getClob(parameterName);
}
public Array getArray(String parameterName) throws SQLException {
return cstmt.getArray(parameterName);
}
public Date getDate(String parameterName, Calendar cal) throws SQLException {
return cstmt.getDate(parameterName, cal);
}
public Time getTime(String parameterName, Calendar cal) throws SQLException {
return cstmt.getTime(parameterName, cal);
}
public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {
return cstmt.getTimestamp(parameterName, cal);
}
public URL getURL(String parameterName) throws SQLException {
return cstmt.getURL(parameterName);
}
public RowId getRowId(int parameterIndex) throws SQLException {
return cstmt.getRowId(parameterIndex);
}
public RowId getRowId(String parameterName) throws SQLException {
return cstmt.getRowId(parameterName);
}
public void setRowId(String parameterName, RowId x) throws SQLException {
cstmt.setRowId(parameterName, x);
}
public void setNString(String parameterName, String value) throws SQLException {
cstmt.setNString(parameterName, value);
}
public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {
cstmt.setNCharacterStream(parameterName, value, length);
}
public void setNClob(String parameterName, NClob value) throws SQLException {
cstmt.setNClob(parameterName, value);
}
public void setClob(String parameterName, Reader reader, long length) throws SQLException {
cstmt.setClob(parameterName, reader, length);
}
public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {
cstmt.setBlob(parameterName, inputStream, length);
}
public void setNClob(String parameterName, Reader reader, long length) throws SQLException {
cstmt.setNClob(parameterName, reader, length);
}
public NClob getNClob(int parameterIndex) throws SQLException {
return cstmt.getNClob(parameterIndex);
}
public NClob getNClob(String parameterName) throws SQLException {
return cstmt.getNClob(parameterName);
}
public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
cstmt.setSQLXML(parameterName, xmlObject);
}
public SQLXML getSQLXML(int parameterIndex) throws SQLException {
return cstmt.getSQLXML(parameterIndex);
}
public SQLXML getSQLXML(String parameterName) throws SQLException {
return cstmt.getSQLXML(parameterName);
}
public String getNString(int parameterIndex) throws SQLException {
return cstmt.getNString(parameterIndex);
}
public String getNString(String parameterName) throws SQLException {
return cstmt.getNString(parameterName);
}
public Reader getNCharacterStream(int parameterIndex) throws SQLException {
return cstmt.getNCharacterStream(parameterIndex);
}
public Reader getNCharacterStream(String parameterName) throws SQLException {
return cstmt.getNCharacterStream(parameterName);
}
public Reader getCharacterStream(int parameterIndex) throws SQLException {
return cstmt.getCharacterStream(parameterIndex);
}
public Reader getCharacterStream(String parameterName) throws SQLException {
return cstmt.getCharacterStream(parameterName);
}
public void setBlob(String parameterName, Blob x) throws SQLException {
cstmt.setBlob(parameterName, x);
}
public void setClob(String parameterName, Clob x) throws SQLException {
cstmt.setClob(parameterName, x);
}
public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {
cstmt.setAsciiStream(parameterName, x, length);
}
public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {
cstmt.setBinaryStream(parameterName, x, length);
}
public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException {
cstmt.setCharacterStream(parameterName, reader, length);
}
public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
cstmt.setAsciiStream(parameterName, x);
}
public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
cstmt.setBinaryStream(parameterName, x);
}
public void setCharacterStream(String parameterName, Reader reader) throws SQLException {
cstmt.setCharacterStream(parameterName, reader);
}
public void setNCharacterStream(String parameterName, Reader value) throws SQLException {
cstmt.setNCharacterStream(parameterName, value);
}
public void setClob(String parameterName, Reader reader) throws SQLException {
cstmt.setClob(parameterName, reader);
}
public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
cstmt.setBlob(parameterName, inputStream);
}
public void setNClob(String parameterName, Reader reader) throws SQLException {
cstmt.setNClob(parameterName, reader);
}
public CallableStatementWrapper(CallableStatement cstmt) {
super(cstmt);
this.cstmt = cstmt;
}
}
/**
* $RCSfile$
* $Revision: 37 $
* $Date: 2004-10-20 23:08:43 -0700 (Wed, 20 Oct 2004) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import java.sql.*;
import java.math.BigDecimal;
import java.io.InputStream;
import java.io.Reader;
import java.util.Calendar;
import java.net.URL;
/**
* An implementation of the PreparedStatement interface that wraps an underlying
* PreparedStatement object.
*
* @author Gaston Dombiak
*/
public abstract class PreparedStatementWrapper extends StatementWrapper
implements PreparedStatement {
protected PreparedStatement pstmt;
public PreparedStatementWrapper(PreparedStatement pstmt) {
super(pstmt);
this.pstmt = pstmt;
}
public ResultSet executeQuery() throws SQLException {
return pstmt.executeQuery();
}
public int executeUpdate() throws SQLException {
return pstmt.executeUpdate();
}
public void setNull(int parameterIndex, int sqlType) throws SQLException {
pstmt.setNull(parameterIndex, sqlType);
}
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
pstmt.setBoolean(parameterIndex, x);
}
public void setByte(int parameterIndex, byte x) throws SQLException {
pstmt.setByte(parameterIndex, x);
}
public void setShort(int parameterIndex, short x) throws SQLException {
pstmt.setShort(parameterIndex, x);
}
public void setInt(int parameterIndex, int x) throws SQLException {
pstmt.setInt(parameterIndex, x);
}
public void setLong(int parameterIndex, long x) throws SQLException {
pstmt.setLong(parameterIndex, x);
}
public void setFloat(int parameterIndex, float x) throws SQLException {
pstmt.setFloat(parameterIndex, x);
}
public void setDouble(int parameterIndex, double x) throws SQLException {
pstmt.setDouble(parameterIndex, x);
}
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
pstmt.setBigDecimal(parameterIndex, x);
}
public void setString(int parameterIndex, String x) throws SQLException {
pstmt.setString(parameterIndex, x);
}
public void setBytes(int parameterIndex, byte x[]) throws SQLException {
pstmt.setBytes(parameterIndex, x);
}
public void setDate(int parameterIndex, Date x) throws SQLException {
pstmt.setDate(parameterIndex, x);
}
public void setTime(int parameterIndex, Time x) throws SQLException {
pstmt.setTime(parameterIndex, x);
}
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
pstmt.setTimestamp(parameterIndex, x);
}
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setAsciiStream(parameterIndex, x, length);
}
@Deprecated public void setUnicodeStream(int parameterIndex, InputStream x, int length)
throws SQLException {
pstmt.setUnicodeStream(parameterIndex, x, length);
}
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setBinaryStream(parameterIndex, x, length);
}
public void clearParameters() throws SQLException {
pstmt.clearParameters();
}
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
throws SQLException {
pstmt.setObject(parameterIndex, x, targetSqlType, scale);
}
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
pstmt.setObject(parameterIndex, x, targetSqlType);
}
public void setObject(int parameterIndex, Object x) throws SQLException {
pstmt.setObject(parameterIndex, x);
}
public boolean execute() throws SQLException {
return pstmt.execute();
}
public void addBatch() throws SQLException {
pstmt.addBatch();
}
public void setCharacterStream(int parameterIndex, Reader reader, int length)
throws SQLException {
pstmt.setCharacterStream(parameterIndex, reader, length);
}
public void setRef(int i, Ref x) throws SQLException {
pstmt.setRef(i, x);
}
public void setBlob(int i, Blob x) throws SQLException {
pstmt.setBlob(i, x);
}
public void setClob(int i, Clob x) throws SQLException {
pstmt.setClob(i, x);
}
public void setArray(int i, Array x) throws SQLException {
pstmt.setArray(i, x);
}
public ResultSetMetaData getMetaData() throws SQLException {
return pstmt.getMetaData();
}
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
pstmt.setDate(parameterIndex, x, cal);
}
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
pstmt.setTime(parameterIndex, x, cal);
}
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
pstmt.setTimestamp(parameterIndex, x, cal);
}
public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException {
pstmt.setNull(paramIndex, sqlType, typeName);
}
public void setURL(int parameterIndex, URL x) throws SQLException {
pstmt.setURL(parameterIndex, x);
}
public ParameterMetaData getParameterMetaData() throws SQLException {
return pstmt.getParameterMetaData();
}
public void setRowId(int parameterIndex, RowId x) throws SQLException {
pstmt.setRowId(parameterIndex, x);
}
public void setNString(int parameterIndex, String value) throws SQLException {
pstmt.setNString(parameterIndex, value);
}
public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
pstmt.setNCharacterStream(parameterIndex, value, length);
}
public void setNClob(int parameterIndex, NClob value) throws SQLException {
pstmt.setNClob(parameterIndex, value);
}
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
pstmt.setClob(parameterIndex, reader, length);
}
public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
pstmt.setBlob(parameterIndex, inputStream, length);
}
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
pstmt.setNClob(parameterIndex, reader, length);
}
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
pstmt.setSQLXML(parameterIndex, xmlObject);
}
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
pstmt.setAsciiStream(parameterIndex, x, length);
}
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
pstmt.setBinaryStream(parameterIndex, x, length);
}
public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
pstmt.setCharacterStream(parameterIndex, reader, length);
}
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
pstmt.setAsciiStream(parameterIndex, x);
}
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
pstmt.setBinaryStream(parameterIndex, x);
}
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
pstmt.setCharacterStream(parameterIndex, reader);
}
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
pstmt.setNCharacterStream(parameterIndex, value);
}
public void setClob(int parameterIndex, Reader reader) throws SQLException {
pstmt.setClob(parameterIndex, reader);
}
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
pstmt.setBlob(parameterIndex, inputStream);
}
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
pstmt.setNClob(parameterIndex, reader);
}
}
/**
* $RCSfile$
* $Revision: 1113 $
* $Date: 2005-03-10 09:53:39 -0800 (Thu, 10 Mar 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import java.sql.*;
import java.util.Hashtable;
import java.util.Map;
/**
* Wraps a Connection object and collects statistics about the database queries
* that are performed.<p>
* <p/>
* Statistics of the profiled Connections can be obtained from the static
* methods of this class. Instances of this class are the actual wrappers that
* perform profiling.
*
* @author Jive Software
*/
public class ProfiledConnection extends AbstractConnection {
public static enum Type {
/**
* Constant for SELECT database queries.
*/
select,
/**
* Constant for UPDATE database queries.
*/
update,
/**
* Constant for INSERT database queries.
*/
insert,
/**
* Constant for DELETE database queries.
*/
delete
}
private static long startInsertTime = 0;
private static long startUpdateTime = 0;
private static long startSelectTime = 0;
private static long startDeleteTime = 0;
private static long endInsertTime = 0;
private static long endUpdateTime = 0;
private static long endSelectTime = 0;
private static long endDeleteTime = 0;
private static long insertCount = 0;
private static long updateCount = 0;
private static long selectCount = 0;
private static long deleteCount = 0;
private static long totalInsertTime = 0;
private static long totalUpdateTime = 0;
private static long totalSelectTime = 0;
private static long totalDeleteTime = 0;
private static Map<String, ProfiledConnectionEntry> insertQueries =
new Hashtable<String, ProfiledConnectionEntry>();
private static Map<String, ProfiledConnectionEntry> updateQueries =
new Hashtable<String, ProfiledConnectionEntry>();
private static Map<String, ProfiledConnectionEntry> selectQueries =
new Hashtable<String, ProfiledConnectionEntry>();
private static Map<String, ProfiledConnectionEntry> deleteQueries =
new Hashtable<String, ProfiledConnectionEntry>();
/**
* Start profiling.
*/
public static void start() {
long now = System.currentTimeMillis();
startInsertTime = startUpdateTime = startSelectTime = startDeleteTime = now;
}
/**
* Stop profiling.
*/
public static void stop() {
endInsertTime = endUpdateTime = endSelectTime = endDeleteTime = 0;
}
/**
* Returns the total number database queries of a particular type performed.
* Valid types are ProfiledConnection.SELECT, ProfiledConnection.UPDATE,
* ProfiledConnection.INSERT, and ProfiledConnection.DELETE.
*
* @param type the type of query to get the count for.
* @return the number queries of type <tt>type</tt> performed.
*/
public static long getQueryCount(Type type) {
switch (type) {
case select:
return selectCount;
case update:
return updateCount;
case insert:
return insertCount;
case delete:
return deleteCount;
default:
throw new IllegalArgumentException("Invalid type");
}
}
/**
* Adds a query.
*
* @param type the type of the query.
* @param sql the insert sql string.
* @param time the length of time the query took in milliseconds
*/
public static void addQuery(Type type, String sql, long time) {
// Do nothing if we didn't receive a sql statement
if (sql == null || sql.equals("")) {
return;
}
// clean up sql to insert spaces after every ','
sql = reformatQuery(sql);
// remove values from query
sql = removeQueryValues(sql);
ProfiledConnectionEntry entry;
switch (type) {
case select:
selectCount++;
totalSelectTime += time;
entry = selectQueries.get(sql);
if (entry == null) {
entry = new ProfiledConnectionEntry(sql);
selectQueries.put(sql, entry);
}
break;
case update:
updateCount++;
totalUpdateTime += time;
entry = updateQueries.get(sql);
if (entry == null) {
entry = new ProfiledConnectionEntry(sql);
updateQueries.put(sql, entry);
}
break;
case insert:
insertCount++;
totalInsertTime += time;
entry = insertQueries.get(sql);
if (entry == null) {
entry = new ProfiledConnectionEntry(sql);
insertQueries.put(sql, entry);
}
break;
case delete:
deleteCount++;
totalDeleteTime += time;
entry = deleteQueries.get(sql);
if (entry == null) {
entry = new ProfiledConnectionEntry(sql);
deleteQueries.put(sql, entry);
}
break;
default:
throw new IllegalArgumentException("Invalid type");
}
entry.count++;
entry.totalTime += time;
}
/**
* Returns the average number of queries of a certain type that have been
* performed per second since profiling started. If profiling has been
* stopped, that moment in time is used for the calculation. Otherwise,
* the current moment in time is used.
*
* @param type the type of database query to check.
* @return the average number of queries of a certain typed performed per
* second.
*/
public static double getQueriesPerSecond(Type type) {
long count, start, end;
switch (type) {
case select:
count = selectCount;
start = startSelectTime;
end = endSelectTime;
break;
case update:
count = updateCount;
start = startUpdateTime;
end = endUpdateTime;
break;
case insert:
count = insertCount;
start = startInsertTime;
end = endInsertTime;
break;
case delete:
count = deleteCount;
start = startDeleteTime;
end = endDeleteTime;
break;
default:
throw new IllegalArgumentException("Invalid type");
}
// if no queries yet, return 0;
if (count == 0) {
return 0;
}
// If the profiling hasn't been stopped yet, we want to give
// profiling values up to the current time instead.
if (end == 0) {
end = System.currentTimeMillis();
}
// Compute the number of seconds
double time = (end - start) / 1000.0;
// Finally, return the average.
return count / time;
}
/**
* Returns the average amount of time spent executing the specified type
* of query.
*
* @param type the type of query.
* @return a double representing the average time spent executing the type
* of query.
*/
public static double getAverageQueryTime(Type type) {
long time, count;
switch (type) {
case select:
count = selectCount;
time = totalSelectTime;
break;
case update:
count = updateCount;
time = totalUpdateTime;
break;
case insert:
count = insertCount;
time = totalInsertTime;
break;
case delete:
count = deleteCount;
time = totalDeleteTime;
break;
default:
throw new IllegalArgumentException("Invalid type");
}
if (count != 0) {
return time / (double)count;
}
else {
return 0.0;
}
}
/**
* Returns the total amount of time in milliseconds spent doing a particular
* type of query. Note that this isn't necessarily representative of actual real
* time since db queries often occur in parallel.
*
* @param type the type of query to check.
* @return the number of milliseconds spent executing the specified type of
* query.
*/
public static long getTotalQueryTime(Type type) {
switch (type) {
case select:
return totalSelectTime;
case update:
return totalUpdateTime;
case insert:
return totalInsertTime;
case delete:
return totalDeleteTime;
default:
throw new IllegalArgumentException("Invalid type");
}
}
/**
* Returns an array of sorted queries (as ProfiledConnectionEntry objects) by type
*
* @param type the type of query to check
* @param sortByTime sort the resulting list by Time if true,
* otherwise sort by count if false (default)
* @return an array of ProfiledConnectionEntry objects
*/
public static ProfiledConnectionEntry[] getSortedQueries(Type type, boolean sortByTime) {
Map<String, ProfiledConnectionEntry> queries;
switch (type) {
case select:
queries = selectQueries;
break;
case update:
queries = updateQueries;
break;
case insert:
queries = insertQueries;
break;
case delete:
queries = deleteQueries;
break;
default:
throw new IllegalArgumentException("Invalid type");
}
// No queries, return null
if (queries.isEmpty()) {
return null;
}
ProfiledConnectionEntry [] result = queries.values().toArray(
new ProfiledConnectionEntry[queries.size()]);
quickSort(result, sortByTime, 0, result.length - 1);
return result;
}
/**
* Reset all statistics.
*/
public static void resetStatistics() {
startInsertTime = startUpdateTime = startSelectTime = startDeleteTime = 0;
endInsertTime = endUpdateTime = endSelectTime = endDeleteTime = 0;
insertCount = updateCount = selectCount = deleteCount = 0;
totalInsertTime = totalUpdateTime = totalSelectTime = totalDeleteTime = 0;
insertQueries.clear();
updateQueries.clear();
selectQueries.clear();
deleteQueries.clear();
}
/**
* @param entries entries
* @param sortByTime sort by time if true, otherwise sort by count
* @param first first index to sort on. Normally 0
* @param last last index to sort on. Normally length -1
*/
private static void quickSort(ProfiledConnectionEntry[] entries, boolean sortByTime, int first, int last) {
// do nothing if array contains fewer than two elements
if (first >= last || entries.length < 2) {
return;
}
swap(entries, first, (first + last) / 2);
int index = first;
for (int i = first + 1; i <= last; i++) {
if (sortByTime && ((entries[first].totalTime / entries[first].count) < (entries[i].totalTime / entries[i].count))) {
swap(entries, ++index, i);
}
else if (!sortByTime && entries[first].count < entries[i].count) {
swap(entries, ++index, i);
}
}
swap(entries, first, index);
quickSort(entries, sortByTime, first, index - 1);
quickSort(entries, sortByTime, index + 1, last);
}
private static void swap(Object[] list, int i, int j) {
Object tmp = list[i];
list[i] = list[j];
list[j] = tmp;
}
private static String removeQueryValues(String _sql) {
int length = _sql.length();
if (_sql.indexOf("=") == -1) {
return _sql;
}
StringBuilder sql = new StringBuilder(_sql);
boolean inValue = false;
boolean afterEquals = false;
boolean hasQuotes = false;
int startValue = -1;
int endValue = -1;
int charRemoved = 0;
for (int x = 0; x < length; x++) {
char c = _sql.charAt(x);
switch (c) {
case '=':
{
if (!afterEquals) {
afterEquals = true;
}
break;
}
case ' ':
{
if (!hasQuotes && inValue) {
endValue = x;
inValue = false;
hasQuotes = false;
afterEquals = false;
}
break;
}
case '\'':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
hasQuotes = true;
}
else if (afterEquals && inValue && hasQuotes) {
endValue = x + 1;
inValue = false;
hasQuotes = false;
afterEquals = false;
}
break;
}
case '-':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '+':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '0':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '1':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '2':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '3':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '4':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '5':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '6':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '7':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '8':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
case '9':
{
if (afterEquals && !inValue) {
startValue = x;
inValue = true;
}
break;
}
default:
{
if (afterEquals && !inValue) {
afterEquals = false;
}
}
}
if (x == length - 1 && afterEquals) {
endValue = x + 1;
}
if (startValue != -1 && endValue != -1) {
sql.replace(startValue - charRemoved, endValue - charRemoved, "?");
charRemoved += endValue - startValue - 1;
startValue = -1;
endValue = -1;
}
}
return sql.toString();
}
private static String reformatQuery(String _sql) {
int length = _sql.length();
int charAdded = 0;
StringBuilder sql = new StringBuilder(_sql);
for (int x = 0; x < length; x++) {
char c = _sql.charAt(x);
if (c == ',' && x < length - 1 && _sql.charAt(x + 1) != ' ') {
sql.replace(x + charAdded, x + 1 + charAdded, ", ");
charAdded++;
}
}
return sql.toString();
}
//--------------------- Connection Wrapping Code ---------------------//
/**
* Creates a new ProfiledConnection that wraps the specified connection.
*
* @param connection the Connection to wrap and collect stats for.
*/
public ProfiledConnection(Connection connection) {
super(connection);
}
public void close() throws SQLException {
// Close underlying connection.
if (connection != null) {
connection.close();
}
}
public Statement createStatement() throws SQLException {
// Returned a TimedStatement so that we can do db timings.
return new TimedStatement(connection.createStatement());
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
// Returned a TimedPreparedStatement so that we can do db timings.
return new TimedPreparedStatement(connection.prepareStatement(sql), sql);
}
public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
return new TimedStatement(connection.createStatement(resultSetType,
resultSetConcurrency));
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return new TimedPreparedStatement(connection.prepareStatement(sql, resultSetType, resultSetConcurrency), sql);
}
public CallableStatement prepareCall(String sql) throws SQLException {
return new TimedCallableStatement(connection.prepareCall(sql), sql);
}
public CallableStatement prepareCall(String sql, int i, int i1) throws SQLException {
return new TimedCallableStatement(connection.prepareCall(sql, i, i1), sql);
}
/**
* An implementation of the Statement interface that wraps an underlying
* Statement object and performs timings of the database queries. The class
* does not handle batch queries but should generally work otherwise.
*/
class TimedStatement extends StatementWrapper {
private Statement stmt;
/**
* Creates a new TimedStatement that wraps <tt>stmt</tt>.
*
* @param stmt the statement.
*/
public TimedStatement(Statement stmt) {
super(stmt);
this.stmt = stmt;
}
public boolean execute(String sql) throws SQLException {
long t1 = System.currentTimeMillis();
boolean result = stmt.execute(sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, sql, t2 - t1);
}
else {
addQuery(Type.select, sql, t2 - t1);
}
return result;
}
public ResultSet executeQuery(String sql) throws SQLException {
long t1 = System.currentTimeMillis();
ResultSet result = stmt.executeQuery(sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, sql, t2 - t1);
}
else {
addQuery(Type.select, sql, t2 - t1);
}
return result;
}
public int executeUpdate(String sql) throws SQLException {
long t1 = System.currentTimeMillis();
int result = stmt.executeUpdate(sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, sql, t2 - t1);
}
else {
addQuery(Type.select, sql, t2 - t1);
}
return result;
}
}
/**
* An implementation of the PreparedStatement interface that wraps an
* underlying PreparedStatement object and performs timings of the database
* queries.
*/
class TimedPreparedStatement extends PreparedStatementWrapper {
private String sql;
private Type type = Type.select;
public TimedPreparedStatement(PreparedStatement pstmt, String sql) {
super(pstmt);
this.sql = sql;
// determine the type of query
String sqlL = sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
type = Type.insert;
}
else if (sqlL.startsWith("update")) {
type = Type.update;
}
else if (sqlL.startsWith("delete")) {
type = Type.delete;
}
else {
type = Type.select;
}
}
public boolean execute() throws SQLException {
// Perform timing of this method.
long t1 = System.currentTimeMillis();
boolean result = pstmt.execute();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
/*
* This is one of the methods that we wish to time
*/
public ResultSet executeQuery() throws SQLException {
long t1 = System.currentTimeMillis();
ResultSet result = pstmt.executeQuery();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
/*
* This is one of the methods that we wish to time
*/
public int executeUpdate() throws SQLException {
long t1 = System.currentTimeMillis();
int result = pstmt.executeUpdate();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
// The following methods are from the Statement class - the
// SuperInterface of PreparedStatement
// without these this class won't compile
public boolean execute(String _sql) throws SQLException {
long t1 = System.currentTimeMillis();
boolean result = pstmt.execute(_sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = _sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, _sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, _sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, _sql, t2 - t1);
}
else {
addQuery(Type.select, _sql, t2 - t1);
}
return result;
}
public int[] executeBatch() throws SQLException {
long t1 = System.currentTimeMillis();
int[] result = pstmt.executeBatch();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
public ResultSet executeQuery(String _sql) throws SQLException {
long t1 = System.currentTimeMillis();
ResultSet result = pstmt.executeQuery(_sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = _sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, _sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, _sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, _sql, t2 - t1);
}
else {
addQuery(Type.select, _sql, t2 - t1);
}
return result;
}
public int executeUpdate(String _sql) throws SQLException {
long t1 = System.currentTimeMillis();
int result = pstmt.executeUpdate(_sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = _sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, _sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, _sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, _sql, t2 - t1);
}
else {
addQuery(Type.select, _sql, t2 - t1);
}
return result;
}
}
/**
* An implementation of the CallableStatement interface that wraps an
* underlying CallableStatement object and performs timings of the database
* queries.
*/
class TimedCallableStatement extends CallableStatementWrapper {
private String sql;
private Type type = Type.select;
public TimedCallableStatement(CallableStatement cstmt, String sql) {
super(cstmt);
this.sql = sql;
// determine the type of query
String sqlL = sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
type = Type.insert;
}
else if (sqlL.startsWith("update")) {
type = Type.update;
}
else if (sqlL.startsWith("delete")) {
type = Type.delete;
}
else {
type = Type.select;
}
}
public boolean execute() throws SQLException {
// Perform timing of this method.
long t1 = System.currentTimeMillis();
boolean result = cstmt.execute();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
/*
* This is one of the methods that we wish to time
*/
public ResultSet executeQuery() throws SQLException {
long t1 = System.currentTimeMillis();
ResultSet result = cstmt.executeQuery();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
/*
* This is one of the methods that we wish to time
*/
public int executeUpdate() throws SQLException {
long t1 = System.currentTimeMillis();
int result = cstmt.executeUpdate();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
// The following methods are from the Statement class - the
// SuperInterface of PreparedStatement
// without these this class won't compile
public boolean execute(String _sql) throws SQLException {
long t1 = System.currentTimeMillis();
boolean result = cstmt.execute(_sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = _sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, _sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, _sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, _sql, t2 - t1);
}
else {
addQuery(Type.select, _sql, t2 - t1);
}
return result;
}
public int[] executeBatch() throws SQLException {
long t1 = System.currentTimeMillis();
int[] result = cstmt.executeBatch();
long t2 = System.currentTimeMillis();
switch (type) {
case select:
addQuery(Type.select, sql, t2 - t1);
break;
case update:
addQuery(Type.update, sql, t2 - t1);
break;
case insert:
addQuery(Type.insert, sql, t2 - t1);
break;
case delete:
addQuery(Type.delete, sql, t2 - t1);
break;
}
return result;
}
public ResultSet executeQuery(String _sql) throws SQLException {
long t1 = System.currentTimeMillis();
ResultSet result = cstmt.executeQuery(_sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = _sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, _sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, _sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, _sql, t2 - t1);
}
else {
addQuery(Type.select, _sql, t2 - t1);
}
return result;
}
public int executeUpdate(String _sql) throws SQLException {
long t1 = System.currentTimeMillis();
int result = cstmt.executeUpdate(_sql);
long t2 = System.currentTimeMillis();
// determine the type of query
String sqlL = _sql.toLowerCase().trim();
if (sqlL.startsWith("insert")) {
addQuery(Type.insert, _sql, t2 - t1);
}
else if (sqlL.startsWith("update")) {
addQuery(Type.update, _sql, t2 - t1);
}
else if (sqlL.startsWith("delete")) {
addQuery(Type.delete, _sql, t2 - t1);
}
else {
addQuery(Type.select, _sql, t2 - t1);
}
return result;
}
}
}
/**
* $RCSfile$
* $Revision: 37 $
* $Date: 2004-10-20 23:08:43 -0700 (Wed, 20 Oct 2004) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
/**
* Simple class for tracking profiling stats for individual SQL queries.
*
* @author Jive Software
*/
public class ProfiledConnectionEntry {
/**
* The SQL query.
*/
public String sql;
/**
* Number of times the query has been executed.
*/
public int count;
/**
* The total time spent executing the query (in milliseconds).
*/
public int totalTime;
public ProfiledConnectionEntry(String sql) {
this.sql = sql;
count = 0;
totalTime = 0;
}
}
/**
* $RCSfile$
* $Revision: 37 $
* $Date: 2004-10-20 23:08:43 -0700 (Wed, 20 Oct 2004) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import java.sql.*;
/**
* An implementation of the Statement interface that wraps an underlying
* Statement object.
*
* @author Gaston Dombiak
*/
public abstract class StatementWrapper implements Statement {
protected Statement stmt;
/**
* Creates a new StatementWrapper that wraps <tt>stmt</tt>.
*
* @param stmt
*/
public StatementWrapper(Statement stmt) {
this.stmt = stmt;
}
public ResultSet executeQuery(String sql) throws SQLException {
return stmt.executeQuery(sql);
}
public int executeUpdate(String sql) throws SQLException {
return stmt.executeUpdate(sql);
}
public void close() throws SQLException {
stmt.close();
}
public int getMaxFieldSize() throws SQLException {
return stmt.getMaxFieldSize();
}
public void setMaxFieldSize(int max) throws SQLException {
stmt.setMaxFieldSize(max);
}
public int getMaxRows() throws SQLException {
return stmt.getMaxRows();
}
public void setMaxRows(int max) throws SQLException {
stmt.setMaxRows(max);
}
public void setEscapeProcessing(boolean enable) throws SQLException {
stmt.setEscapeProcessing(enable);
}
public int getQueryTimeout() throws SQLException {
return stmt.getQueryTimeout();
}
public void setQueryTimeout(int seconds) throws SQLException {
stmt.setQueryTimeout(seconds);
}
public void cancel() throws SQLException {
stmt.cancel();
}
public SQLWarning getWarnings() throws SQLException {
return stmt.getWarnings();
}
public void clearWarnings() throws SQLException {
stmt.clearWarnings();
}
public void setCursorName(String name) throws SQLException {
stmt.setCursorName(name);
}
public boolean execute(String sql) throws SQLException {
return stmt.execute(sql);
}
public ResultSet getResultSet() throws SQLException {
return stmt.getResultSet();
}
public int getUpdateCount() throws SQLException {
return stmt.getUpdateCount();
}
public boolean getMoreResults() throws SQLException {
return stmt.getMoreResults();
}
public void setFetchDirection(int direction) throws SQLException {
stmt.setFetchDirection(direction);
}
public int getFetchDirection() throws SQLException {
return stmt.getFetchDirection();
}
public void setFetchSize(int rows) throws SQLException {
stmt.setFetchSize(rows);
}
public int getFetchSize() throws SQLException {
return stmt.getFetchSize();
}
public int getResultSetConcurrency() throws SQLException {
return stmt.getResultSetConcurrency();
}
public int getResultSetType() throws SQLException {
return stmt.getResultSetType();
}
public void addBatch(String sql) throws SQLException {
stmt.addBatch(sql);
}
public void clearBatch() throws SQLException {
stmt.clearBatch();
}
public int[] executeBatch() throws SQLException {
return stmt.executeBatch();
}
public Connection getConnection() throws SQLException {
return stmt.getConnection();
}
public boolean getMoreResults(int current) throws SQLException {
return stmt.getMoreResults(current);
}
public ResultSet getGeneratedKeys() throws SQLException {
return stmt.getGeneratedKeys();
}
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return stmt.executeUpdate(sql, autoGeneratedKeys);
}
public int executeUpdate(String sql, int columnIndexes[]) throws SQLException {
return stmt.executeUpdate(sql, columnIndexes);
}
public int executeUpdate(String sql, String columnNames[]) throws SQLException {
return stmt.executeUpdate(sql, columnNames);
}
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
return stmt.execute(sql, autoGeneratedKeys);
}
public boolean execute(String sql, int columnIndexes[]) throws SQLException {
return stmt.execute(sql, columnIndexes);
}
public boolean execute(String sql, String columnNames[]) throws SQLException {
return stmt.execute(sql, columnNames);
}
public int getResultSetHoldability() throws SQLException {
return stmt.getResultSetHoldability();
}
public <T> T unwrap(Class<T> iface) throws SQLException {
return stmt.unwrap(iface);
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return stmt.isWrapperFor(iface);
}
public boolean isClosed() throws SQLException {
return stmt.isClosed();
}
public void setPoolable(boolean poolable) throws SQLException {
stmt.setPoolable(poolable);
}
public boolean isPoolable() throws SQLException {
return stmt.isPoolable();
}
}
......@@ -8,6 +8,11 @@
<packaging>pom</packaging>
<modules>
<module>xmppserver</module>
<module>dbutil</module>
</modules>
<organization>
<name>Ignite Realtime</name>
<url>http://www.igniterealtime.org</url>
......@@ -143,8 +148,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
......@@ -168,7 +173,20 @@
</plugins>
</build>
<modules>
<module>xmppserver</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xmppserver</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dbutil</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
\ No newline at end of file
......@@ -14,16 +14,31 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<excludes>
<exclude>**/MINAStatCollector.java</exclude>
<exclude>**/org/jivesoftware/openfire/launcher/Launcher.java</exclude>
<exclude>**/org/jivesoftware/openfire/launcher/Uninstaller.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/Admin*.java</exclude>
<exclude>**/XMLProp*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dbutil</artifactId>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
......@@ -65,6 +80,11 @@
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
......@@ -104,12 +124,59 @@
<artifactId>jmdns</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>rome</groupId>
<artifactId>rome</artifactId>
<version>0.9</version>
</dependency>
<dependency>
<groupId>rome</groupId>
<artifactId>rome-fetcher</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler</artifactId>
<version>5.5.15</version>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.15</version>
</dependency>
<dependency>
<groupId>proxool</groupId>
<artifactId>proxool</artifactId>
<version>0.8.3</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>com.atlassian.shaj</groupId>
<artifactId>atlassian-shaj</artifactId>
<version>0.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>atlassian</id>
<url>https://maven.atlassian.com/content/groups/public/</url>
</repository>
</repositories>
</project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment