public class JavaBeanReferenceMaker implements ReferenceMaker {
  private static final MLogger logger = MLog.getLogger(JavaBeanReferenceMaker.class);

  static final String REF_PROPS_KEY = "com.mchange.v2.naming.JavaBeanReferenceMaker.REF_PROPS_KEY";

  static final Object[] EMPTY_ARGS = new Object[0];

  static final byte[] NULL_TOKEN_BYTES = new byte[0];

  String factoryClassName = "com.mchange.v2.naming.JavaBeanObjectFactory";
  String defaultFactoryClassLocation = null;

  Set referenceProperties = new HashSet();

  ReferenceIndirector indirector = new ReferenceIndirector();

  public Hashtable getEnvironmentProperties() {
    return indirector.getEnvironmentProperties();
  }

  public void setEnvironmentProperties(Hashtable environmentProperties) {
    indirector.setEnvironmentProperties(environmentProperties);
  }

  public void setFactoryClassName(String factoryClassName) {
    this.factoryClassName = factoryClassName;
  }

  public String getFactoryClassName() {
    return factoryClassName;
  }

  public String getDefaultFactoryClassLocation() {
    return defaultFactoryClassLocation;
  }

  public void setDefaultFactoryClassLocation(String defaultFactoryClassLocation) {
    this.defaultFactoryClassLocation = defaultFactoryClassLocation;
  }

  public void addReferenceProperty(String propName) {
    referenceProperties.add(propName);
  }

  public void removeReferenceProperty(String propName) {
    referenceProperties.remove(propName);
  }

