[teiid-commits] teiid SVN: r2796 - in trunk: client/src/main/java/org/teiid/jdbc and 6 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Thu Dec 23 15:05:37 EST 2010


Author: shawkins
Date: 2010-12-23 15:05:36 -0500 (Thu, 23 Dec 2010)
New Revision: 2796

Added:
   trunk/client/src/main/java/org/teiid/jdbc/TeiidConnection.java
Modified:
   trunk/build/kits/jboss-container/teiid-releasenotes.html
   trunk/client/src/main/java/org/teiid/jdbc/ConnectionImpl.java
   trunk/client/src/main/java/org/teiid/net/ServerConnection.java
   trunk/client/src/main/java/org/teiid/net/socket/SocketServerConnection.java
   trunk/client/src/test/java/org/teiid/net/socket/TestSocketServerConnection.java
   trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml
   trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java
   trunk/runtime/src/main/java/org/teiid/transport/LogonImpl.java
   trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java
Log:
TEIID-192 adding reauthentication support

Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html	2010-12-23 20:05:36 UTC (rev 2796)
@@ -38,6 +38,7 @@
 	<LI><B>Partition-wise Optimizations</B> - Views defined by partitioned unions (union alls where each branch has a projected literal or an IN predicate that makes its values mutually exclusive from the other branches) can 
 	be used in aggregation or joins and the optimizer will take advantage of the partitioning information.  For example, when a partitioned union is joined against another partitioned union, the optimizer will reorganize the join of unions into a union of joins.
 	<LI><B>Delegate Translator</B> - A new translator added that is capable of delegating all the calls to another configured translator.
+	<LI><B>JDBC Reauthentication</B> - Teiid connections (defined by the org.teiid.jdbc.TeiidConnection interface) now support the changeUser method to reauthenticate a given connection.
 </UL>
 
 <h2><a name="Compatibility">Compatibility Issues</a></h2>

Modified: trunk/client/src/main/java/org/teiid/jdbc/ConnectionImpl.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/ConnectionImpl.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/client/src/main/java/org/teiid/jdbc/ConnectionImpl.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -58,6 +58,7 @@
 import org.teiid.client.xa.XidImpl;
 import org.teiid.core.util.SqlUtil;
 import org.teiid.net.CommunicationException;
+import org.teiid.net.ConnectionException;
 import org.teiid.net.ServerConnection;
 import org.teiid.net.TeiidURL;
 import org.teiid.net.socket.SocketServerConnection;
@@ -65,7 +66,7 @@
 /**
  * Teiid's Connection implementation.
  */
