Get DB2-specific parser instance - java

I'm trying to create a simple plugin where I can paste in an sql query from our logs and have it display the column names and inserted values in a table. I've got it working, except for dates and times, because our DB2 database uses special values like {d: '2014-07-03'} rather than '2014-07-03'.
How do I figure out what values I need to pass to SQLQueryParserManagerProvider.getInstance().getParserManager(dbProduct,
dbVersion);
to get the right parser that can handle these values?

Set up a connection in the Database Development view (I called mine QA), double click to open a connection, then run:
IConnectionProfile profile = ProfileManager.getInstance().getProfileByName("QA");
Database db = getDatabase(profile);
if (db != null) {
System.out.println("DB Vendor: " + db.getVendor());
System.out.println("DB Version: " + db.getVersion());
}
getDatabase method was taken from the end of this page:
private Database getDatabase(IConnectionProfile profile) {
IManagedConnection managedConnection = ((IConnectionProfile) profile)
.getManagedConnection("org.eclipse.datatools.connectivity.sqm.core.connection.ConnectionInfo");
if (managedConnection != null) {
try {
ConnectionInfo connectionInfo = (ConnectionInfo) managedConnection.getConnection().getRawConnection();
if (connectionInfo != null) {
Database database = connectionInfo.getSharedDatabase();
return database;
}
}
catch (Exception e) {
e.printStackTrace();
}
}
return null;
}

Related

Spring R2DBC Postgres Row Level Security

I'm trying to implement Postgres Row Level Security on my app that uses R2DBC.
I found this AWS post that implements this but uses a non-reactive approach.
I'm having problems converting this to a reactive approach since I can't find a class equivalent to the AbstractRoutingDataSource:
public class TenantAwareDataSource extends AbstractRoutingDataSource {
private static final Logger LOGGER = LoggerFactory.getLogger(TenantAwareDataSource.class);
#Override
protected Object determineCurrentLookupKey() {
Object key = null;
// Pull the currently authenticated tenant from the security context
// of the HTTP request and use it as the key in the map that points
// to the connection pool (data source) for each tenant.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
try {
if (!(authentication instanceof AnonymousAuthenticationToken)) {
Tenant currentTenant = (Tenant) authentication.getPrincipal();
key = currentTenant.getId();
}
} catch (Exception e) {
LOGGER.error("Failed to get current tenant for data source lookup", e);
throw new RuntimeException(e);
}
return key;
}
#Override
public Connection getConnection() throws SQLException {
// Every time the app asks the data source for a connection
// set the PostgreSQL session variable to the current tenant
// to enforce data isolation.
Connection connection = super.getConnection();
try (Statement sql = connection.createStatement()) {
LOGGER.info("Setting PostgreSQL session variable app.current_tenant = '{}' on {}", determineCurrentLookupKey().toString(), this);
sql.execute("SET SESSION app.current_tenant = '" + determineCurrentLookupKey().toString() + "'");
} catch (Exception e) {
LOGGER.error("Failed to execute: SET SESSION app.current_tenant = '{}'", determineCurrentLookupKey().toString(), e);
}
return connection;
}
#Override
public String toString() {
return determineTargetDataSource().toString();
}
}
What would be the equivalent on R2DBC to AbstractRoutingDataSource?
Thanks
Full source code here.

How to switch between different database users with different permissions, directly inside my application on Java?

