/*
* (C) Copyright IBM Corp. 2011
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import com.ibm.gaiandb.diags.GDBMessages;
public class GaianDBProcedureUtils extends GaianDBConfig {
// Use PROPRIETARY notice if class contains a main() method, otherwise use COPYRIGHT notice.
public static final String COPYRIGHT_NOTICE = "(c) Copyright IBM Corp. 2011";
private static final Logger logger = new Logger( "GaianDBProcedureUtils", 25 );
// Standard VARCHAR lengths
static final String TSTR = Util.TSTR;
static final String SSTR = Util.SSTR;
static final String MSTR = Util.MSTR;
static final String LSTR = Util.LSTR;
static final String VSTR = Util.VSTR;
static final String XSTR = Util.XSTR;
// Note new api calls must not exceed 20 chars in length as proc name alias is cast to a TSTR for readability/usability
// read only functions and procedures
static final String listspfs = "listspfs";
static final String listapi = "listapi";
static final String listconfig = "listconfig";
static final String listwarnings = "listwarnings";
static final String listwarningsx = "listwarningsx";
static final String listrdbc = "listrdbc";
static final String listlts = "listlts";
static final String listltmatches = "listltmatches";
static final String listds = "listds";
static final String listderbytables = "listderbytables";
static final String listexplain = "listexplain";
static final String listqueries = "listqueries";
static final String listflood = "listflood";
static final String listnodes = "listnodes";
static final String logtail = "logtail";
static final String gpublickey = "gpublickey";
static final String getconfigproperty = "getconfigproperty";
static final String getnodes = "getnodes";
static final String gdb_node = "gdb_node";
static final String getnodecount = "getnodecount";
static final String ltmatch = "ltmatch";
static final String getlts = "getlts";
// General utility functions are missing below (e.g. jhash,...)
// static final Set<String> readOnlySPFs = new HashSet<String>( Arrays.asList(
// listspfs, listapi, listconfig, listwarnings, listwarningsx, listrdbc, listlts, listltmatches, listds, listderbytables, listexplain,
// listflood, listnodes, logtail, gpublickey, getnodes, getnodecount, ltmatch, gdbtrigger, getlts
// ) );
// write + execute functions and procedures
static final String setrdbc = "setrdbc";
static final String setlt = "setlt";
static final String setltforrdbtable = "setltforrdbtable";
static final String setltforfile = "setltforfile";
static final String setltforexcel = "setltforexcel"; // Denis
static final String setltforws = "setltforws";
static final String setltfornode = "setltfornode";
static final String setltconstants = "setltconstants";
static final String setnodeconstants = "setnodeconstants";
static final String setdsrdbtable = "setdsrdbtable";
static final String setdslocalderby = "setdslocalderby";
static final String setdsfile = "setdsfile";
static final String setdsvti = "setdsvti";
static final String setdsexcel = "setdsexcel";
static final String removerdbc = "removerdbc";
static final String removelt = "removelt";
static final String removeds = "removeds";
static final String gconnect = "gconnect";
static final String gconnectx = "gconnectx";
static final String gdisconnect = "gdisconnect";
static final String setminconnections = "setminconnections";
static final String setdiscoveryhosts = "setdiscoveryhosts";
static final String setdiscoveryip = "setdiscoveryip";
static final String setmaxpropagation = "setmaxpropagation";
static final String setmaxpoolsizes = "setmaxpoolsizes";
static final String setmaxcachedrows = "setmaxcachedrows";
static final String setloglevel = "setloglevel";
static final String setsourcelist = "setsourcelist";
static final String setmsgbrokerdetails = "setmsgbrokerdetails";
static final String setconfigproperty = "setconfigproperty";
static final String setConfigProperties = "setConfigProperties";
static final String setaccessclusters = "setaccessclusters";
static final String cancelquery = "cancelquery";
static final String gkill = "gkill";
static final String gkillnodes = "gkillnodes";
static final String gkillall = "gkillall";
static final String addgateway = "addgateway";
static final String removegateway = "removegateway";
static final String setuser = "setuser";
static final String removeuser = "removeuser";
private static final Set<String> configurationAPIs = new HashSet<String>( Arrays.asList(
setrdbc, setlt, setltforrdbtable, setltforfile, setltforexcel, setltfornode, setltconstants, setnodeconstants,
setdsrdbtable, setdslocalderby, setdsfile, setdsvti, setdsexcel, removerdbc, removelt, removeds, gconnect,gconnectx, gdisconnect,
setminconnections, setdiscoveryhosts, setdiscoveryip, setmaxpropagation, setmaxpoolsizes,
setmaxcachedrows, setloglevel, setsourcelist, setmsgbrokerdetails, setconfigproperty, setaccessclusters, gkill, gkillnodes, gkillall,
addgateway, removegateway, setuser, removeuser
) );
// Utility ResultSet request identifiers
static final String FILESTATS = "FILESTATS";
// private static void logEnteredMsg( String spf ) {
// logEnteredMsg(spf, null);
// }
static void logEnteredMsg( String spf, List<String> args ) {
if ( null == args ) args = Arrays.asList();
StringBuffer sb = new StringBuffer("(");
Iterator<String> i = args.iterator();
if ( i.hasNext() ) sb.append("'" + i.next() + "'");
while ( i.hasNext() ) sb.append(", '" + i.next() + "'");
sb.append(')');
String prefix = Logger.sdf.format(new Date(System.currentTimeMillis())) + " ---------------> ";
logger.logImportant( Logger.HORIZONTAL_RULE + "\n" + prefix + "API call: " + spf + sb + "\n");
}
static void apiStart( String spf ) throws Exception {
apiStart(spf, null);
}
static void apiStart( String spf, List<String> args ) throws Exception {
logEnteredMsg( spf, args );
if ( !isAllowedAPIConfiguration() && configurationAPIs.contains(spf) ) {
String warning = "SQL API command '"+spf+"' is not allowed. To allow configuration management via the SQL API, set this property in " +
getConfigFileName() + ": " + ALLOW_SQL_API_CONFIGURATION + "=TRUE" +
". To prevent others from updating your configuration, set a different 'GAIAN_NODE_USR' property and its associated password in derby.properties";
logger.logWarning(GDBMessages.CONFIG_SQL_API_UNAUTHORISED, warning);
throw new Exception(warning);
}
}
public static Connection getDefaultDerbyConnection() throws SQLException {
return DriverManager.getConnection("jdbc:default:connection"); //, getGaianNodeUser(), getGaianNodePassword());
// return DriverManager.getConnection("jdbc:derby://localhost:6414/gaiandb", getGaianNodeUser(), getGaianNodePassword());
}
public static ResultSet getResultSetFromQueryAgainstDefaultConnection( String sql ) throws SQLException {
Connection c = getDefaultDerbyConnection();
// System.out.println(sql);
ResultSet rs = c.createStatement().executeQuery( sql );
return rs;
}
static synchronized void setConfigProperties( String sqlQueryReturningPropertyKeysAndValues, Connection conn ) throws Exception {
if ( null == sqlQueryReturningPropertyKeysAndValues ) return;
Map<String, String> updates = new LinkedHashMap<String, String>();
ResultSet rs = conn.createStatement().executeQuery( sqlQueryReturningPropertyKeysAndValues );
while ( rs.next() ) updates.put( rs.getString(1).trim(), rs.getString(2).trim() );
// TODO: check if property name relates to a transient data source - e.g. if it exists in transient set.
// If so, change the transient one, update the upr as well and reload the data source (don't reload if it was a VTI Property)
// Blocked on this for now as cant resolve ltname and dsname deterministically...
for ( String propertyName : updates.keySet() )
if ( inMemoryDataSourceProperties.contains(propertyName) )
throw new Exception("Cannot update transient data source property: '" + propertyName +
"'. Please remove the data source first with removeds().");
persistAndApplyConfigUpdates(updates);
DataSourcesManager.checkUpdateLogicalTableViewsOnAllDBs();
}
// private static ResultSet getDataAsResultSet( List<String[]> rows, String[] colAliases, boolean[] isQuoted ) throws SQLException {
// StringBuffer sb = new StringBuffer();
//
// for ( String[] row : rows )
// for ( int i=0; i<row.length; i++ )
// sb.append( ( 0<i ? " UNION ALL " : "" ) +
// "SELECT " + (isQuoted[i]?"'":"") + row[i] + (isQuoted[i]?"' ":" \"") + colAliases[i] + "\" FROM SYSIBM.SYSDUMMY1" );
//
// return getResultSetFromQueryAgainstDefaultConnection( sb.toString() );
// }
// public static byte[] readFileBytes( File file ) is equivalent to: Util.getFileBytes(file);
// public static void writeBytesToFile( byte[] bytes, File file ) is just: Util.copyBinaryData(new ByteArrayInputStream(bytes), new FileOutputStream(file));
public static byte[] readAndZipFileBytes( File file ) throws Exception {
try {
if ( file.isDirectory() ) throw new Exception("File is a directory");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Util.copyBinaryData(new FileInputStream(file), new GZIPOutputStream(baos));
byte[] bytes = baos.toByteArray();
baos.close(); // other streams are closed
return bytes;
}
catch (Exception e) { throw new Exception("Cannot read/zip bytes from '" + file.getName() + "': " + e); }
}
public static void writeToFileAfterUnzip( File file, byte[] zippedBytes ) throws Exception {
try {
ByteArrayInputStream is = new ByteArrayInputStream(zippedBytes);
Util.copyBinaryData(new GZIPInputStream(is), new FileOutputStream(file));
is.close(); // other streams are closed
}
catch (Exception e) { throw new Exception("Unable to unzip and write to file " + file.getName() + ": " + e); }
}
}