-public class ConnectionImpl extends WrapperImpl implements Connection {
+public class ConnectionImpl extends WrapperImpl implements TeiidConnection {
 	private static Logger logger = Logger.getLogger("org.teiid.jdbc"); //$NON-NLS-1$
 
 	public static final int DEFAULT_ISOLATION = Connection.TRANSACTION_READ_COMMITTED;
@@ -109,9 +110,11 @@
     // the last query debug log
     private String debugLog;
     // the last query annotations
-    private Collection<Annotation> annotations;
+    private Collection<Annotation> annotations;
+    private Properties connectionProps;
         
-    public ConnectionImpl(ServerConnection serverConn, Properties info, String url) {        
+    public ConnectionImpl(ServerConnection serverConn, Properties info, String url) { 
+    	this.connectionProps = info;
     	this.serverConn = serverConn;
         this.url = url;
         this.dqp = serverConn.getService(DQP.class);
@@ -944,6 +947,46 @@
 
 	public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
 		throw SqlUtil.createFeatureNotSupportedException();
+	}
+	
+	@Override
+	public void changeUser(String userName, String newPassword)
+			throws SQLException {
+		//TODO: recycleConnection();
+		Object oldName = null;
+		Object oldPassword = null;
+		if (userName != null) {
+			oldName = this.connectionProps.put(TeiidURL.CONNECTION.USER_NAME, userName);
+		} else {
+			oldName = this.connectionProps.remove(TeiidURL.CONNECTION.USER_NAME);
+		}
+		if (newPassword != null) {
+			oldPassword = this.connectionProps.put(TeiidURL.CONNECTION.PASSWORD, newPassword);
+		} else {
+			oldPassword = this.connectionProps.remove(TeiidURL.CONNECTION.PASSWORD);
+		}
+		boolean success = false;
+		try {
+			this.serverConn.authenticate();
+			success = true;
+		} catch (ConnectionException e) {
+			throw TeiidSQLException.create(e);
+		} catch (CommunicationException e) {
+			throw TeiidSQLException.create(e);
+		} finally {
+			if (!success) {
+				if (oldName != null) {
+					this.connectionProps.put(TeiidURL.CONNECTION.USER_NAME, oldName);
+				} else {
+					this.connectionProps.remove(TeiidURL.CONNECTION.USER_NAME);
+				}
+				if (oldPassword != null) {
+					this.connectionProps.put(TeiidURL.CONNECTION.PASSWORD, oldPassword);
+				} else {
+					this.connectionProps.remove(TeiidURL.CONNECTION.PASSWORD);
+				}
+			}
+		}
 	}
 
 }

Added: trunk/client/src/main/java/org/teiid/jdbc/TeiidConnection.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/TeiidConnection.java	                        (rev 0)
+++ trunk/client/src/main/java/org/teiid/jdbc/TeiidConnection.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Optional methods supported by Teiid Connections.
+ */
+public interface TeiidConnection extends Connection {
+
+	/**
+	 * Re-authenticate with the given username and password.  If the re-authentication
+	 * fails the connection will remain under the current user.
+	 * 
+	 * @param userName
+     *            the username to authenticate with
+   	 * @param newPassword
+   	 *            the password to authenticate with
+	 */
+	public void changeUser(String userName, String newPassword) throws SQLException;
+}


Property changes on: trunk/client/src/main/java/org/teiid/jdbc/TeiidConnection.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/client/src/main/java/org/teiid/net/ServerConnection.java
===================================================================
--- trunk/client/src/main/java/org/teiid/net/ServerConnection.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/client/src/main/java/org/teiid/net/ServerConnection.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -40,4 +40,6 @@
 	
 	void cleanUp();
 	
+	void authenticate() throws ConnectionException, CommunicationException;
+	
 }
\ No newline at end of file

Modified: trunk/client/src/main/java/org/teiid/net/socket/SocketServerConnection.java
===================================================================
--- trunk/client/src/main/java/org/teiid/net/socket/SocketServerConnection.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/client/src/main/java/org/teiid/net/socket/SocketServerConnection.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -91,7 +91,7 @@
 		this.logon = this.getService(ILogon.class);
 		this.failOver = Boolean.valueOf(connProps.getProperty(TeiidURL.CONNECTION.AUTO_FAILOVER)).booleanValue();
 		this.failOver |= Boolean.valueOf(connProps.getProperty(TeiidURL.CONNECTION.ADMIN)).booleanValue();
-		selectServerInstance();
+		selectServerInstance(false);
 	}
 	
 	/**
@@ -100,7 +100,7 @@
 	 * TODO: put more information on hostinfo as to process response time, last successful connect, etc.
 	 * @throws ConnectionException 
 	 */
