/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.data.jdbc; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.geotools.data.jdbc.datasource.UnWrapper; import org.springframework.jdbc.support.nativejdbc.C3P0NativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.JBossNativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.Jdbc4NativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.WebLogicNativeJdbcExtractor; import org.springframework.jdbc.support.nativejdbc.WebSphereNativeJdbcExtractor; //import org.springframework.jdbc.support.nativejdbc.XAPoolNativeJdbcExtractor; /** * Wires up the rich set of Spring native connection and statements un-wrappers to the * GeoTools UnWrapper API, whose model is different (they assume you know in advance * which un-wrapper you'll need, each un-wrapper works only in the environment it was * designed for) * @author Andrea Aime - OpenGeo */ public class SpringUnWrapper implements UnWrapper { static final List<NativeJdbcExtractor> EXTRACTORS; static { List<NativeJdbcExtractor> extractors = new ArrayList<NativeJdbcExtractor>(); // some of these extractors will just blow up during initialization if // the environment does not contain the classes they are looking for, so we // guard their initialization and just skip them try { extractors.add(new CommonsDbcpNativeJdbcExtractor()); } catch(Throwable e) {}; try { extractors.add(new JBossNativeJdbcExtractor()); } catch(Throwable e) {}; try { extractors.add(new Jdbc4NativeJdbcExtractor()); } catch(Throwable e) {}; try { extractors.add(new SimpleNativeJdbcExtractor()); } catch(Throwable e) {}; try { extractors.add(new WebLogicNativeJdbcExtractor()); } catch(Throwable e) {}; try { extractors.add(new WebSphereNativeJdbcExtractor()); } catch(Throwable e) {}; // try { // extractors.add(new XAPoolNativeJdbcExtractor()); // } catch(Throwable e) {}; try { extractors.add(new C3P0NativeJdbcExtractor()); } catch(Throwable e) {}; // use a concurrent enabled data structure so that we can modify // the order of extractors at run time, in a way that the extractors // that can actually do the work end up first (the code is executed in // tight loops over features and handling over and over exceptions is expensive) EXTRACTORS = new CopyOnWriteArrayList<NativeJdbcExtractor>(extractors); } public boolean canUnwrap(Connection conn) { Connection unwrapped = unwrapInternal(conn); return unwrapped != null; } public Connection unwrap(Connection conn) { Connection unwrapped = unwrapInternal(conn); if(unwrapped != null) return unwrapped; else throw new IllegalArgumentException("This connection is not unwrappable, " + "check canUnwrap before calling unwrap"); } private Connection unwrapInternal(Connection conn) { for (int i = 0; i < EXTRACTORS.size(); i++) { NativeJdbcExtractor extractor = EXTRACTORS.get(i); try { // the contract is that the original connection is returned // if unwrapping was not possible Connection unwrapped = extractor.getNativeConnection(conn); if(conn != unwrapped) { if(i != 0) { // move the extractor to the top, so that we don't do // many useless attempts at unwrapping with the others // (this code is typically executed for each feature) EXTRACTORS.add(0, extractor); EXTRACTORS.remove(i); } return unwrapped; } } catch(Throwable t) { // catch a throwable since some of the unwrappers do not blow up // during initialization when the enviroment does not help, but // they do at unwrap time and they throw Error suclasses // We just want to skip the unwrapper and move on } } return null; } public boolean canUnwrap(Statement st) { Statement unwrapped = unwrapInternal(st); return unwrapped != null; } public Statement unwrap(Statement statement) { Statement unwrapped = unwrapInternal(statement); if(unwrapped != null) return unwrapped; else throw new IllegalArgumentException("This statement is not unwrappable, " + "check canUnwrap before calling unwrap"); } private Statement unwrapInternal(Statement st) { for (int i = 0; i < EXTRACTORS.size(); i++) { NativeJdbcExtractor extractor = EXTRACTORS.get(i); try { // the contract is that the original connection is returned // if unwrapping was not possible Statement unwrapped = extractor.getNativeStatement(st); if(st != unwrapped) { if(i != 0) { // move the extractor to the beginning, so that we don't do // many useless attempts at unwrapping with the others // (this code is typically executed for each feature) EXTRACTORS.add(0, extractor); EXTRACTORS.remove(i); } return unwrapped; } } catch(SQLException e) { // no problem, skip it } } return null; } }