  public Reference createReference(Object bean) throws NamingException {
    try {
      BeanInfo bi = Introspector.getBeanInfo(bean.getClass());
      PropertyDescriptor[] pds = bi.getPropertyDescriptors();
      List refAddrs = new ArrayList();
      String factoryClassLocation = defaultFactoryClassLocation;

      boolean using_ref_props = referenceProperties.size() > 0;

      // we only include this so that on dereference we are not surprised to find some properties
      // missing
      if (using_ref_props)
        refAddrs.add(
            new BinaryRefAddr(REF_PROPS_KEY, SerializableUtils.toByteArray(referenceProperties)));

      for (int i = 0, len = pds.length; i < len; ++i) {
        PropertyDescriptor pd = pds[i];
        String propertyName = pd.getName();
        // System.err.println("Making Reference: " + propertyName);

        if (using_ref_props && !referenceProperties.contains(propertyName)) {
          // System.err.println("Not a ref_prop -- continuing.");
          continue;
        }

        Class propertyType = pd.getPropertyType();
        Method getter = pd.getReadMethod();
        Method setter = pd.getWriteMethod();
        if (getter != null
            && setter != null) // only use properties that are both readable and writable
        {
          Object val = getter.invoke(bean, EMPTY_ARGS);
          // System.err.println( "val: " + val );
          if (propertyName.equals("factoryClassLocation")) {
            if (String.class != propertyType)
              throw new NamingException(
                  this.getClass().getName()
                      + " requires a factoryClassLocation property to be a string, "
                      + propertyType.getName()
                      + " is not valid.");
            factoryClassLocation = (String) val;
          }

          if (val == null) {
            RefAddr addMe = new BinaryRefAddr(propertyName, NULL_TOKEN_BYTES);
            refAddrs.add(addMe);
          } else if (Coerce.canCoerce(propertyType)) {
            RefAddr addMe = new StringRefAddr(propertyName, String.valueOf(val));
            refAddrs.add(addMe);
          } else // other Object properties
          {
            RefAddr addMe = null;
            PropertyEditor pe = BeansUtils.findPropertyEditor(pd);
            if (pe != null) {
              pe.setValue(val);
              String textValue = pe.getAsText();
              if (textValue != null) addMe = new StringRefAddr(propertyName, textValue);
            }
            if (addMe == null) // property editor approach failed
            addMe =
                  new BinaryRefAddr(
                      propertyName,
                      SerializableUtils.toByteArray(
                          val, indirector, IndirectPolicy.INDIRECT_ON_EXCEPTION));
            refAddrs.add(addMe);
          }
        } else {
          // 				System.err.println(this.getClass().getName() +
          // 						   ": Skipping " + propertyName + " because it is " + (setter == null ?
          // "read-only." : "write-only."));

          if (logger.isLoggable(MLevel.WARNING))
            logger.warning(
                this.getClass().getName()
                    + ": Skipping "
                    + propertyName
                    + " because it is "
                    + (setter == null ? "read-only." : "write-only."));
        }
      }
      Reference out =
          new Reference(bean.getClass().getName(), factoryClassName, factoryClassLocation);
      for (Iterator ii = refAddrs.iterator(); ii.hasNext(); ) out.add((RefAddr) ii.next());
      return out;
    } catch (Exception e) {
      // e.printStackTrace();
      if (Debug.DEBUG && logger.isLoggable(MLevel.FINE))
        logger.log(MLevel.FINE, "Exception trying to create Reference.", e);

      throw new NamingException("Could not create reference from bean: " + e.toString());
    }
  }
}
public abstract class AbstractPoolBackedDataSource extends PoolBackedDataSourceBase
    implements PooledDataSource {
  static final MLogger logger = MLog.getLogger(AbstractPoolBackedDataSource.class);

  static final String NO_CPDS_ERR_MSG =
      "Attempted to use an uninitialized PoolBackedDataSource. "
          + "Please call setConnectionPoolDataSource( ... ) to initialize.";

  // MT: protected by this' lock
  transient C3P0PooledConnectionPoolManager poolManager;
  transient boolean is_closed = false;
  // MT: end protected by this' lock

  protected AbstractPoolBackedDataSource(boolean autoregister) {
    super(autoregister);
    setUpPropertyEvents();
  }

  protected AbstractPoolBackedDataSource(String configName) {
    this(true);
    initializeNamedConfig(configName);
  }

  private void setUpPropertyEvents() {
    PropertyChangeListener l =
        new PropertyChangeListener() {
          public void propertyChange(PropertyChangeEvent evt) {
            resetPoolManager();
          }
        };
    this.addPropertyChangeListener(l);
  }

  protected void initializeNamedConfig(String configName) {
    try {
      if (configName != null) {
        C3P0Config.bindNamedConfigToBean(this, configName);
        if (this.getDataSourceName()
            .equals(this.getIdentityToken())) // dataSourceName has not been specified in config
        this.setDataSourceName(configName);
      }
    } catch (Exception e) {
      if (logger.isLoggable(MLevel.WARNING))
        logger.log(
            MLevel.WARNING,
            "Error binding PoolBackedDataSource to named-config '"
                + configName
                + "'. Some default-config values may be used.",
            e);
    }
  }

  //  Commented out method is just super.getReference() with a lot of extra printing

  //  public javax.naming.Reference getReference() throws javax.naming.NamingException
  //  {
  //  System.err.println("getReference()!!!!");
  //  new Exception("PRINT-STACK-TRACE").printStackTrace();
  //  javax.naming.Reference out = super.getReference();
  //  System.err.println(out);
  //  return out;
  //  }

  // report our ID token as dataSourceName if we have no
  // name explicitly set
  public String getDataSourceName() {
    String out = super.getDataSourceName();
    if (out == null) out = this.getIdentityToken();
    return out;
  }

  // implementation of javax.sql.DataSource
  public Connection getConnection() throws SQLException {
    PooledConnection pc = getPoolManager().getPool().checkoutPooledConnection();
    return pc.getConnection();
  }

  public Connection getConnection(String username, String password) throws SQLException {
    PooledConnection pc = getPoolManager().getPool(username, password).checkoutPooledConnection();
    return pc.getConnection();
  }

  public PrintWriter getLogWriter() throws SQLException {
    return assertCpds().getLogWriter();
  }

  public void setLogWriter(PrintWriter out) throws SQLException {
    assertCpds().setLogWriter(out);
  }

  public int getLoginTimeout() throws SQLException {
    return assertCpds().getLoginTimeout();
  }

  public void setLoginTimeout(int seconds) throws SQLException {
    assertCpds().setLoginTimeout(seconds);
  }

  // implementation of com.mchange.v2.c3p0.PoolingDataSource
  public int getNumConnections() throws SQLException {
    return getPoolManager().getPool().getNumConnections();
  }

  public int getNumIdleConnections() throws SQLException {
    return getPoolManager().getPool().getNumIdleConnections();
  }

  public int getNumBusyConnections() throws SQLException {
    return getPoolManager().getPool().getNumBusyConnections();
  }

  public int getNumUnclosedOrphanedConnections() throws SQLException {
    return getPoolManager().getPool().getNumUnclosedOrphanedConnections();
  }

  public int getNumConnectionsDefaultUser() throws SQLException {
    return getNumConnections();
  }

  public int getNumIdleConnectionsDefaultUser() throws SQLException {
    return getNumIdleConnections();
  }

  public int getNumBusyConnectionsDefaultUser() throws SQLException {
    return getNumBusyConnections();
  }

  public int getNumUnclosedOrphanedConnectionsDefaultUser() throws SQLException {
    return getNumUnclosedOrphanedConnections();
  }

  public int getStatementCacheNumStatementsDefaultUser() throws SQLException {
    return getPoolManager().getPool().getStatementCacheNumStatements();
  }

  public int getStatementCacheNumCheckedOutDefaultUser() throws SQLException {
    return getPoolManager().getPool().getStatementCacheNumCheckedOut();
  }

  public int getStatementCacheNumConnectionsWithCachedStatementsDefaultUser() throws SQLException {
    return getPoolManager().getPool().getStatementCacheNumConnectionsWithCachedStatements();
  }

  public float getEffectivePropertyCycleDefaultUser() throws SQLException {
    return getPoolManager().getPool().getEffectivePropertyCycle();
  }

  public long getStartTimeMillisDefaultUser() throws SQLException {
    return getPoolManager().getPool().getStartTime();
  }

  public long getUpTimeMillisDefaultUser() throws SQLException {
    return getPoolManager().getPool().getUpTime();
  }

  public long getNumFailedCheckinsDefaultUser() throws SQLException {
    return getPoolManager().getPool().getNumFailedCheckins();
  }

  public long getNumFailedCheckoutsDefaultUser() throws SQLException {
    return getPoolManager().getPool().getNumFailedCheckouts();
  }

  public long getNumFailedIdleTestsDefaultUser() throws SQLException {
    return getPoolManager().getPool().getNumFailedIdleTests();
  }

  public int getNumThreadsAwaitingCheckoutDefaultUser() throws SQLException {
    return getPoolManager().getPool().getNumThreadsAwaitingCheckout();
  }

  public int getThreadPoolSize() throws SQLException {
    return getPoolManager().getThreadPoolSize();
  }

  public int getThreadPoolNumActiveThreads() throws SQLException {
    return getPoolManager().getThreadPoolNumActiveThreads();
  }

  public int getThreadPoolNumIdleThreads() throws SQLException {
    return getPoolManager().getThreadPoolNumIdleThreads();
  }

  public int getThreadPoolNumTasksPending() throws SQLException {
    return getPoolManager().getThreadPoolNumTasksPending();
  }

  public String sampleThreadPoolStackTraces() throws SQLException {
    return getPoolManager().getThreadPoolStackTraces();
  }

  public String sampleThreadPoolStatus() throws SQLException {
    return getPoolManager().getThreadPoolStatus();
  }

  public String sampleStatementCacheStatusDefaultUser() throws SQLException {
    return getPoolManager().getPool().dumpStatementCacheStatus();
  }

  public String sampleStatementCacheStatus(String username, String password) throws SQLException {
    return assertAuthPool(username, password).dumpStatementCacheStatus();
  }

  public Throwable getLastAcquisitionFailureDefaultUser() throws SQLException {
    return getPoolManager().getPool().getLastAcquisitionFailure();
  }

  public Throwable getLastCheckinFailureDefaultUser() throws SQLException {
    return getPoolManager().getPool().getLastCheckinFailure();
  }

  public Throwable getLastCheckoutFailureDefaultUser() throws SQLException {
    return getPoolManager().getPool().getLastCheckoutFailure();
  }

  public Throwable getLastIdleTestFailureDefaultUser() throws SQLException {
    return getPoolManager().getPool().getLastIdleTestFailure();
  }

  public Throwable getLastConnectionTestFailureDefaultUser() throws SQLException {
    return getPoolManager().getPool().getLastConnectionTestFailure();
  }

  public Throwable getLastAcquisitionFailure(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getLastAcquisitionFailure();
  }

  public Throwable getLastCheckinFailure(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getLastCheckinFailure();
  }

  public Throwable getLastCheckoutFailure(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getLastCheckoutFailure();
  }

  public Throwable getLastIdleTestFailure(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getLastIdleTestFailure();
  }

  public Throwable getLastConnectionTestFailure(String username, String password)
      throws SQLException {
    return assertAuthPool(username, password).getLastConnectionTestFailure();
  }

  public int getNumThreadsAwaitingCheckout(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumThreadsAwaitingCheckout();
  }

  public String sampleLastAcquisitionFailureStackTraceDefaultUser() throws SQLException {
    Throwable t = getLastAcquisitionFailureDefaultUser();
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastCheckinFailureStackTraceDefaultUser() throws SQLException {
    Throwable t = getLastCheckinFailureDefaultUser();
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastCheckoutFailureStackTraceDefaultUser() throws SQLException {
    Throwable t = getLastCheckoutFailureDefaultUser();
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastIdleTestFailureStackTraceDefaultUser() throws SQLException {
    Throwable t = getLastIdleTestFailureDefaultUser();
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastConnectionTestFailureStackTraceDefaultUser() throws SQLException {
    Throwable t = getLastConnectionTestFailureDefaultUser();
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastAcquisitionFailureStackTrace(String username, String password)
      throws SQLException {
    Throwable t = getLastAcquisitionFailure(username, password);
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastCheckinFailureStackTrace(String username, String password)
      throws SQLException {
    Throwable t = getLastCheckinFailure(username, password);
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastCheckoutFailureStackTrace(String username, String password)
      throws SQLException {
    Throwable t = getLastCheckoutFailure(username, password);
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastIdleTestFailureStackTrace(String username, String password)
      throws SQLException {
    Throwable t = getLastIdleTestFailure(username, password);
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public String sampleLastConnectionTestFailureStackTrace(String username, String password)
      throws SQLException {
    Throwable t = getLastConnectionTestFailure(username, password);
    return t == null ? null : ThrowableUtils.extractStackTrace(t);
  }

  public void softResetDefaultUser() throws SQLException {
    getPoolManager().getPool().reset();
  }

  public int getNumConnections(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumConnections();
  }

  public int getNumIdleConnections(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumIdleConnections();
  }

  public int getNumBusyConnections(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumBusyConnections();
  }

  public int getNumUnclosedOrphanedConnections(String username, String password)
      throws SQLException {
    return assertAuthPool(username, password).getNumUnclosedOrphanedConnections();
  }

  public int getStatementCacheNumStatements(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getStatementCacheNumStatements();
  }

  public int getStatementCacheNumCheckedOut(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getStatementCacheNumCheckedOut();
  }

  public int getStatementCacheNumConnectionsWithCachedStatements(String username, String password)
      throws SQLException {
    return assertAuthPool(username, password).getStatementCacheNumConnectionsWithCachedStatements();
  }

  public float getEffectivePropertyCycle(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getEffectivePropertyCycle();
  }

  public long getStartTimeMillis(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getStartTime();
  }

  public long getUpTimeMillis(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getUpTime();
  }

  public long getNumFailedCheckins(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumFailedCheckins();
  }

  public long getNumFailedCheckouts(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumFailedCheckouts();
  }

  public long getNumFailedIdleTests(String username, String password) throws SQLException {
    return assertAuthPool(username, password).getNumFailedIdleTests();
  }

  public void softReset(String username, String password) throws SQLException {
    assertAuthPool(username, password).reset();
  }

  public int getNumBusyConnectionsAllUsers() throws SQLException {
    return getPoolManager().getNumBusyConnectionsAllAuths();
  }

  public int getNumIdleConnectionsAllUsers() throws SQLException {
    return getPoolManager().getNumIdleConnectionsAllAuths();
  }

  public int getNumConnectionsAllUsers() throws SQLException {
    return getPoolManager().getNumConnectionsAllAuths();
  }

  public int getNumUnclosedOrphanedConnectionsAllUsers() throws SQLException {
    return getPoolManager().getNumUnclosedOrphanedConnectionsAllAuths();
  }

  public int getStatementCacheNumStatementsAllUsers() throws SQLException {
    return getPoolManager().getStatementCacheNumStatementsAllUsers();
  }

  public int getStatementCacheNumCheckedOutStatementsAllUsers() throws SQLException {
    return getPoolManager().getStatementCacheNumCheckedOutStatementsAllUsers();
  }

  public synchronized int getStatementCacheNumConnectionsWithCachedStatementsAllUsers()
      throws SQLException {
    return getPoolManager().getStatementCacheNumConnectionsWithCachedStatementsAllUsers();
  }

  public void softResetAllUsers() throws SQLException {
    getPoolManager().softResetAllAuths();
  }

  public int getNumUserPools() throws SQLException {
    return getPoolManager().getNumManagedAuths();
  }

  public Collection getAllUsers() throws SQLException {
    LinkedList out = new LinkedList();
    Set auths = getPoolManager().getManagedAuths();
    for (Iterator ii = auths.iterator(); ii.hasNext(); ) out.add(((DbAuth) ii.next()).getUser());
    return Collections.unmodifiableList(out);
  }

  public synchronized void hardReset() {
    resetPoolManager();
  }

  public synchronized void close() {
    resetPoolManager();
    is_closed = true;

    C3P0Registry.markClosed(this);

    if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX && logger.isLoggable(MLevel.FINEST)) {
      logger.log(
          MLevel.FINEST,
          this.getClass().getName()
              + '@'
              + Integer.toHexString(System.identityHashCode(this))
              + " has been closed. ",
          new Exception("DEBUG STACK TRACE for PoolBackedDataSource.close()."));
    }
  }

  /**
   * @deprecated the force_destroy argument is now meaningless, as pools are no longer potentially
   *     shared between multiple DataSources.
   */
  public void close(boolean force_destroy) {
    close();
  }

  // other code
  public synchronized void
      resetPoolManager() // used by other, wrapping datasources in package, and in mbean package
      {
    resetPoolManager(true);
  }

  public synchronized void resetPoolManager(
      boolean
          close_checked_out_connections) // used by other, wrapping datasources in package, and in
                                         // mbean package
      {
    if (poolManager != null) {
      poolManager.close(close_checked_out_connections);
      poolManager = null;
    }
  }

  private synchronized ConnectionPoolDataSource assertCpds() throws SQLException {
    if (is_closed) throw new SQLException(this + " has been closed() -- you can no longer use it.");

    ConnectionPoolDataSource out = this.getConnectionPoolDataSource();
    if (out == null) throw new SQLException(NO_CPDS_ERR_MSG);
    return out;
  }

  private synchronized C3P0PooledConnectionPoolManager getPoolManager() throws SQLException {
    if (poolManager == null) {
      ConnectionPoolDataSource cpds = assertCpds();
      poolManager =
          new C3P0PooledConnectionPoolManager(
              cpds, null, null, this.getNumHelperThreads(), this.getIdentityToken());
      if (logger.isLoggable(MLevel.INFO))
        logger.info(
            "Initializing c3p0 pool... "
                + this.toString() /* + "; using pool manager: " + poolManager */);
    }
    return poolManager;
  }

  private C3P0PooledConnectionPool assertAuthPool(String username, String password)
      throws SQLException {
    C3P0PooledConnectionPool authPool = getPoolManager().getPool(username, password, false);
    if (authPool == null)
      throw new SQLException(
          "No pool has been yet been established for Connections authenticated by user '"
              + username
              + "' with the password provided. [Use getConnection( username, password ) "
              + "to initialize such a pool.]");
    else return authPool;
  }

  // serialization stuff -- set up bound/constrained property event handlers on deserialization
  private static final long serialVersionUID = 1;
  private static final short VERSION = 0x0001;

  private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.writeShort(VERSION);
  }

  private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    short version = ois.readShort();
    switch (version) {
      case VERSION:
        setUpPropertyEvents();
        break;
      default:
        throw new IOException("Unsupported Serialized Version: " + version);
    }
  }
}
public class DefaultC3P0ConfigFinder implements C3P0ConfigFinder {
  static final String XML_CFG_FILE_KEY = "com.mchange.v2.c3p0.cfg.xml";
  static final String CLASSLOADER_RESOURCE_PREFIX = "classloader:";

  static final MLogger logger = MLog.getLogger(DefaultC3P0ConfigFinder.class);

  final boolean warn_of_xml_overrides;

  public DefaultC3P0ConfigFinder(boolean warn_of_xml_overrides) {
    this.warn_of_xml_overrides = warn_of_xml_overrides;
  }

  public DefaultC3P0ConfigFinder() {
    this(false);
  }

  public C3P0Config findConfig() throws Exception {
    C3P0Config out;

    HashMap flatDefaults = C3P0ConfigUtils.extractHardcodedC3P0Defaults();

    // this includes System properties, but we have to check for System properties
    // again, since we want system properties to override unspecified user, default-config
    // properties in the XML
    flatDefaults.putAll(C3P0ConfigUtils.extractC3P0PropertiesResources());

    String cfgFile = C3P0Config.getPropsFileConfigProperty(XML_CFG_FILE_KEY);
    if (cfgFile == null) {
      C3P0Config xmlConfig = C3P0ConfigXmlUtils.extractXmlConfigFromDefaultResource();
      if (xmlConfig != null) {
        insertDefaultsUnderNascentConfig(flatDefaults, xmlConfig);
        out = xmlConfig;

        mbOverrideWarning("resource", C3P0ConfigXmlUtils.XML_CONFIG_RSRC_PATH);
      } else out = C3P0ConfigUtils.configFromFlatDefaults(flatDefaults);
    } else {
      cfgFile = cfgFile.trim();

      InputStream is = null;
      try {
        if (cfgFile.startsWith(CLASSLOADER_RESOURCE_PREFIX)) {
          ClassLoader cl = this.getClass().getClassLoader();
          String rsrcPath = cfgFile.substring(CLASSLOADER_RESOURCE_PREFIX.length());

          // eliminate leading slash because ClassLoader.getResource
          // is always absolute and does not expect a leading slash
          if (rsrcPath.startsWith("/")) rsrcPath = rsrcPath.substring(1);

          is = cl.getResourceAsStream(rsrcPath);
          if (is == null)
            throw new FileNotFoundException(
                "Specified ClassLoader resource '"
                    + rsrcPath
                    + "' could not be found. "
                    + "[ Found in configuration: "
                    + XML_CFG_FILE_KEY
                    + '='
                    + cfgFile
                    + " ]");

          mbOverrideWarning("resource", rsrcPath);
        } else {
          is = new BufferedInputStream(new FileInputStream(cfgFile));
          mbOverrideWarning("file", cfgFile);
        }

        C3P0Config xmlConfig = C3P0ConfigXmlUtils.extractXmlConfigFromInputStream(is);
        insertDefaultsUnderNascentConfig(flatDefaults, xmlConfig);
        out = xmlConfig;
      } finally {
        try {
          if (is != null) is.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

    // overwrite default, unspecified user config with System properties
    // defined values
    Properties sysPropConfig = C3P0ConfigUtils.findAllC3P0SystemProperties();
    out.defaultConfig.props.putAll(sysPropConfig);

    return out;
  }

  private void insertDefaultsUnderNascentConfig(HashMap flatDefaults, C3P0Config config) {
    flatDefaults.putAll(config.defaultConfig.props);
    config.defaultConfig.props = flatDefaults;
  }

  private void mbOverrideWarning(String srcType, String srcName) {
    if (warn_of_xml_overrides && logger.isLoggable(MLevel.WARNING))
      logger.log(
          MLevel.WARNING,
          "Configuation defined in "
              + srcType
              + "'"
              + srcName
              + "' overrides all other c3p0 config.");
  }
}