So I'm using Java and MySQL, I created a database with different roles (user/manager/admin etc....) By default, I'm connected as a simple user, but how can I switch my user to the super admin after he authenticates?
Because right now, my connection with MySQL is made in a private constructor with private methods, so at first I thought about putting setters, but I can't access them given that I can't instantiate an object from my class with the private constructor.
ConnexionMySQL.java:
private ResourceBundle bundle =
ResourceBundle.getBundle("domaine.properties.config");
private String url = bundle.getString("sgbd.url");
private String driver = bundle.getString("sgbd.driver");
private String mysqlUser = bundle.getString("sgbd.login");
private String mysqlPassword = bundle.getString("sgbd.password");
private ConnexionMysql(){
try {
session = doSshTunnel(this.sshUser, this.sshPassword, this.sshHost, this.sshPort, this.url, this.sshLocalPort,this.sshRemotePort);
System.out.println("Opened SSH on " + sshHost);
Class.forName(driver);
connect = DriverManager.getConnection(url, mysqlUser ,mysqlPassword);
System.out.println("connect� Mysql");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static Connection getInstance(){
if(instance == null){
instance = new ConnexionMysql();
System.out.println("INSTANCIATION DE LA CONNEXION SQL ! ");
}
else{
System.out.println("CONNEXION SQL EXISTANTE ! ");
}
return connect;
}
public static void disconnect(){
try {
connect.close();
session.disconnect();
instance = null;
System.out.println("Deconnexion r�ussie");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
I have another config.properties file in which I specified the login and password.
But what if now I wanna change those values in a controller for example after a user authenticates ?
I would say that the easiest way to solve this problems will be to make as many clases as roles you want to create (of course if you want to leave your constructor private).
In my opinion it should look something like this:
ConnexionMySQLuser;
ConnexionMySQLmanager;
ConnexionMySQLadmin;
Of course if you have numerous of roles it can create problems in future.

Java JDBC and Oracle Wallet Connection

How to use oracle wallet
Using this as reference. I am still unable to connect to Oracle Wallet. Sample code below.
Errors
--
java.sql.SQLException: encountered a problem with the Secret Store. Check the wallet location for the presence of an open wallet (cwallet.sso) and ensure that this wallet contains the correct credentials using the mkstore utility: java.io.IOException: oracle.security.crypto.cert.PKCS12.getAuthSafesAsList()Ljava/util/ArrayList;
at oracle.jdbc.driver.PhysicalConnection.getSecretStoreCredentials(PhysicalConnection.java:1314)
at oracle.jdbc.driver.PhysicalConnection.parseUrl(PhysicalConnection.java:1198)
at oracle.jdbc.driver.PhysicalConnection.readConnectionProperties(PhysicalConnection.java:982)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:646)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:428)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:38)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:691)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
--
Sample Code
public static void main (String [] args) {
System.out.println("-------- Oracle JDBC Connection Testing ------");
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
System.out.println("Where is your Oracle JDBC Driver?");
e.printStackTrace();
return;
}
System.out.println("Oracle JDBC Driver Registered!");
Connection connection = null;
determineAndSetTnsHome();
try {
connection = DriverManager.getConnection(
"jdbc:oracle:thin:/#xxx");
} catch (SQLException e) {
System.out.println("Connection Failed! Check output console");
e.printStackTrace();
return;
}
if (connection != null) {
System.out.println("You made it, take control your database now!");
} else {
System.out.println("Failed to make connection!");
}
}
private static void determineAndSetTnsHome() {
String tnsAdmin = System.getenv("TNS_ADMIN");
if (tnsAdmin == null) {
String oracleHome = System.getenv("ORACLE_HOME");
if (oracleHome == null) {
return; //failed to find any useful env variables
}
tnsAdmin = oracleHome + File.separatorChar + "network" + File.separatorChar + "admin";
}
System.setProperty("oracle.net.tns_admin", tnsAdmin);
}
--
Notes
Confirmed that wallet is setup.
- Doing sqlplus $xxx connects fine.
- Doing mkstore -wrl -listCredential returns the entry after entering wallet password.
Thanks in advance.
Can you check out the blog for more details?
Check if you are using TLSv1.2 and Oracle Wallets require additional jars (oraclepki.jar, osdt_core.jar, and osdt_cert.jar)
Your wallet may be installed and configured correctly, but that does not mean the wallet is currently open. Anytime the database is restarted, the wallet needs to be opened.
Run a sample query against a known table in your schema in SQL*Plus (connecting is not enough)
If the wallet is not open you will get the following error:
ORA-28365: wallet is not open
This query should give you the status of the wallet:
select wrl_type wallet,status,wrl_parameter wallet_location from v$encryption_wallet;
In order to open a wallet, run the following command, replacing "myPassword" with the password you chose:
ALTER SYSTEM SET ENCRYPTION WALLET OPEN IDENTIFIED BY "myPassword";

Postgres Query to know the db is up and running

(EDITED)
I am using the following code to check if my Postgres db is up and running. However if the machine running the db is slow (Not enough RAM for example) it sometimes pass but when i tried to get some real data from the db (a few millisec after) i fail. I guess because not all tables were loaded.
Here is my code:
public static boolean testDBConnection(boolean refreshFactory) throws Exception
Session session = null;
try {
if(refreshFactory){
ConnectionUtil.refreshSessionFactory();
}
session = ConnectionUtil.getSessionFactory().openSession();
String sql = "select 1";
session.createSQLQuery(sql).list();
return true;
}
catch (HibernateException e) {
String error = "Failed to connect db.";
throw ExceptionFactory.create(error);
}
finally{
if(session!=null){
session.close();
}
}
}
Is there a better way then "select 1"?
Thanks

Java Datasource, how to dispose it

I'm working on a webapp where i manually create my DataSource. (also see my other question why: How to use Spring to manage connection to multiple databases) because I need to connect to other databases (dev, prod, qa, test).
Now I have solved it to choose and switch between databases. But if a user logs out of my app. He wants to try to connect to an other database. He is still connected to the same datasource because at runtime the myDs is not null. How can I properly dispose of this Datasource when user logs out? I don't want the user to create the datasource every time he queries the database.
private DataSource createDataSource(Environment e) {
OracleDataSource ds = null;
String url = null;
try {
if (myDs != null) {
logger.info("myDs connection: " + etmetaDs.getConnection().getMetaData().getURL());
url = myDs.getConnection().getMetaData().getURL();
}
} catch (SQLException exc) {
// TODO Auto-generated catch block
exc.printStackTrace();
}
if (myDs == null) {
try {
ds = new OracleDataSource();
} catch (SQLException ex) {
ex.printStackTrace();
}
ds.setDriverType("oracle.jdbc.OracleDriver");
ds.setURL(e.getUrl());
try {
Cryptographer c = new Cryptographer();
ds.setUser(c.decrypt(e.getUsername()));
ds.setPassword(c.decrypt(e.getPassword()));
} catch (CryptographyException ex) {
logger.error("Failed to connect to my environment [" + e.getName() + "]");
ex.printStackTrace();
return null;
}
logger.info("Connecting to my environment [" + e.getName() + "]");
myDs = ds;
} else if (url.equals(e.getUrl())) {
} else {
}
return myDs;
}
If you read the answer of Reza in you other question you can see how to create multiple DataSource.
I think here that the problem is not the DataSource but the way you store information in your code. I suppose that your etmetaDs is shared but all your users, so dispose it when a user log out (= set it to null) is not the good option.
What you have to do, is to maintain the status of the connection for each user. And when a user log off, you can reset is status in order to obtain a new connection the next time it connects.
Update: There are many way to achieve this. I give here an example of what I imagine, but you have to adapt it to your needs. Suppose that you have a UserData object that holds information :
public class UserData
{
String id;
String name;
String database;
}
You may have in your application a dropdown with the name of the database (dev, test, ...) with an empty first item. When the user selects a database, you get the connection with createDataSource(). If it already exists you returns the DataSource else you create a new one. When your user disconnect (or when the user log on), you set the database to "" to force him to select the database in the dropdown. There is no need to reset the datasource.

Categories