-	public synchronized SocketServerInstance selectServerInstance()
+	public synchronized SocketServerInstance selectServerInstance(boolean logoff)
 			throws CommunicationException, ConnectionException {
 		if (closed) {
 			throw new CommunicationException(JDBCPlugin.Util.getString("SocketServerConnection.closed")); //$NON-NLS-1$ 
@@ -124,9 +124,7 @@
 				ILogon newLogon = connect(hostInfo);
 				if (this.logonResult == null) {
 			        try {
-			            this.logonResult = newLogon.logon(connProps);
-			            this.logonResults.put(this.serverInstance.getHostInfo(), this.logonResult);
-			            this.connectionFactory.connected(this.serverInstance, this.logonResult.getSessionToken());
+			            logon(newLogon, logoff);
 						this.serverDiscovery.connectionSuccessful(hostInfo);
 			            if (discoverHosts) {
 				            List<HostInfo> updatedHosts = this.serverDiscovery.getKnownHosts(logonResult, this.serverInstance);
@@ -166,6 +164,23 @@
 		throw new CommunicationException(JDBCPlugin.Util.getString("SocketServerInstancePool.No_valid_host_available", hostCopy.toString())); //$NON-NLS-1$
 	}
 
+	private void logon(ILogon newLogon, boolean logoff) throws LogonException,
+			TeiidComponentException, CommunicationException {
+		LogonResult newResult = newLogon.logon(connProps);
+		SocketServerInstance instance = this.serverInstance;
+		if (logoff) {
+			if ("7.3".compareTo(this.serverInstance.getServerVersion()) <= 0) { //$NON-NLS-1$
+				//just remove the current instance - the server has already logged off the current user
+				LogonResult old = this.logonResults.remove(this.serverInstance.getHostInfo());
+				this.connectionFactory.disconnected(this.serverInstance, old.getSessionToken());
+			}
+			logoffAll();
+		}
+		this.logonResult = newResult;
+		this.logonResults.put(instance.getHostInfo(), this.logonResult);
+		this.connectionFactory.connected(instance, this.logonResult.getSessionToken());
+	}
+
 	private ILogon connect(HostInfo hostInfo) throws CommunicationException,
 			IOException {
 		hostInfo.setSsl(secure);
@@ -189,7 +204,7 @@
 			protected SocketServerInstance getInstance() throws CommunicationException {
 				if (failOver && System.currentTimeMillis() - lastPing > pingFailOverInterval) {
 					try {
-						ResultsFuture<?> future = selectServerInstance().getService(ILogon.class).ping();
+						ResultsFuture<?> future = selectServerInstance(false).getService(ILogon.class).ping();
 						future.get();
 					} catch (SingleInstanceCommunicationException e) {
 						closeServerInstance();
@@ -204,7 +219,7 @@
 				}
 				lastPing = System.currentTimeMillis();
 				try {
-					return selectServerInstance();
+					return selectServerInstance(false);
 				} catch (ConnectionException e) {
 					throw new CommunicationException(e);
 				}
@@ -234,6 +249,13 @@
 			logoff();
 		}
 		
+		logoffAll();
+		
+		this.closed = true;
+		this.serverDiscovery.shutdown();
+	}
+
+	private void logoffAll() {
 		for (Map.Entry<HostInfo, LogonResult> logonEntry : logonResults.entrySet()) {
 			try {
 				connect(logonEntry.getKey());
@@ -242,9 +264,6 @@
 				
 			}
 		}
-		
-		this.closed = true;
-		this.serverDiscovery.shutdown();
 	}
 
 	private void logoff() {
@@ -299,7 +318,7 @@
 			return false;
 		}
 		try {
-			return selectServerInstance().getHostInfo().equals(((SocketServerConnection)otherService).selectServerInstance().getHostInfo());
+			return selectServerInstance(false).getHostInfo().equals(((SocketServerConnection)otherService).selectServerInstance(false).getHostInfo());
 		} catch (ConnectionException e) {
 			throw new CommunicationException(e);
 		}
@@ -316,4 +335,21 @@
 	public void setFailOverPingInterval(int pingFailOverInterval) {
 		this.pingFailOverInterval = pingFailOverInterval;
 	}
+	
+	@Override
+	public void authenticate() throws ConnectionException,
+			CommunicationException {
+		if (this.serverInstance == null) {
+			selectServerInstance(true); //this will trigger a logon with the new credentials
+		} else {
+			ILogon logonInstance = this.serverInstance.getService(ILogon.class);
+			try {
+				this.logon(logonInstance, true);
+			} catch (LogonException e) {
+				throw new ConnectionException(e);
+			} catch (TeiidComponentException e) {
+				throw new CommunicationException(e);
+			}
+		}
+	}
 }
\ No newline at end of file

Modified: trunk/client/src/test/java/org/teiid/net/socket/TestSocketServerConnection.java
===================================================================
--- trunk/client/src/test/java/org/teiid/net/socket/TestSocketServerConnection.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/client/src/test/java/org/teiid/net/socket/TestSocketServerConnection.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -54,8 +54,8 @@
 /**
  * <code>TestCase</case> for <code>SocketServerConnection</code>
  * @see SocketServerConnection
- * @since Westport
  */
+ at SuppressWarnings("nls")
 public class TestSocketServerConnection {
 	
 	private static final class FakeILogon implements ILogon {
@@ -83,7 +83,7 @@
 				Properties connectionProperties)
 				throws LogonException,
 				TeiidComponentException {
-			return new LogonResult(new SessionToken(1, "fooUser"), "foo", 1, "fake"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return new LogonResult(new SessionToken(1, connectionProperties.getProperty(TeiidURL.CONNECTION.USER_NAME, "fooUser")), "foo", 1, "fake"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 		}
 
 		@Override
@@ -151,6 +151,15 @@
 		assertEquals(String.valueOf(1), connection.getLogonResult().getSessionID()); 
 	}
 	
+	@Test public void testChangeUser() throws Exception {
+		Properties p = new Properties();
+		SocketServerConnection connection = createConnection(null, p);
+		assertEquals("fooUser", connection.getLogonResult().getUserName()); 
+		p.setProperty(TeiidURL.CONNECTION.USER_NAME, "newUser");
+		connection.authenticate();
+		assertEquals("newUser", connection.getLogonResult().getUserName());
+	}
+	
 	/**
 	 * Since the original instance is still open, this will be a transparent retry
 	 */
@@ -177,12 +186,15 @@
 	}
 
 	private SocketServerConnection createConnection(final Throwable throwException) throws CommunicationException, ConnectionException {
-		return createConnection(throwException, new HostInfo("0.0.0.2", 1)); //$NON-NLS-1$
+		return createConnection(throwException, new Properties());
 	}
 	
-	private SocketServerConnection createConnection(final Throwable t, final HostInfo hostInfo)
+	private SocketServerConnection createConnection(final Throwable throwException, Properties p) throws CommunicationException, ConnectionException {
+		return createConnection(throwException, new HostInfo("0.0.0.2", 1), p); //$NON-NLS-1$
+	}
+	
+	private SocketServerConnection createConnection(final Throwable t, final HostInfo hostInfo, Properties p)
 			throws CommunicationException, ConnectionException {
-		Properties p = new Properties();
 		ServerDiscovery discovery = new UrlServerDiscovery(new TeiidURL(hostInfo.getHostName(), hostInfo.getPortNumber(), false));
 		SocketServerInstanceFactory instanceFactory = new SocketServerInstanceFactory() {
 			FakeILogon logon = new FakeILogon(t);
@@ -194,6 +206,7 @@
 				Mockito.stub(instance.getCryptor()).toReturn(new NullCryptor());
 				Mockito.stub(instance.getHostInfo()).toReturn(hostInfo);
 				Mockito.stub(instance.getService(ILogon.class)).toReturn(logon);
+				Mockito.stub(instance.getServerVersion()).toReturn("7.3");
 				if (t != null) {
 					try {
 						Mockito.doAnswer(new Answer<Void>() {
@@ -231,8 +244,8 @@
 	}
 	
 	@Test public void testIsSameInstance() throws Exception {
-		SocketServerConnection conn = createConnection(null, new HostInfo("0.0.0.0", 1)); //$NON-NLS-1$
-		SocketServerConnection conn1 = createConnection(null, new HostInfo("0.0.0.1", 1)); //$NON-NLS-1$
+		SocketServerConnection conn = createConnection(null, new HostInfo("0.0.0.0", 1), new Properties()); //$NON-NLS-1$
+		SocketServerConnection conn1 = createConnection(null, new HostInfo("0.0.0.1", 1), new Properties()); //$NON-NLS-1$
 		
 		assertFalse(conn.isSameInstance(conn1));
 		assertTrue(conn.isSameInstance(conn));

Modified: trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml
===================================================================
--- trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml	2010-12-23 20:05:36 UTC (rev 2796)
@@ -536,5 +536,10 @@
         	<para>Your customized server discovery class will then need to be referenced by the discoveryStategy connection/DataSource property by its full class name.</para>
         </section>
     </section>
-    
+    <section>
+    	<title>Reauthentication</title>
+    	<para>Teiid connections (defined by the <code>org.teiid.jdbc.TeiidConnection</code> interface) support the changeUser method to reauthenticate a given connection.  
+    	If the reauthentication is successful the current connection my be used with the given identity.  
+    	Existing statements/result sets are still available for use under the old identity.  See the JBossAS issue <ulink url="https://issues.jboss.org/browse/JBAS-1429">JBAS-1429</ulink> for more on using reauthentication support with JCA.</para>
+    </section>
 </chapter>
\ No newline at end of file

Modified: trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -62,7 +62,7 @@
 		this.connectionProperties = connectionProperties;
 		this.csr = getClientServiceRegistry();
 		workContext.setSecurityHelper(csr.getSecurityHelper());
-		authenticate(connectionProperties);
+		authenticate();
 		passthrough = Boolean.valueOf(connectionProperties.getProperty(TeiidURL.CONNECTION.PASSTHROUGH_AUTHENTICATION, "false")); //$NON-NLS-1$
 	}
 
@@ -75,9 +75,9 @@
 		}
 	}
 	
-	public synchronized void authenticate(Properties connProps) throws ConnectionException, CommunicationException {
+	public synchronized void authenticate() throws ConnectionException, CommunicationException {
         try {
-        	this.result = this.getService(ILogon.class).logon(connProps);
+        	this.result = this.getService(ILogon.class).logon(this.connectionProperties);
         } catch (LogonException e) {
             // Propagate the original message as it contains the message we want
             // to give to the user
@@ -101,8 +101,7 @@
 					if (passthrough && !arg1.getDeclaringClass().equals(ILogon.class)) {
 						// check to make sure the current security context same as logged one
 						if (!csr.getSecurityHelper().sameSubject(workContext.getSession().getSecurityDomain(), workContext.getSession().getSecurityContext(), workContext.getSubject())) {
-							logoff();
-							authenticate(connectionProperties);
+							authenticate();
 						}
 					}
 					

Modified: trunk/runtime/src/main/java/org/teiid/transport/LogonImpl.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/LogonImpl.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/runtime/src/main/java/org/teiid/transport/LogonImpl.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -59,7 +59,8 @@
 
 	public LogonResult logon(Properties connProps) throws LogonException,
 			ComponentNotFoundException {
-		
+		DQPWorkContext workContext = DQPWorkContext.getWorkContext();
+		SessionToken oldToken = workContext.getSessionToken();
         String applicationName = connProps.getProperty(TeiidURL.CONNECTION.APP_NAME);
         // user may be null if using trustedToken to log on
         String user = connProps.getProperty(TeiidURL.CONNECTION.USER_NAME, CoreConstants.DEFAULT_ANON_USERNAME);
@@ -77,6 +78,12 @@
 	        if (DQPWorkContext.getWorkContext().getClientAddress() == null) {
 				sessionInfo.setEmbedded(true);
 	        }
+	        if (oldToken != null) {
+	        	try {
+					this.service.closeSession(oldToken.getSessionID());
+				} catch (InvalidSessionException e) {
+				}
+	        }
 			return new LogonResult(sessionInfo.getSessionToken(), sessionInfo.getVDBName(), sessionInfo.getVDBVersion(), clusterName);
 		} catch (LoginException e) {
 			throw new LogonException(e.getMessage());

Modified: trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java
===================================================================
--- trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java	2010-12-23 18:26:05 UTC (rev 2795)
+++ trunk/runtime/src/test/java/org/teiid/transport/TestCommSockets.java	2010-12-23 20:05:36 UTC (rev 2796)
@@ -140,7 +140,7 @@
 		SSLConfiguration config = new SSLConfiguration();
 		config.setMode(SSLConfiguration.DISABLED);
 		SocketServerConnection conn = helpEstablishConnection(false, config, new Properties());
-		assertTrue(conn.selectServerInstance().getCryptor() instanceof NullCryptor);
+		assertTrue(conn.selectServerInstance(false).getCryptor() instanceof NullCryptor);
 		conn.close();
 	}
 



More information about the teiid-commits mailing list