Author: rmannibucau Date: Thu Oct 2 13:58:18 2014 New Revision: 1628979 URL: http://svn.apache.org/r1628979 Log: TOMEE-1374 TOMEE-1373 unregistring AlternativeDriver + trying to detect we have to create with app loader a datasource
Added: tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/ tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/CipherFromAppTest.java tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/MyConstantCipher.java Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java Added: tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/CipherFromAppTest.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/CipherFromAppTest.java?rev=1628979&view=auto ============================================================================== --- tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/CipherFromAppTest.java (added) +++ tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/CipherFromAppTest.java Thu Oct 2 13:58:18 2014 @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.cipher; + +import org.apache.openejb.cipher.PasswordCipher; +import org.apache.openejb.resource.jdbc.managed.local.ManagedDataSource; +import org.apache.tomee.jdbc.TomEEDataSourceCreator; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +import static org.junit.Assert.assertEquals; + +@RunWith(Arquillian.class) +public class CipherFromAppTest { + @Deployment + public static Archive<?> war() { + return ShrinkWrap.create(WebArchive.class, CipherFromAppTest.class.getName() + ".war") + .addClass(MyConstantCipher.class) + .addAsWebInfResource(new StringAsset(MyConstantCipher.class.getName()), "classes/META-INF/" + PasswordCipher.class.getName() + "/constant") + .addAsWebInfResource(new StringAsset("" + + "<resource>" + + " <Resource type=\"DataSource\" id=\"cipher\">" + + " PasswordCipher = constant" + + " </Resource>" + + "</resource>"), "resources.xml"); + } + + @Resource(name = "cipher") + private DataSource ds; + + @Test + public void checkPassword() { + final DataSource delegate = ManagedDataSource.class.cast(ds).getDelegate(); + assertEquals(new MyConstantCipher().decrypt(null), TomEEDataSourceCreator.TomEEDataSource.class.cast(delegate).getPoolProperties().getPassword()); + } +} Added: tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/MyConstantCipher.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/MyConstantCipher.java?rev=1628979&view=auto ============================================================================== --- tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/MyConstantCipher.java (added) +++ tomee/tomee/trunk/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cipher/MyConstantCipher.java Thu Oct 2 13:58:18 2014 @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.cipher; + +import org.apache.openejb.cipher.PasswordCipher; + +public class MyConstantCipher implements PasswordCipher { + @Override + public char[] encrypt(final String plainPassword) { + return new char[0]; + } + + @Override + public String decrypt(final char[] encryptedPassword) { + return "constant I said"; + } +} Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java?rev=1628979&r1=1628978&r2=1628979&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java Thu Oct 2 13:58:18 2014 @@ -17,6 +17,8 @@ package org.apache.openejb.resource.jdbc; +import org.apache.openejb.cipher.PasswordCipherException; +import org.apache.openejb.cipher.PasswordCipherFactory; import org.apache.openejb.loader.IO; import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.resource.XAResourceWrapper; @@ -50,6 +52,8 @@ import java.util.Properties; import java.util.TreeMap; import java.util.concurrent.TimeUnit; +import static java.util.Arrays.asList; + /** * @version $Rev$ $Date$ */ @@ -64,6 +68,8 @@ public class DataSourceFactory { public static final String POOL_PROPERTY = "openejb.datasource.pool"; public static final String DATA_SOURCE_CREATOR_PROP = "DataSourceCreator"; + private static final Map<CommonDataSource, AlternativeDriver> driverByDataSource = new HashMap<CommonDataSource, AlternativeDriver>(); + private static final Map<CommonDataSource, DataSourceCreator> creatorByDataSource = new HashMap<CommonDataSource, DataSourceCreator>(); private static final Map<String, String> KNOWN_CREATORS = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER) {{ put("simple", "org.apache.openejb.resource.jdbc.SimpleDataSourceCreator"); // use user provided DS, pooling not supported @@ -114,23 +120,37 @@ public class DataSourceFactory { final String jdbcUrl = properties.getProperty("JdbcUrl"); + final AlternativeDriver driver; if (Driver.class.isAssignableFrom(impl) && jdbcUrl != null) { try { - final AlternativeDriver driver = new AlternativeDriver((Driver) impl.newInstance(), jdbcUrl); + driver = new AlternativeDriver((Driver) impl.newInstance(), jdbcUrl); driver.register(); } catch (final SQLException e) { throw new IllegalStateException(e); } + } else { + driver = null; } final boolean logSql = SystemInstance.get().getOptions().get(GLOBAL_LOG_SQL_PROPERTY, "true".equalsIgnoreCase((String) properties.remove(LOG_SQL_PROPERTY))); final DataSourceCreator creator = creator(properties.remove(DATA_SOURCE_CREATOR_PROP), logSql); - final boolean useContainerLoader = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.resources.use-container-loader", "true")) && (impl == null || impl.getClassLoader() == DataSourceFactory.class.getClassLoader()); + boolean useContainerLoader = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.resources.use-container-loader", "true")) && (impl == null || impl.getClassLoader() == DataSourceFactory.class.getClassLoader()); final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); if (useContainerLoader) { - Thread.currentThread().setContextClassLoader(DataSourceFactory.class.getClassLoader()); + final ClassLoader containerLoader = DataSourceFactory.class.getClassLoader(); + Thread.currentThread().setContextClassLoader(containerLoader); + try { + useContainerLoader = basicChecksThatDataSourceCanBeCreatedFromContainerLoader(properties, containerLoader); + } finally { + Thread.currentThread().setContextClassLoader(oldLoader); + } + if (useContainerLoader) { + Thread.currentThread().setContextClassLoader(containerLoader); + } else { + LOGGER.info("Can't use container loader to create datasource " + name + " so using application one"); + } } try { @@ -178,6 +198,9 @@ public class DataSourceFactory { // ds and creator are associated here, not after the proxying of the next if if active setCreatedWith(creator, ds); + if (driver != null) { + driverByDataSource.put(ds, driver); + } if (logSql) { ds = makeItLogging(ds); @@ -194,6 +217,34 @@ public class DataSourceFactory { } } + private static boolean basicChecksThatDataSourceCanBeCreatedFromContainerLoader(final Properties properties, final ClassLoader containerLoader) { + // check basic some classes can be loaded from container otherwise don't force it + try { + for (final String property : asList("JdbcDriver", "driverClassName")) { + final String value = properties.getProperty(property); + if (value != null) { + Class.forName(value, false, containerLoader); + } + } + } catch (final ClassNotFoundException cnfe) { + return false; + } catch (final NoClassDefFoundError cnfe) { + return false; + } + + // also password cipher can be loaded from apps + try { + final String cipher = properties.getProperty("PasswordCipher"); + if (cipher != null && !"PlainText".equals(cipher) && !"Static3DES".equals(cipher)) { + PasswordCipherFactory.getPasswordCipher(cipher); + } + } catch (final PasswordCipherException cnfe) { + return false; + } + + return true; + } + private static CommonDataSource makeFlushable(final CommonDataSource ds, final FlushableDataSourceHandler.FlushConfig flushConfig) { return (CommonDataSource) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), @@ -334,6 +385,11 @@ public class DataSourceFactory { } final DataSourceCreator remove = creatorByDataSource.remove(instance); remove.destroy(instance); + + final AlternativeDriver driver = driverByDataSource.remove(instance); + if (driver != null) { + driver.deregister(); + } } // remove proxy added by us in front of the datasource returned by the creator