entry = iterator.next();
+ sb.append(entry.getKey()).append("=").append(entry.getValue());
+
+ if (iterator.hasNext())
+ sb.append(":");
+ }
+ }
+
+ sb.append("-");
+ if (bootstrapContextName != null && !bootstrapContextName.trim().equals(""))
+ {
+ sb.append(bootstrapContextName);
+ }
+ else
+ {
+ sb.append(defaultBootstrapContext.getName());
+ }
+
+ return sb.toString();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bootstrapcontext/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bootstrapcontext/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bootstrapcontext/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,6 @@
+
+This package contains implementations of the BootstrapContext interface.
+
+IronJacamar extends javax.resource.spi.BootstrapContext with a org.jboss.jca.core.api.CloneableBootstrapContext
+interface in order to allow different implementations to be used for the resource adapter deployments.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/BeanValidation.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/BeanValidation.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/BeanValidation.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,138 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.bv;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.validation.Configuration;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+
+/**
+ * Bean validation implementation backed by Hibernate Validator
+ *
+ * @author Jesper Pedersen
+ * @version $Revision: $
+ */
+public class BeanValidation
+{
+ /** Validator factory */
+ private static final String VALIDATOR_FACTORY = "java:/ValidatorFactory";
+
+ /** Validator */
+ private static final String VALIDATOR = "java:/Validator";
+
+ /** The validator factory */
+ private ValidatorFactory validatorFactory;
+
+ /** The validator */
+ private Validator validator;
+
+ /**
+ * Constructor
+ */
+ public BeanValidation()
+ {
+ Configuration configuration = Validation.byDefaultProvider().configure();
+ Configuration> conf = configuration.traversableResolver(new JCATraversableResolver());
+
+ validatorFactory = conf.buildValidatorFactory();
+ validator = validatorFactory.getValidator();
+ }
+
+ /**
+ * Get the validator factory
+ * @return The factory
+ */
+ public ValidatorFactory getValidatorFactory()
+ {
+ return validatorFactory;
+ }
+
+ /**
+ * Get the validator
+ * @return The validator
+ */
+ public Validator getValidator()
+ {
+ return validator;
+ }
+
+ /**
+ * Start
+ * @exception Throwable If an error occurs
+ */
+ public void start() throws Throwable
+ {
+ Context context = null;
+ try
+ {
+ context = new InitialContext();
+
+ context.rebind(VALIDATOR_FACTORY, new SerializableValidatorFactory(validatorFactory));
+ context.rebind(VALIDATOR, new SerializableValidator(validator));
+ }
+ finally
+ {
+ try
+ {
+ if (context != null)
+ context.close();
+ }
+ catch (NamingException ne)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ /**
+ * Stop
+ * @exception Throwable If an error occurs
+ */
+ public void stop() throws Throwable
+ {
+ Context context = null;
+ try
+ {
+ context = new InitialContext();
+
+ context.unbind(VALIDATOR);
+ context.unbind(VALIDATOR_FACTORY);
+ }
+ finally
+ {
+ try
+ {
+ if (context != null)
+ context.close();
+ }
+ catch (NamingException ne)
+ {
+ // Ignore
+ }
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/BeanValidationUtil.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/BeanValidationUtil.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/BeanValidationUtil.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,67 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.bv;
+
+import javax.validation.Configuration;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+
+/**
+ * Bean validation utility
+ *
+ * @author Jesper Pedersen
+ * @version $Revision: $
+ */
+public class BeanValidationUtil
+{
+ /**
+ * Constructor
+ */
+ private BeanValidationUtil()
+ {
+ }
+
+ /**
+ * Create a validator factory
+ * @return The factory
+ */
+ public static ValidatorFactory createValidatorFactory()
+ {
+ Configuration configuration = Validation.byDefaultProvider().configure();
+ Configuration> conf = configuration.traversableResolver(new JCATraversableResolver());
+
+ return conf.buildValidatorFactory();
+ }
+
+ /**
+ * Create a validator
+ * @return The validator
+ */
+ public static Validator createValidator()
+ {
+ ValidatorFactory vf = createValidatorFactory();
+
+ return vf.getValidator();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/JCATraversableResolver.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/JCATraversableResolver.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/JCATraversableResolver.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,91 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.bv;
+
+import java.lang.annotation.ElementType;
+
+import javax.validation.Path;
+import javax.validation.TraversableResolver;
+
+/**
+ * JCATraversableResolver
+ * @author Jeff Zhang
+ * @version $Revision: $
+ */
+public class JCATraversableResolver implements TraversableResolver
+{
+ /**
+ * Determine if Bean Validation is allowed to reach the property state
+ *
+ * @param traversableObject
+ * object hosting traversableProperty
or null if
+ * validateValue is called
+ * @param traversableProperty
+ * the traversable property.
+ * @param rootBeanType
+ * type of the root object passed to the Validator.
+ * @param pathToTraversableObject
+ * path from the root object to traversableObject
+ * (using the path specification defined by Bean Validator).
+ * @param elementType
+ * either FIELD
or METHOD
.
+ *
+ * @return true
if Bean Validation is allowed to reach the
+ * property state, false
otherwise.
+ */
+ public boolean isReachable(Object traversableObject, Path.Node traversableProperty,
+ Class> rootBeanType, Path pathToTraversableObject,
+ ElementType elementType)
+ {
+ return true;
+ }
+
+ /**
+ * Determine if Bean Validation is allowed to cascade validation on the bean
+ * instance returned by the property value marked as @Valid
.
+ * Note that this method is called only if isReachable returns true for the
+ * same set of arguments and if the property is marked as @Valid
+ *
+ * @param traversableObject
+ * object hosting traversableProperty
or null if
+ * validateValue is called
+ * @param traversableProperty
+ * the traversable property.
+ * @param rootBeanType
+ * type of the root object passed to the Validator.
+ * @param pathToTraversableObject
+ * path from the root object to traversableObject
+ * (using the path specification defined by Bean Validator).
+ * @param elementType
+ * either FIELD
or METHOD
.
+ *
+ * @return true
if Bean Validation is allowed to cascade
+ * validation, false
otherwise.
+ */
+ public boolean isCascadable(Object traversableObject,
+ Path.Node traversableProperty, Class> rootBeanType,
+ Path pathToTraversableObject, ElementType elementType)
+ {
+ return true;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/SerializableValidator.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/SerializableValidator.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/SerializableValidator.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,137 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.bv;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+import javax.validation.executable.ExecutableValidator;
+import javax.validation.metadata.BeanDescriptor;
+
+/**
+ * Serializable validator
+ *
+ * @author Jesper Pedersen
+ * @version $Revision: $
+ */
+public class SerializableValidator implements Validator, Serializable
+{
+ /** Serial version uid */
+ private static final long serialVersionUID = 2L;
+
+ /** The validator */
+ private transient Validator validator;
+
+ /**
+ * Constructor
+ */
+ public SerializableValidator()
+ {
+ this(BeanValidationUtil.createValidator());
+ }
+
+ /**
+ * Constructor
+ * @param v The validator
+ */
+ public SerializableValidator(Validator v)
+ {
+ this.validator = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public BeanDescriptor getConstraintsForClass(Class> clazz)
+ {
+ return validator.getConstraintsForClass(clazz);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set> validate(T object, Class>... groups)
+ {
+ return validator.validate(object, groups);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set> validateProperty(T object, String propertyName, Class>... groups)
+ {
+ return validator.validateProperty(object, propertyName, groups);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set> validateValue(Class beanType,
+ String propertyName,
+ Object value,
+ Class>... groups)
+ {
+ return validator.validateValue(beanType, propertyName, value, groups);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public T unwrap(Class type)
+ {
+ return validator.unwrap(type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ExecutableValidator forExecutables()
+ {
+ return validator.forExecutables();
+ }
+
+ /**
+ * Write the object - Nothing is written as the validator factory is transient
+ * @param out The output stream
+ * @exception IOException Thrown if an error occurs
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ }
+
+ /**
+ * Read the object - Nothing is read as the validator factory is transient.
+ * A new instance is created
+ * @param out The output stream
+ * @exception IOException Thrown if an error occurs
+ */
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ validator = BeanValidationUtil.createValidator();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/SerializableValidatorFactory.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/SerializableValidatorFactory.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/SerializableValidatorFactory.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,152 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.bv;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.TraversableResolver;
+import javax.validation.Validator;
+import javax.validation.ValidatorContext;
+import javax.validation.ValidatorFactory;
+
+/**
+ * Serializable validator factory
+ *
+ * @author Jesper Pedersen
+ * @version $Revision: $
+ */
+public class SerializableValidatorFactory implements ValidatorFactory, Serializable
+{
+ /** Serial version uid */
+ private static final long serialVersionUID = 2L;
+
+ /** The validator factory */
+ private transient ValidatorFactory validatorFactory;
+
+ /**
+ * Constructor
+ */
+ public SerializableValidatorFactory()
+ {
+ this(BeanValidationUtil.createValidatorFactory());
+ }
+
+ /**
+ * Constructor
+ * @param vf The validator factory
+ */
+ public SerializableValidatorFactory(ValidatorFactory vf)
+ {
+ this.validatorFactory = vf;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MessageInterpolator getMessageInterpolator()
+ {
+ return validatorFactory.getMessageInterpolator();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Validator getValidator()
+ {
+ return validatorFactory.getValidator();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ValidatorContext usingContext()
+ {
+ return validatorFactory.usingContext();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public T unwrap(Class type)
+ {
+ return validatorFactory.unwrap(type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConstraintValidatorFactory getConstraintValidatorFactory()
+ {
+ return validatorFactory.getConstraintValidatorFactory();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TraversableResolver getTraversableResolver()
+ {
+ return validatorFactory.getTraversableResolver();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ParameterNameProvider getParameterNameProvider()
+ {
+ return validatorFactory.getParameterNameProvider();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close()
+ {
+ validatorFactory.close();
+ }
+
+ /**
+ * Write the object - Nothing is written as the validator factory is transient
+ * @param out The output stream
+ * @exception IOException Thrown if an error occurs
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ }
+
+ /**
+ * Read the object - Nothing is read as the validator factory is transient.
+ * A new instance is created
+ * @param out The output stream
+ * @exception IOException Thrown if an error occurs
+ */
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ validatorFactory = BeanValidationUtil.createValidatorFactory();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/bv/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the bean validation service.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,1077 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager;
+
+import org.jboss.jca.common.api.metadata.common.FlushStrategy;
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager;
+import org.jboss.jca.core.api.management.ManagedEnlistmentTrace;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionState;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.spi.graceful.GracefulCallback;
+import org.jboss.jca.core.spi.security.SubjectFactory;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.RetryableException;
+import javax.resource.spi.security.PasswordCredential;
+import javax.security.auth.Subject;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+
+import org.jboss.logging.Messages;
+
+/**
+ * AbstractConnectionManager.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public abstract class AbstractConnectionManager implements ConnectionManager
+{
+ /** Empty graceful shutdown call back */
+ private static final GracefulCallback EMPTY_CALL_BACK = new GracefulCallback()
+ {
+ @Override public void cancel()
+ {
+ // do nothing
+ }
+
+ @Override public void done()
+ {
+ // do nothing
+ }
+ };
+
+
+ /** Log instance */
+ private final CoreLogger log;
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** The pool */
+ private Pool pool;
+
+ /** Security domain */
+ private String securityDomain;
+
+ /** SubjectFactory */
+ private SubjectFactory subjectFactory;
+
+ /** The flush strategy */
+ private FlushStrategy flushStrategy;
+
+ /** Number of retry to allocate connection */
+ private int allocationRetry;
+
+ /** Interval between retries */
+ private long allocationRetryWaitMillis;
+
+ /** Startup/ShutDown flag */
+ private final AtomicBoolean shutdown = new AtomicBoolean(false);
+
+ /** Scheduled executor for graceful shutdown */
+ private ScheduledExecutorService scheduledExecutorService;
+
+ /** Graceful job */
+ private ScheduledFuture scheduledGraceful;
+
+ /** Graceful call back. A non-null value indicates shutdown is prepared but has not started. */
+ private volatile GracefulCallback gracefulCallback;
+
+ /** Cached connection manager */
+ private CachedConnectionManager cachedConnectionManager;
+
+ /** Jndi name */
+ private String jndiName;
+
+ /** Sharable */
+ private boolean sharable;
+
+ /** Enlistment */
+ protected boolean enlistment;
+
+ /** Connectable */
+ protected boolean connectable;
+
+ /** Tracking */
+ protected Boolean tracking;
+
+ /** Enlistment trace */
+ protected ManagedEnlistmentTrace enlistmentTrace;
+
+ /**
+ * Creates a new instance of connection manager.
+ */
+ protected AbstractConnectionManager()
+ {
+ this.log = getLogger();
+ this.scheduledExecutorService = null;
+ this.scheduledGraceful = null;
+ this.gracefulCallback = null;
+ }
+
+ /**
+ * Get the logger.
+ * @return The value
+ */
+ protected abstract CoreLogger getLogger();
+
+ /**
+ * Set the pool.
+ * @param pool the pool
+ */
+ public void setPool(Pool pool)
+ {
+ this.pool = pool;
+ }
+
+ /**
+ * Get the pool.
+ * @return the pool
+ */
+ public Pool getPool()
+ {
+ return pool;
+ }
+
+ /**
+ * Sets cached connection manager.
+ * @param cachedConnectionManager cached connection manager
+ */
+ public void setCachedConnectionManager(CachedConnectionManager cachedConnectionManager)
+ {
+ this.cachedConnectionManager = cachedConnectionManager;
+ }
+
+ /**
+ * Gets cached connection manager.
+ * @return cached connection manager
+ */
+ public CachedConnectionManager getCachedConnectionManager()
+ {
+ return cachedConnectionManager;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean cancelShutdown()
+ {
+ if (scheduledGraceful != null)
+ {
+ boolean result = scheduledGraceful.cancel(false);
+
+ if (result)
+ {
+ shutdown.set(false);
+
+ if (gracefulCallback != null)
+ gracefulCallback.cancel();
+
+ if (pool != null)
+ pool.cancelShutdown();
+
+ scheduledGraceful = null;
+ gracefulCallback = null;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (shutdown.get())
+ {
+ shutdown.set(false);
+
+ if (gracefulCallback != null)
+ gracefulCallback.cancel();
+
+ if (pool != null)
+ pool.cancelShutdown();
+
+ gracefulCallback = null;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prepareShutdown()
+ {
+ prepareShutdown(0, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prepareShutdown(GracefulCallback cb)
+ {
+ prepareShutdown(0, cb);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prepareShutdown(int seconds)
+ {
+ prepareShutdown(seconds, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prepareShutdown(int seconds, GracefulCallback cb)
+ {
+ shutdown.set(true);
+
+ // use gracefulCallback as an indicator that shutdown is prepared and not started, for that reason this field
+ // will never be null after preparation and before shutdown (this prevents adding an extra field,
+ // shutdownPrepared, or having to replace shutdown by a state field)
+ if (gracefulCallback == null)
+ gracefulCallback = cb == null ? EMPTY_CALL_BACK : cb;
+
+ if (pool != null)
+ pool.prepareShutdown();
+
+ if (seconds > 0)
+ {
+ if (scheduledGraceful == null)
+ {
+ if (scheduledExecutorService == null)
+ scheduledExecutorService = Executors.newScheduledThreadPool(1);
+
+ scheduledGraceful =
+ scheduledExecutorService.schedule(new ConnectionManagerShutdown(this), seconds, TimeUnit.SECONDS);
+ }
+ }
+ else
+ {
+ if (pool != null && pool.isIdle())
+ {
+ synchronized (this)
+ {
+ // skip shutdown if there is another thread already taking care of it
+ if (gracefulCallback == null)
+ return;
+ }
+ shutdown();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void shutdown()
+ {
+ getLogger().debugf("%s: shutdown", jndiName);
+ final GracefulCallback gracefulCallback;
+ final ScheduledExecutorService scheduledExecutorService;
+ synchronized (this)
+ {
+ shutdown.set(true);
+ gracefulCallback = this.gracefulCallback;
+ this.gracefulCallback = null;
+ scheduledExecutorService = this.scheduledExecutorService;
+ this.scheduledExecutorService = null;
+ }
+
+ if (pool != null)
+ pool.shutdown();
+
+ if (scheduledExecutorService != null)
+ {
+ if (scheduledGraceful != null && !scheduledGraceful.isDone())
+ scheduledGraceful.cancel(true);
+
+ scheduledGraceful = null;
+ scheduledExecutorService.shutdownNow();
+ }
+
+ if (gracefulCallback != null)
+ {
+ gracefulCallback.done();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isShutdown()
+ {
+ return shutdown.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDelay()
+ {
+ if (scheduledGraceful != null)
+ return (int)scheduledGraceful.getDelay(TimeUnit.SECONDS);
+
+ if (shutdown.get())
+ return Integer.MIN_VALUE;
+
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Gets jndi name.
+ * @return jndi name
+ */
+ public String getJndiName()
+ {
+ return jndiName;
+ }
+
+ /**
+ * Sets jndi name.
+ * @param jndiName jndi name
+ */
+ public void setJndiName(String jndiName)
+ {
+ this.jndiName = jndiName;
+ }
+
+ /**
+ * Is sharable
+ * @return The value
+ */
+ public boolean isSharable()
+ {
+ return sharable;
+ }
+
+ /**
+ * Set the sharable flag
+ * @param v The value
+ */
+ public void setSharable(boolean v)
+ {
+ this.sharable = v;
+
+ log.tracef("sharable=%s", sharable);
+ }
+
+ /**
+ * Is enlistment
+ * @return The value
+ */
+ public boolean isEnlistment()
+ {
+ return enlistment;
+ }
+
+ /**
+ * Set the enlistment flag
+ * @param v The value
+ */
+ public void setEnlistment(boolean v)
+ {
+ this.enlistment = v;
+
+ log.tracef("enlistment=%s", enlistment);
+ }
+
+ /**
+ * Is connectable
+ * @return The value
+ */
+ public boolean isConnectable()
+ {
+ return connectable;
+ }
+
+ /**
+ * Set the connectable flag
+ * @param v The value
+ */
+ public void setConnectable(boolean v)
+ {
+ this.connectable = v;
+
+ log.tracef("connectable=%s", connectable);
+ }
+
+ /**
+ * Get tracking
+ * @return The value
+ */
+ public Boolean getTracking()
+ {
+ return tracking;
+ }
+
+ /**
+ * Set the tracking flag
+ * @param v The value
+ */
+ public void setTracking(Boolean v)
+ {
+ this.tracking = v;
+
+ log.tracef("tracking=%s", tracking);
+ }
+
+ /**
+ * Get enlistment trace
+ * @return The value
+ */
+ public ManagedEnlistmentTrace getEnlistmentTrace()
+ {
+ return enlistmentTrace;
+ }
+
+ /**
+ * Set the enlistment trace flag
+ * @param v The value
+ */
+ public void setEnlistmentTrace(ManagedEnlistmentTrace v)
+ {
+ this.enlistmentTrace = v;
+
+ log.tracef("enlistment_trace=%s", enlistmentTrace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSecurityDomain()
+ {
+ return securityDomain;
+ }
+
+ /**
+ * Sets security domain
+ * @param securityDomain security domain
+ */
+ public void setSecurityDomain(String securityDomain)
+ {
+ this.securityDomain = securityDomain;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SubjectFactory getSubjectFactory()
+ {
+ return subjectFactory;
+ }
+
+ /**
+ * Sets subject factory.
+ * @param subjectFactory subject factory
+ */
+ public void setSubjectFactory(SubjectFactory subjectFactory)
+ {
+ this.subjectFactory = subjectFactory;
+ }
+
+ /**
+ * Get the flush strategy
+ * @return The value
+ */
+ public FlushStrategy getFlushStrategy()
+ {
+ return flushStrategy;
+ }
+
+ /**
+ * Set the flush strategy
+ * @param v The value
+ */
+ public void setFlushStrategy(FlushStrategy v)
+ {
+ this.flushStrategy = v;
+ }
+
+ /**
+ * Gets managed connection factory.
+ * @return managed connection factory
+ */
+ public javax.resource.spi.ManagedConnectionFactory getManagedConnectionFactory()
+ {
+ if (pool == null)
+ {
+ log.tracef("No pooling strategy found! for connection manager : %s", this);
+ return null;
+ }
+ else
+ {
+ return pool.getManagedConnectionFactory();
+ }
+
+ }
+
+ /**
+ * Set the number of allocation retries
+ * @param number retry number
+ */
+ public void setAllocationRetry(int number)
+ {
+ if (number >= 0)
+ allocationRetry = number;
+ }
+
+ /**
+ * Get the number of allocation retries
+ * @return The number of retries
+ */
+ public int getAllocationRetry()
+ {
+ return allocationRetry;
+ }
+
+ /**
+ * Set the wait time between each allocation retry
+ * @param millis wait in ms
+ */
+ public void setAllocationRetryWaitMillis(long millis)
+ {
+ if (millis > 0)
+ allocationRetryWaitMillis = millis;
+ }
+
+ /**
+ * Get the wait time between each allocation retry
+ * @return The millis
+ */
+ public long getAllocationRetryWaitMillis()
+ {
+ return allocationRetryWaitMillis;
+ }
+
+ /**
+ * Public for use in testing pooling functionality by itself.
+ * called by both allocateConnection and reconnect.
+ *
+ * @param subject a Subject
value
+ * @param cri a ConnectionRequestInfo
value
+ * @return a ManagedConnection
value
+ * @exception ResourceException if an error occurs
+ */
+ public ConnectionListener getManagedConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException
+ {
+ return getManagedConnection(null, subject, cri);
+ }
+
+ /**
+ * Get the managed connection from the pool.
+ *
+ * @param transaction the transaction for track by transaction
+ * @param subject the subject
+ * @param cri the ConnectionRequestInfo
+ * @return a managed connection
+ * @exception ResourceException if an error occurs
+ */
+ protected ConnectionListener getManagedConnection(Transaction transaction, Subject subject,
+ ConnectionRequestInfo cri) throws ResourceException
+ {
+ Exception failure = null;
+
+ if (shutdown.get())
+ {
+ throw new ResourceException(bundle.connectionManagerIsShutdown(jndiName));
+ }
+
+ // First attempt
+ boolean isInterrupted = Thread.interrupted();
+ boolean innerIsInterrupted = false;
+ try
+ {
+ return pool.getConnection(transaction, subject, cri);
+ }
+ catch (ResourceException e)
+ {
+ failure = e;
+
+ // Retry?
+ if (allocationRetry != 0 || e instanceof RetryableException)
+ {
+ int to = allocationRetry;
+
+ if (allocationRetry == 0 && e instanceof RetryableException)
+ to = 1;
+
+ for (int i = 0; i < to; i++)
+ {
+ if (shutdown.get())
+ {
+ throw new ResourceException(bundle.connectionManagerIsShutdown(jndiName));
+ }
+
+ log.tracef("%s: Attempting allocation retry (%s, %s, %s)", jndiName, transaction, subject, cri);
+
+ if (Thread.currentThread().isInterrupted())
+ {
+ Thread.interrupted();
+ innerIsInterrupted = true;
+ }
+
+ try
+ {
+ if (allocationRetryWaitMillis != 0)
+ {
+ Thread.sleep(allocationRetryWaitMillis);
+ }
+
+ return pool.getConnection(transaction, subject, cri);
+ }
+ catch (ResourceException re)
+ {
+ failure = re;
+ }
+ catch (InterruptedException ie)
+ {
+ failure = ie;
+ innerIsInterrupted = true;
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ failure = e;
+ }
+ finally
+ {
+ if (isInterrupted || innerIsInterrupted)
+ {
+ Thread.currentThread().interrupt();
+
+ if (innerIsInterrupted)
+ throw new ResourceException(bundle.getManagedConnectionRetryWaitInterrupted(jndiName), failure);
+ }
+ }
+
+ // If we get here all retries failed, throw the lastest failure
+ throw new ResourceException(bundle.unableGetManagedConnection(jndiName), failure);
+ }
+
+ /**
+ * Kill given connection listener wrapped connection instance.
+ * @param bcl connection listener that wraps connection
+ * @param kill kill connection or not
+ */
+ public void returnManagedConnection(org.jboss.jca.core.api.connectionmanager.listener.ConnectionListener bcl,
+ boolean kill)
+ {
+ // Hack - We know that we can type cast it
+ ConnectionListener cl = (ConnectionListener)bcl;
+
+ Pool localStrategy = cl.getPool();
+ if (localStrategy != pool || shutdown.get())
+ {
+ kill = true;
+ }
+
+ try
+ {
+ if (!kill && cl.getState().equals(ConnectionState.NORMAL))
+ {
+ cl.tidyup();
+ }
+ }
+ catch (Throwable t)
+ {
+ log.errorDuringTidyUpConnection(cl, t);
+ kill = true;
+ }
+
+ try
+ {
+ localStrategy.returnConnection(cl, kill);
+ }
+ catch (ResourceException re)
+ {
+ // We can receive notification of an error on the connection
+ // before it has been assigned to the pool. Reduce the noise for
+ // these errors
+ if (kill)
+ {
+ log.debug("ResourceException killing connection", re);
+ }
+ else
+ {
+ log.resourceExceptionReturningConnection(cl.getManagedConnection(), re);
+ }
+ }
+ catch (Exception e)
+ {
+ try
+ {
+ // Something is very wrong, so lets set the state up-front
+ if (cl.getState().equals(ConnectionState.NORMAL))
+ cl.setState(ConnectionState.DESTROY);
+
+ localStrategy.returnConnection(cl, true);
+ }
+ catch (Throwable t)
+ {
+ log.throwableReturningConnection(cl.getManagedConnection(), t);
+ }
+ }
+
+ if (shutdown.get() && pool.isIdle())
+ {
+ synchronized (this)
+ {
+ // skip shutdown if there is another thread already taking care of it
+ if (gracefulCallback == null)
+ return;
+ }
+ shutdown();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object allocateConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo cri) throws ResourceException
+ {
+ //Check for pooling!
+ if (pool == null || shutdown.get())
+ {
+ throw new ResourceException(bundle.tryingUseConnectionFactoryShutDown(jndiName));
+ }
+
+ //it is an explicit spec requirement that equals be used for matching rather than ==.
+ if (!pool.getManagedConnectionFactory().equals(mcf))
+ {
+ throw new ResourceException(
+ bundle.wrongManagedConnectionFactorySentToAllocateConnection(pool.getManagedConnectionFactory(), mcf));
+ }
+
+ // Pick a managed connection from the pool
+ Subject subject = getSubject();
+ ConnectionListener cl = getManagedConnection(subject, cri);
+
+ // Tell each connection manager the managed connection is active
+ reconnectManagedConnection(cl);
+
+ // Ask the managed connection for a connection
+ Object connection = null;
+ try
+ {
+ connection = cl.getManagedConnection().getConnection(subject, cri);
+ }
+ catch (Throwable t)
+ {
+ try
+ {
+ managedConnectionDisconnected(cl);
+ }
+ catch (ResourceException re)
+ {
+ log.tracef("Get exception from managedConnectionDisconnected, maybe delist() have problem %s", re);
+ returnManagedConnection(cl, true);
+ }
+ throw new ResourceException(bundle.uncheckedThrowableInManagedConnectionGetConnection(cl), t);
+ }
+
+ // Associate managed connection with the connection
+ registerAssociation(cl, connection);
+
+ if (cachedConnectionManager != null)
+ {
+ cachedConnectionManager.registerConnection(this, cl, connection);
+ }
+
+ return connection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void associateConnection(Object connection, ManagedConnectionFactory mcf, ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ associateManagedConnection(connection, mcf, cri);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ManagedConnection associateManagedConnection(Object connection, ManagedConnectionFactory mcf,
+ ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ // Check for pooling!
+ if (pool == null || shutdown.get())
+ {
+ throw new ResourceException(bundle.tryingUseConnectionFactoryShutDown(jndiName));
+ }
+
+ // It is an explicit spec requirement that equals be used for matching rather than ==.
+ if (!pool.getManagedConnectionFactory().equals(mcf))
+ {
+ throw new ResourceException(
+ bundle.wrongManagedConnectionFactorySentToAllocateConnection(pool.getManagedConnectionFactory(), mcf));
+ }
+
+ if (connection == null)
+ throw new ResourceException(bundle.connectionIsNull());
+
+ // Pick a managed connection from the pool
+ Subject subject = getSubject();
+ ConnectionListener cl = getManagedConnection(subject, cri);
+
+ // Tell each connection manager the managed connection is active
+ reconnectManagedConnection(cl);
+
+ // Associate managed connection with the connection
+ cl.getManagedConnection().associateConnection(connection);
+ registerAssociation(cl, connection);
+
+ if (cachedConnectionManager != null)
+ {
+ cachedConnectionManager.registerConnection(this, cl, connection);
+ }
+
+ return cl.getManagedConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dissociateManagedConnection(Object connection, ManagedConnection mc, ManagedConnectionFactory mcf)
+ throws ResourceException
+ {
+ if (connection == null || mc == null || mcf == null)
+ throw new ResourceException(bundle.unableToFindConnectionListener());
+
+ ConnectionListener cl = getPool().findConnectionListener(mc, connection);
+
+ if (cl != null)
+ {
+ log.tracef("DissociateManagedConnection: cl=%s, connection=%s", cl, connection);
+
+ if (getCachedConnectionManager() != null)
+ {
+ try
+ {
+ getCachedConnectionManager().unregisterConnection(this, cl, connection);
+ }
+ catch (Throwable t)
+ {
+ log.debug("Throwable from unregisterConnection", t);
+ }
+ }
+
+ unregisterAssociation(cl, connection);
+
+ if (cl.getNumberOfConnections() == 0)
+ {
+ log.tracef("DissociateManagedConnection: Returning cl=%s", cl);
+
+ cl.dissociate();
+
+ log.tracef("DissociateManagedConnection: isManagedConnectionFree=%s", cl.isManagedConnectionFree());
+
+ if (cl.isManagedConnectionFree())
+ {
+ // TODO - clean up TSR
+
+ returnManagedConnection(cl, false);
+
+ return true;
+ }
+ }
+ }
+ else
+ {
+ throw new ResourceException(bundle.unableToFindConnectionListener());
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void inactiveConnectionClosed(Object connection, ManagedConnectionFactory mcf)
+ {
+ // We don't track inactive connections
+ }
+
+ /**
+ * Unregister association.
+ * @param cl connection listener
+ * @param c connection
+ */
+ //does NOT put the mc back in the pool if no more handles. Doing so would introduce a race condition
+ //whereby the mc got back in the pool while still enlisted in the tx.
+ //The mc could be checked out again and used before the delist occured.
+ public void unregisterAssociation(ConnectionListener cl, Object c)
+ {
+ cl.unregisterConnection(c);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void lazyEnlist(ManagedConnection mc) throws ResourceException
+ {
+ // Nothing by default
+ }
+
+ /**
+ * Invoked to reassociate a managed connection.
+ *
+ * @param cl the managed connection
+ * @throws ResourceException for exception
+ */
+ protected void reconnectManagedConnection(ConnectionListener cl) throws ResourceException
+ {
+ try
+ {
+ managedConnectionReconnected(cl);
+ }
+ catch (Throwable t)
+ {
+ disconnectManagedConnection(cl);
+ throw new ResourceException(bundle.uncheckedThrowableInManagedConnectionReconnected(cl), t);
+ }
+ }
+
+ /**
+ * Invoked when a managed connection is no longer associated
+ *
+ * @param cl the managed connection
+ */
+ protected void disconnectManagedConnection(ConnectionListener cl)
+ {
+ try
+ {
+ managedConnectionDisconnected(cl);
+ }
+ catch (Throwable t)
+ {
+ log.uncheckedThrowableInManagedConnectionDisconnected(cl, t);
+ }
+ }
+
+ /**
+ * For polymorphism.
+ *
+ *
+ * Do not invoke directly, use reconnectManagedConnection
+ * which does the relevent exception handling
+ * @param cl connection listener
+ * @throws ResourceException for exception
+ */
+ protected void managedConnectionReconnected(ConnectionListener cl) throws ResourceException
+ {
+ //Nothing as default
+ }
+
+ /**
+ * For polymorphism.
+ *
+ *
+ * Do not invoke directly, use disconnectManagedConnection
+ * which does the relevent exception handling
+ * @param cl connection listener
+ * @throws ResourceException for exception
+ */
+ protected void managedConnectionDisconnected(ConnectionListener cl) throws ResourceException
+ {
+ //Nothing as default
+ }
+
+ /**
+ * Register connection with connection listener.
+ * @param cl connection listener
+ * @param c connection
+ * @throws ResourceException exception
+ */
+ private void registerAssociation(ConnectionListener cl, Object c) throws ResourceException
+ {
+ cl.registerConnection(c);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract void transactionStarted(Collection conns) throws SystemException;
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract boolean isTransactional();
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract TransactionIntegration getTransactionIntegration();
+
+ /**
+ * Get a subject
+ * @return The subject
+ */
+ private Subject getSubject()
+ {
+ Subject subject = null;
+
+ if (subjectFactory != null && securityDomain != null)
+ {
+ subject = SecurityActions.createSubject(subjectFactory, securityDomain);
+
+ Set credentials = SecurityActions.getPasswordCredentials(subject);
+ if (credentials != null && credentials.size() > 0)
+ {
+ ManagedConnectionFactory pcMcf = getManagedConnectionFactory();
+ for (PasswordCredential pc : credentials)
+ {
+ pc.setManagedConnectionFactory(pcMcf);
+ }
+ }
+ }
+
+ log.tracef("Subject: %s", subject);
+
+ return subject;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManager.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManager.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManager.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,144 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2014, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager;
+
+import org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionCacheListener;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+import org.jboss.jca.core.spi.graceful.GracefulShutdown;
+import org.jboss.jca.core.spi.security.SubjectFactory;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ManagedConnection;
+
+/**
+ * Internal connection manager contract.
+ *
+ *
+ * Responsible for managing cached connections over transactional
+ * components via {@link ConnectionCacheListener}
+ * Responsible for managing connection instances using event listener
+ *
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public interface ConnectionManager extends
+ org.jboss.jca.core.api.connectionmanager.ConnectionManager,
+ ConnectionCacheListener,
+ GracefulShutdown
+{
+ /**
+ * Get the pool.
+ * @return the pool
+ */
+ public Pool getPool();
+
+ /**
+ * Gets cached connection manager
+ * @return The cached connection manager
+ */
+ public CachedConnectionManager getCachedConnectionManager();
+
+ /**
+ * Get the number of allocation retries
+ * @return The number of retries
+ */
+ public int getAllocationRetry();
+
+ /**
+ * Get the wait time between each allocation retry
+ * @return The millis
+ */
+ public long getAllocationRetryWaitMillis();
+
+ /**
+ * Get the JNDI name
+ * @return The value
+ */
+ public String getJndiName();
+
+ /**
+ * Set the JNDI name
+ * @param value The value
+ */
+ public void setJndiName(String value);
+
+ /**
+ * Get the security domain.
+ * @return The value
+ */
+ public String getSecurityDomain();
+
+ /**
+ * Get the subject factory
+ * @return The value
+ */
+ public SubjectFactory getSubjectFactory();
+
+ /**
+ * Unregister association.
+ * @param cl connection listener
+ * @param c connection
+ */
+ public void unregisterAssociation(ConnectionListener cl, Object c);
+
+ /**
+ * Create a managed connection listener for the managed connection.
+ *
+ * @param managedConnection the managed connection
+ * @param mcp the managed connection pool
+ * @return a new connection event listener
+ * @throws ResourceException for any error
+ */
+ public ConnectionListener createConnectionListener(ManagedConnection managedConnection, ManagedConnectionPool mcp)
+ throws ResourceException;
+
+ /**
+ * Determine whether there connection is a transactional.
+ *
+ * @return whether it is a transactional or not
+ */
+ public boolean isTransactional();
+
+ /**
+ * Get the transaction integration.
+ *
+ * @return the transaction integration
+ */
+ public TransactionIntegration getTransactionIntegration();
+
+ /**
+ * Is sharable
+ * @return The value
+ */
+ public boolean isSharable();
+
+ /**
+ * Is enlistment
+ * @return The value
+ */
+ public boolean isEnlistment();
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManagerFactory.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManagerFactory.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManagerFactory.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,312 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager;
+
+import org.jboss.jca.common.api.metadata.common.FlushStrategy;
+import org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager;
+import org.jboss.jca.core.api.management.ManagedEnlistmentTrace;
+import org.jboss.jca.core.connectionmanager.notx.NoTxConnectionManagerImpl;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl;
+import org.jboss.jca.core.spi.security.SubjectFactory;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+
+import javax.resource.spi.TransactionSupport.TransactionSupportLevel;
+import javax.transaction.TransactionManager;
+
+/**
+ * The connection manager factory.
+ * @author Jesper Pedersen
+ */
+public class ConnectionManagerFactory
+{
+ /**
+ * Constructor
+ */
+ public ConnectionManagerFactory()
+ {
+ }
+
+ /**
+ * Create a connection manager
+ * @param tsl The transaction support level
+ * @param pool The pool for the connection manager
+ * @param subjectFactory The subject factory
+ * @param securityDomain The security domain
+ * @param useCcm Should the CCM be used
+ * @param ccm The cached connection manager
+ * @param sharable Enable sharable connections
+ * @param enlistment Enable enlistment connections
+ * @param connectable Enable connectable connections
+ * @param tracking The tracking status
+ * @param flushStrategy The flush strategy
+ * @param allocationRetry The allocation retry value
+ * @param allocationRetryWaitMillis The allocation retry millis value
+ * @return The connection manager instance
+ */
+ public NoTxConnectionManager createNonTransactional(final TransactionSupportLevel tsl,
+ final Pool pool,
+ final SubjectFactory subjectFactory,
+ final String securityDomain,
+ final boolean useCcm,
+ final CachedConnectionManager ccm,
+ final boolean sharable,
+ final boolean enlistment,
+ final boolean connectable,
+ final Boolean tracking,
+ final FlushStrategy flushStrategy,
+ final Integer allocationRetry,
+ final Long allocationRetryWaitMillis)
+ {
+ if (tsl == null)
+ throw new IllegalArgumentException("TransactionSupportLevel is null");
+
+ if (pool == null)
+ throw new IllegalArgumentException("Pool is null");
+
+ if (flushStrategy == null)
+ throw new IllegalArgumentException("FlushStrategy is null");
+
+ NoTxConnectionManagerImpl cm = null;
+
+ switch (tsl)
+ {
+ case NoTransaction:
+ cm = new NoTxConnectionManagerImpl();
+ break;
+
+ case LocalTransaction:
+ throw new IllegalArgumentException("Transactional connection manager not supported");
+
+ case XATransaction:
+ throw new IllegalArgumentException("Transactional connection manager not supported");
+
+ default:
+ throw new IllegalArgumentException("Unknown transaction support level " + tsl);
+ }
+
+ setProperties(cm, pool,
+ subjectFactory, securityDomain,
+ useCcm, ccm,
+ sharable,
+ enlistment,
+ connectable,
+ tracking,
+ null,
+ flushStrategy,
+ allocationRetry, allocationRetryWaitMillis,
+ null);
+ setNoTxProperties(cm);
+
+ return cm;
+ }
+
+ /**
+ * Create a transactional connection manager
+ * @param tsl The transaction support level
+ * @param pool The pool for the connection manager
+ * @param subjectFactory The subject factory
+ * @param securityDomain The security domain
+ * @param useCcm Should the CCM be used
+ * @param ccm The cached connection manager
+ * @param sharable Enable sharable connections
+ * @param enlistment Enable enlistment connections
+ * @param connectable Enable connectable connections
+ * @param tracking The tracking status
+ * @param enlistmentTrace The enlistment trace
+ * @param flushStrategy The flush strategy
+ * @param allocationRetry The allocation retry value
+ * @param allocationRetryWaitMillis The allocation retry millis value
+ * @param txIntegration The transaction manager integration
+ * @param interleaving Enable interleaving
+ * @param xaResourceTimeout The transaction timeout for XAResource
+ * @param isSameRMOverride Should isSameRM be overridden
+ * @param wrapXAResource Should XAResource be wrapped
+ * @param padXid Should Xids be padded
+ * @return The connection manager instance
+ */
+ public TxConnectionManager createTransactional(final TransactionSupportLevel tsl,
+ final Pool pool,
+ final SubjectFactory subjectFactory,
+ final String securityDomain,
+ final boolean useCcm,
+ final CachedConnectionManager ccm,
+ final boolean sharable,
+ final boolean enlistment,
+ final boolean connectable,
+ final Boolean tracking,
+ final ManagedEnlistmentTrace enlistmentTrace,
+ final FlushStrategy flushStrategy,
+ final Integer allocationRetry,
+ final Long allocationRetryWaitMillis,
+ final TransactionIntegration txIntegration,
+ final Boolean interleaving,
+ final Integer xaResourceTimeout,
+ final Boolean isSameRMOverride,
+ final Boolean wrapXAResource,
+ final Boolean padXid)
+ {
+ if (tsl == null)
+ throw new IllegalArgumentException("TransactionSupportLevel is null");
+
+ if (pool == null)
+ throw new IllegalArgumentException("Pool is null");
+
+ if (txIntegration == null)
+ throw new IllegalArgumentException("TransactionIntegration is null");
+
+ if (flushStrategy == null)
+ throw new IllegalArgumentException("FlushStrategy is null");
+
+ TxConnectionManagerImpl cm = null;
+
+ switch (tsl)
+ {
+ case NoTransaction:
+ throw new IllegalArgumentException("Non transactional connection manager not supported");
+
+ case LocalTransaction:
+ cm = new TxConnectionManagerImpl(txIntegration, true);
+ break;
+
+ case XATransaction:
+ cm = new TxConnectionManagerImpl(txIntegration, false);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown transaction support level " + tsl);
+ }
+
+ setProperties(cm, pool,
+ subjectFactory, securityDomain,
+ useCcm, ccm,
+ sharable,
+ enlistment,
+ connectable,
+ tracking,
+ enlistmentTrace,
+ flushStrategy,
+ allocationRetry, allocationRetryWaitMillis,
+ txIntegration.getTransactionManager());
+ setTxProperties(cm, interleaving, xaResourceTimeout, isSameRMOverride, wrapXAResource, padXid);
+
+ return cm;
+ }
+
+ /**
+ * Common properties
+ * @param cm The connection manager
+ * @param pool The pool
+ * @param subjectFactory The subject factory
+ * @param securityDomain The security domain
+ * @param useCcm Should the CCM be used
+ * @param ccm The cached connection manager
+ * @param sharable Enable sharable connections
+ * @param enlistment Enable enlistment connections
+ * @param connectable Enable connectable connections
+ * @param tracking The tracking status
+ * @param enlistmentTrace The enlistment trace
+ * @param flushStrategy The flush strategy
+ * @param allocationRetry The allocation retry value
+ * @param allocationRetryWaitMillis The allocation retry millis value
+ * @param tm The transaction manager
+ */
+ private void setProperties(AbstractConnectionManager cm,
+ Pool pool,
+ SubjectFactory subjectFactory,
+ String securityDomain,
+ boolean useCcm,
+ CachedConnectionManager ccm,
+ boolean sharable,
+ boolean enlistment,
+ boolean connectable,
+ Boolean tracking,
+ ManagedEnlistmentTrace enlistmentTrace,
+ FlushStrategy flushStrategy,
+ Integer allocationRetry,
+ Long allocationRetryWaitMillis,
+ TransactionManager tm)
+ {
+ pool.setConnectionManager(cm);
+ cm.setPool(pool);
+
+ cm.setSubjectFactory(subjectFactory);
+ cm.setSecurityDomain(securityDomain);
+
+ cm.setFlushStrategy(flushStrategy);
+
+ if (allocationRetry != null)
+ cm.setAllocationRetry(allocationRetry.intValue());
+
+ if (allocationRetryWaitMillis != null)
+ cm.setAllocationRetryWaitMillis(allocationRetryWaitMillis.longValue());
+
+ if (useCcm)
+ cm.setCachedConnectionManager(ccm);
+
+ cm.setSharable(sharable);
+ cm.setEnlistment(enlistment);
+ cm.setConnectable(connectable);
+ cm.setTracking(tracking);
+ cm.setEnlistmentTrace(enlistmentTrace);
+ }
+
+ /**
+ * NoTxConnectionManager properties
+ * @param cm The connection manager
+ */
+ private void setNoTxProperties(NoTxConnectionManagerImpl cm)
+ {
+ }
+
+ /**
+ * TxConnectionManager properties
+ * @param cm The connection manager
+ * @param interleaving Enable interleaving
+ * @param xaResourceTimeout The transaction timeout for XAResource
+ * @param isSameRMOverride Should isSameRM be overridden
+ * @param wrapXAResource Should XAResource be wrapped
+ * @param padXid Should Xids be padded
+ */
+ private void setTxProperties(TxConnectionManagerImpl cm,
+ Boolean interleaving,
+ Integer xaResourceTimeout,
+ Boolean isSameRMOverride,
+ Boolean wrapXAResource,
+ Boolean padXid)
+ {
+ if (interleaving != null)
+ cm.setInterleaving(interleaving.booleanValue());
+
+ if (xaResourceTimeout != null)
+ cm.setXAResourceTimeout(xaResourceTimeout.intValue());
+
+ cm.setIsSameRMOverride(isSameRMOverride);
+
+ if (wrapXAResource != null)
+ cm.setWrapXAResource(wrapXAResource.booleanValue());
+
+ if (padXid != null)
+ cm.setPadXid(padXid.booleanValue());
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManagerShutdown.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManagerShutdown.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionManagerShutdown.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,49 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2014, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager;
+
+/**
+ * Shutdown a ConnectionManager
+ * @author Jesper Pedersen
+ */
+class ConnectionManagerShutdown implements Runnable
+{
+ private ConnectionManager cm;
+
+ /**
+ * Constructor
+ * @param cm The connection manager
+ */
+ ConnectionManagerShutdown(ConnectionManager cm)
+ {
+ this.cm = cm;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run()
+ {
+ cm.shutdown();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionRecord.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionRecord.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ConnectionRecord.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,77 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+
+/**
+ * Information about a connection.
+ *
+ * @author David Jencks
+ * @author Adrian Brock
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class ConnectionRecord
+{
+ private ConnectionListener connectionListener;
+ private final Object connection;
+
+ /**
+ * Creates a new connection record.
+ * @param cl connection listener
+ * @param connection connection handle
+ */
+ public ConnectionRecord (final org.jboss.jca.core.api.connectionmanager.listener.ConnectionListener cl,
+ final Object connection)
+ {
+ this.connectionListener = (ConnectionListener)cl;
+ this.connection = connection;
+ }
+
+ /**
+ * Get the connection listener
+ * @return The listener
+ */
+ public ConnectionListener getConnectionListener()
+ {
+ return connectionListener;
+ }
+
+ /**
+ * Set the connection listener
+ * @param cl The listener
+ */
+ void setConnectionListener(ConnectionListener cl)
+ {
+ this.connectionListener = cl;
+ }
+
+ /**
+ * Get the connection
+ * @return The connection
+ */
+ public Object getConnection()
+ {
+ return connection;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/NoTxConnectionManager.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/NoTxConnectionManager.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/NoTxConnectionManager.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,31 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2010, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager;
+
+/**
+ * Internal connection manager contract for non-transactional contexts.
+ *
+ * @author Jesper Pedersen
+ */
+public interface NoTxConnectionManager extends ConnectionManager
+{
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,85 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2014, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager;
+
+import org.jboss.jca.core.spi.security.SubjectFactory;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Set;
+
+import javax.resource.spi.security.PasswordCredential;
+import javax.security.auth.Subject;
+
+/**
+ * Privileged Blocks
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Constructor
+ */
+ private SecurityActions()
+ {
+ }
+
+ /**
+ * Get a Subject instance
+ * @param subjectFactory The subject factory
+ * @param domain The domain
+ * @return The instance
+ */
+ static Subject createSubject(final SubjectFactory subjectFactory, final String domain)
+ {
+ if (System.getSecurityManager() == null)
+ return subjectFactory.createSubject(domain);
+
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Subject run()
+ {
+ return subjectFactory.createSubject(domain);
+ }
+ });
+ }
+
+ /**
+ * Get the PasswordCredential from the Subject
+ * @param subject The subject
+ * @return The instances
+ */
+ static Set getPasswordCredentials(final Subject subject)
+ {
+ if (System.getSecurityManager() == null)
+ return subject.getPrivateCredentials(PasswordCredential.class);
+
+ return AccessController.doPrivileged(new PrivilegedAction>()
+ {
+ public Set run()
+ {
+ return subject.getPrivateCredentials(PasswordCredential.class);
+ }
+ });
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/TxConnectionManager.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/TxConnectionManager.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/TxConnectionManager.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,79 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager;
+
+import org.jboss.jca.core.spi.transaction.TransactionTimeoutConfiguration;
+
+/**
+ * Internal connection manager contract for transactional contexts.
+ *
+ *
+ * Responsible for managing transaction operations via {@link TransactionTimeoutConfiguration}
+ *
+ *
+ *
+ * @author Jesper Pedersen
+ */
+public interface TxConnectionManager extends ConnectionManager, TransactionTimeoutConfiguration
+{
+ /**
+ * Get the interleaving status
+ * @return True if interleaving; otherwise false
+ */
+ public boolean isInterleaving();
+
+ /**
+ * Get the local transaction status
+ * @return True if local transactions; false if XA
+ */
+ public boolean isLocalTransactions();
+
+ /**
+ * Get the XA resource transaction time out in seconds
+ * @return The value
+ */
+ public int getXAResourceTimeout();
+
+ /**
+ * Get the IsSameRMOverride status
+ * @return null
if no override; else true or false
+ */
+ public Boolean getIsSameRMOverride();
+
+ /**
+ * Get the wrap XAResource status
+ * @return True if XAResource instances are wrapped; otherwise false
+ */
+ public boolean getWrapXAResource();
+
+ /**
+ * Get the PadXid status
+ * @return True if Xids are padded; otherwise false
+ */
+ public boolean getPadXid();
+
+ /**
+ * Is allow marked for rollback enabled
+ * @return True
if set, otherwise false
+ */
+ public boolean isAllowMarkedForRollback();
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/CachedConnectionManagerImpl.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/CachedConnectionManagerImpl.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/CachedConnectionManagerImpl.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,741 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2015, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.ccm;
+
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager;
+import org.jboss.jca.core.connectionmanager.ConnectionRecord;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionCacheListener;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.transaction.TransactionSynchronizer;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+import org.jboss.jca.core.spi.transaction.TxUtils;
+import org.jboss.jca.core.tracer.Tracer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.resource.ResourceException;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+import org.jboss.logging.Logger;
+import org.jboss.logging.Messages;
+
+/**
+ * CacheConnectionManager.
+ *
+ * @author Jesper Pedersen
+ */
+public class CachedConnectionManagerImpl implements CachedConnectionManager
+{
+ /** Log instance */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class,
+ CachedConnectionManager.class.getName());
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** Debugging flag */
+ private boolean debug = false;
+
+ /** Enabled error handling for debugging */
+ private boolean error = false;
+
+ /** Ignore unknown connections */
+ private boolean ignoreConnections = false;
+
+ /** Transaction integration */
+ private TransactionIntegration transactionIntegration;
+
+ /**
+ * ThreadLocal that holds current calling meta-programming aware
+ * object, used in case someone is idiotic enough to cache a
+ * connection between invocations.and want the spec required
+ * behavior of it getting hooked up to an appropriate
+ * ManagedConnection on each method invocation.
+ */
+ private final ThreadLocal> currentObjects =
+ new ThreadLocal>();
+
+ /**
+ * The variable objectToConnectionManagerMap
holds the
+ * map of meta-aware object to set of connections it holds, used by
+ * the idiot spec compliant behavior.
+ */
+ private final ConcurrentMap>>
+ objectToConnectionManagerMap = new ConcurrentHashMap>>();
+
+ /**
+ * Connection stacktraces
+ */
+ private final Map connectionStackTraces = new WeakHashMap();
+
+ /**
+ * Creates a new instance.
+ * @param transactionIntegration The transaction integration
+ */
+ public CachedConnectionManagerImpl(TransactionIntegration transactionIntegration)
+ {
+ if (transactionIntegration == null)
+ throw new IllegalArgumentException("TransactionIntegration is null");
+
+ this.transactionIntegration = transactionIntegration;
+ }
+
+ /**
+ * Gets transaction manager.
+ * @return transaction manager
+ */
+ public TransactionManager getTransactionManager()
+ {
+ return transactionIntegration.getTransactionManager();
+ }
+
+ /**
+ * Gets transaction synchronization registry
+ * @return TransactionSynchronizationRegistry
+ */
+ public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry()
+ {
+ return transactionIntegration.getTransactionSynchronizationRegistry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDebug()
+ {
+ return debug;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDebug(boolean v)
+ {
+ debug = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isError()
+ {
+ return error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setError(boolean v)
+ {
+ error = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isIgnoreUnknownConnections()
+ {
+ return ignoreConnections;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setIgnoreUnknownConnections(boolean v)
+ {
+ ignoreConnections = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start()
+ {
+ if (transactionIntegration.getUserTransactionRegistry() != null)
+ transactionIntegration.getUserTransactionRegistry().addListener(this);
+
+ log.debugf("start: %s", this.toString());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop()
+ {
+ log.debugf("stop: %s", this.toString());
+
+ if (transactionIntegration.getUserTransactionRegistry() != null)
+ transactionIntegration.getUserTransactionRegistry().removeListener(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void userTransactionStarted() throws SystemException
+ {
+ KeyConnectionAssociation key = peekMetaAwareObject();
+
+ log.tracef("user tx started, key: %s", key);
+
+ if (key != null)
+ {
+ ConcurrentMap> cmToConnectionsMap =
+ key.getCMToConnectionsMap();
+
+ Iterator>> cmToConnectionsMapIterator =
+ cmToConnectionsMap.entrySet().iterator();
+
+ while (cmToConnectionsMapIterator.hasNext())
+ {
+ Entry> entry =
+ cmToConnectionsMapIterator.next();
+
+ ConnectionCacheListener cm = entry.getKey();
+ CopyOnWriteArrayList conns = entry.getValue();
+
+ if (Tracer.isEnabled())
+ {
+ for (ConnectionRecord cr : conns)
+ {
+ ConnectionListener cl = (ConnectionListener)cr.getConnectionListener();
+ Tracer.ccmUserTransaction(cl.getPool().getName(), cl.getManagedConnectionPool(),
+ cl, cr.getConnection(), key.toString());
+ }
+ }
+
+ cm.transactionStarted(conns);
+ }
+ }
+ }
+
+ /**
+ *
+ * @return stack last meta-aware object
+ */
+ private KeyConnectionAssociation peekMetaAwareObject()
+ {
+ LinkedList stack = currentObjects.get();
+
+ if (stack != null && !stack.isEmpty())
+ {
+ return stack.getLast();
+ }
+
+ return null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public void popMetaAwareObject(Set unsharableResources) throws ResourceException
+ {
+ LinkedList stack = currentObjects.get();
+ KeyConnectionAssociation oldKey = stack.removeLast();
+
+ log.tracef("popped object: %s", oldKey);
+
+ if (Tracer.isEnabled())
+ Tracer.popCCMContext(oldKey.toString(), new Throwable("CALLSTACK"));
+
+ if (debug)
+ {
+ if (closeAll(oldKey) && error)
+ {
+ throw new ResourceException(bundle.someConnectionsWereNotClosed());
+ }
+ }
+ }
+
+ /**
+ * Register connection.
+ * @param cm connection manager
+ * @param cl connection listener
+ * @param connection connection handle
+ */
+ public void registerConnection(org.jboss.jca.core.api.connectionmanager.listener.ConnectionCacheListener cm,
+ org.jboss.jca.core.api.connectionmanager.listener.ConnectionListener cl,
+ Object connection)
+ {
+ if (debug)
+ {
+ synchronized (connectionStackTraces)
+ {
+ connectionStackTraces.put(connection, new Throwable("STACKTRACE"));
+ }
+ }
+
+ KeyConnectionAssociation key = peekMetaAwareObject();
+
+ log.tracef("registering connection from connection manager: %s, connection : %s, key: %s",
+ cm, connection, key);
+
+ if (key != null)
+ {
+ if (Tracer.isEnabled())
+ {
+ ConnectionListener l = (ConnectionListener)cl;
+ Tracer.registerCCMConnection(l.getPool().getName(), l.getManagedConnectionPool(),
+ l, connection, key.toString());
+ }
+
+ ConnectionRecord cr = new ConnectionRecord(cl, connection);
+ ConcurrentMap> cmToConnectionsMap =
+ key.getCMToConnectionsMap();
+
+ CopyOnWriteArrayList conns = cmToConnectionsMap.get(cm);
+ if (conns == null)
+ {
+ conns = new CopyOnWriteArrayList();
+ cmToConnectionsMap.put((ConnectionCacheListener)cm, conns);
+ }
+
+ conns.add(cr);
+ }
+ }
+
+ /**
+ * Unregister connection.
+ * @param cm connection manager
+ * @param cl connection listener
+ * @param connection connection handle
+ */
+ public void unregisterConnection(org.jboss.jca.core.api.connectionmanager.listener.ConnectionCacheListener cm,
+ org.jboss.jca.core.api.connectionmanager.listener.ConnectionListener cl,
+ Object connection)
+ {
+ if (debug)
+ {
+ CloseConnectionSynchronization cas = getCloseConnectionSynchronization(false);
+ if (cas != null)
+ {
+ cas.remove(connection);
+ }
+
+ synchronized (connectionStackTraces)
+ {
+ connectionStackTraces.remove(connection);
+ }
+ }
+
+ KeyConnectionAssociation key = peekMetaAwareObject();
+
+ log.tracef("unregistering connection from connection manager: %s, connection: %s, key: %s",
+ cm, connection, key);
+
+ if (key == null)
+ return;
+
+ ConcurrentMap> cmToConnectionsMap =
+ key.getCMToConnectionsMap();
+
+ CopyOnWriteArrayList conns = cmToConnectionsMap.get(cm);
+
+ // Can happen if connections are "passed" between contexts
+ if (conns == null)
+ return;
+
+ // Note iterator of CopyOnWriteArrayList does not support remove method
+ // We use here remove on CopyOnWriteArrayList directly
+ for (ConnectionRecord connectionRecord : conns)
+ {
+ if (connectionRecord.getConnection() == connection)
+ {
+ if (Tracer.isEnabled())
+ {
+ ConnectionListener l = (ConnectionListener)cl;
+ Tracer.unregisterCCMConnection(l.getPool().getName(), l.getManagedConnectionPool(),
+ l, connection, key.toString());
+ }
+
+ conns.remove(connectionRecord);
+ return;
+ }
+ }
+
+ if (Tracer.isEnabled())
+ {
+ ConnectionListener l = (ConnectionListener)cl;
+ Tracer.unknownCCMConnection(l.getPool().getName(), l.getManagedConnectionPool(),
+ l, connection, key.toString());
+ }
+
+ if (!ignoreConnections)
+ throw new IllegalStateException(bundle.tryingToReturnUnknownConnection(connection.toString()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public void pushMetaAwareObject(final Object rawKey, Set unsharableResources) throws ResourceException
+ {
+ LinkedList stack = currentObjects.get();
+ KeyConnectionAssociation key = new KeyConnectionAssociation(rawKey);
+
+ if (stack == null)
+ {
+ log.tracef("new stack for key: %s", key);
+
+ stack = new LinkedList();
+ currentObjects.set(stack);
+ }
+ else if (stack.isEmpty())
+ {
+ log.tracef("new stack for key: %s", key);
+ }
+ else
+ {
+ log.tracef("old stack for key: %s", stack.getLast());
+ log.tracef("new stack for key: %s", key);
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.pushCCMContext(key.toString(), new Throwable("CALLSTACK"));
+
+ stack.addLast(key);
+ }
+
+ /**
+ * Describe unregisterConnectionCacheListener
method here.
+ * This is a shutdown method called by a connection manager. It will remove all reference
+ * to that connection manager from the cache, so cached connections from that manager
+ * will never be recoverable.
+ * Possibly this method should not exist.
+ *
+ * @param cm a ConnectionCacheListener
value
+ */
+ public void unregisterConnectionCacheListener(ConnectionCacheListener cm)
+ {
+ log.tracef("unregisterConnectionCacheListener: %s", cm);
+
+ Iterator>> it =
+ objectToConnectionManagerMap.values().iterator();
+
+ while (it.hasNext())
+ {
+ ConcurrentMap> cmToConnectionsMap = it.next();
+
+ if (cmToConnectionsMap != null)
+ cmToConnectionsMap.remove(cm);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getNumberOfConnections()
+ {
+ if (!debug)
+ return 0;
+
+ synchronized (connectionStackTraces)
+ {
+ return connectionStackTraces.size();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map listConnections()
+ {
+ if (!debug)
+ return Collections.unmodifiableMap(Collections.EMPTY_MAP);
+
+ synchronized (connectionStackTraces)
+ {
+ HashMap result = new HashMap();
+
+ for (Map.Entry entry : connectionStackTraces.entrySet())
+ {
+ Object key = entry.getKey();
+ Throwable stackTrace = entry.getValue();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos, true);
+ stackTrace.printStackTrace(ps);
+
+ result.put(key.toString(), baos.toString());
+ }
+
+ return Collections.unmodifiableMap(result);
+ }
+ }
+
+ /**
+ * Close all connections.
+ * @param key The key
+ * @return true if close
+ */
+ private boolean closeAll(KeyConnectionAssociation key)
+ {
+ ConcurrentMap> cmToConnectionsMap =
+ key.getCMToConnectionsMap();
+ boolean unclosed = false;
+
+ Collection> connections = cmToConnectionsMap.values();
+ if (connections.size() != 0)
+ {
+ for (Iterator> i = connections.iterator(); i.hasNext();)
+ {
+ CopyOnWriteArrayList conns = i.next();
+ for (ConnectionRecord cr : conns)
+ {
+ Object c = cr.getConnection();
+ CloseConnectionSynchronization cas = getCloseConnectionSynchronization(true);
+ if (cas == null)
+ {
+ unclosed = true;
+
+ if (Tracer.isEnabled())
+ {
+ ConnectionListener cl = (ConnectionListener)cr.getConnectionListener();
+ Tracer.closeCCMConnection(cl.getPool().getName(), cl.getManagedConnectionPool(),
+ cl, c, key.toString());
+ }
+
+ closeConnection(c);
+ }
+ else
+ {
+ cas.add(c);
+ }
+ }
+ }
+ }
+
+ return unclosed;
+ }
+
+ /**
+ * Gets close sync. instance.
+ * @param createIfNotFound create if not found
+ * @return sync. instance
+ */
+ private CloseConnectionSynchronization getCloseConnectionSynchronization(boolean createIfNotFound)
+ {
+ try
+ {
+ Transaction tx = null;
+ if (getTransactionManager() != null)
+ {
+ tx = getTransactionManager().getTransaction();
+ }
+
+ if (tx != null)
+ {
+ if (createIfNotFound)
+ TransactionSynchronizer.lock(tx, transactionIntegration);
+ try
+ {
+ CloseConnectionSynchronization cas =
+ (CloseConnectionSynchronization)TransactionSynchronizer.getCCMSynchronization(tx,
+ transactionIntegration);
+
+ if (cas == null && createIfNotFound && TxUtils.isActive(tx))
+ {
+ cas = new CloseConnectionSynchronization();
+ TransactionSynchronizer.registerCCMSynchronization(tx, cas, transactionIntegration);
+ }
+
+ return cas;
+ }
+ finally
+ {
+ if (createIfNotFound)
+ TransactionSynchronizer.unlock(tx, transactionIntegration);
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ log.debug("Unable to synchronize with transaction", t);
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Close connection handle.
+ * @param connectionHandle connection handle
+ */
+ private void closeConnection(Object connectionHandle)
+ {
+ try
+ {
+ Throwable exception;
+
+ synchronized (connectionStackTraces)
+ {
+ exception = connectionStackTraces.remove(connectionHandle);
+ }
+
+ Method m = SecurityActions.getMethod(connectionHandle.getClass(), "close", new Class[]{});
+
+ try
+ {
+ if (exception != null)
+ {
+ log.closingConnection(connectionHandle, exception);
+ }
+ else
+ {
+ log.closingConnection(connectionHandle);
+ }
+
+ m.invoke(connectionHandle, new Object[]{});
+ }
+ catch (Throwable t)
+ {
+ log.closingConnectionThrowable(t);
+ }
+ }
+ catch (NoSuchMethodException nsme)
+ {
+ log.closingConnectionNoClose(connectionHandle.getClass().getName());
+ }
+ }
+
+
+ /**
+ * Close synch. class.
+ */
+ private class CloseConnectionSynchronization implements Synchronization
+ {
+ /**Connection handles*/
+ CopyOnWriteArraySet connections = new CopyOnWriteArraySet();
+
+ /**Closing flag*/
+ AtomicBoolean closing = new AtomicBoolean(false);
+
+ /**
+ * Creates a new instance.
+ */
+ public CloseConnectionSynchronization()
+ {
+ }
+
+ /**
+ * Add new connection handle.
+ * @param c connection handle
+ */
+ public void add(Object c)
+ {
+ if (!closing.get())
+ connections.add(c);
+ }
+
+ /**
+ * Removes connection handle.
+ * @param c connection handle
+ */
+ public void remove(Object c)
+ {
+ if (!closing.get())
+ connections.remove(c);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void beforeCompletion()
+ {
+ // No-action
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void afterCompletion(int status)
+ {
+ closing.set(true);
+
+ for (Iterator i = connections.iterator(); i.hasNext();)
+ {
+ closeConnection(i.next());
+ }
+
+ connections.clear();
+ }
+ }
+
+ /**
+ * Get the currentObjects.
+ * This method is package protected beacause it is intended only for test case use.
+ * Please don't use it in your production code.
+ *
+ * @return the currentObjects.
+ */
+ final ThreadLocal> getCurrentObjects()
+ {
+ return currentObjects;
+ }
+
+ /**
+ * String representation
+ * @return The string
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("CachedConnectionManagerImpl@").append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append("[debug=").append(debug);
+ sb.append(" error=").append(error);
+ sb.append(" ignoreConnections=").append(ignoreConnections);
+ sb.append(" transactionIntegration=").append(transactionIntegration);
+ sb.append(" currentObjects=").append(currentObjects.get());
+ sb.append(" objectToConnectionManagerMap=").append(objectToConnectionManagerMap);
+ sb.append(" connectionStackTraces=").append(connectionStackTraces);
+ sb.append("]");
+
+ return sb.toString();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/KeyConnectionAssociation.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/KeyConnectionAssociation.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/KeyConnectionAssociation.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,108 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.ccm;
+
+import org.jboss.jca.core.connectionmanager.ConnectionRecord;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionCacheListener;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * The class KeyConnectionAssociation
wraps objects so they may be used in hashmaps
+ * based on their object identity rather than equals implementation. Used for keys.
+ *
+ * @author Gurkan Erdogdu
+ * @version $Rev$
+ */
+final class KeyConnectionAssociation
+{
+ //key
+ private final Object metaAwareObject;
+
+ //map of cm to list of connections for that cm.
+ private ConcurrentMap> cmToConnectionsMap;
+
+ /**
+ * Creates a new instance.
+ * @param metaAwareObject meta aware object
+ */
+ KeyConnectionAssociation(final Object metaAwareObject)
+ {
+ this.metaAwareObject = metaAwareObject;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ return true;
+
+ if (other == null || !(other instanceof KeyConnectionAssociation))
+ return false;
+
+ KeyConnectionAssociation kca = (KeyConnectionAssociation)other;
+
+ return metaAwareObject.equals(kca.metaAwareObject);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return metaAwareObject.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(metaAwareObject));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ return System.identityHashCode(metaAwareObject);
+ }
+
+ /**
+ * Set map instance.
+ * @param cmToConnectionsMap connection manager to connections
+ */
+ public void setCMToConnectionsMap(ConcurrentMap> cmToConnectionsMap)
+ {
+ this.cmToConnectionsMap = cmToConnectionsMap;
+ }
+
+ /**
+ *
+ * @return map instance
+ */
+ public ConcurrentMap> getCMToConnectionsMap()
+ {
+ if (cmToConnectionsMap == null)
+ cmToConnectionsMap = new ConcurrentHashMap>();
+
+ return cmToConnectionsMap;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,76 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.ccm;
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Constructor
+ */
+ private SecurityActions()
+ {
+ }
+
+ /**
+ * Get the method
+ * @param c The class
+ * @param name The name
+ * @param params The parameters
+ * @return The method
+ * @exception NoSuchMethodException If a matching method is not found.
+ */
+ static Method getMethod(final Class> c, final String name, final Class>... params)
+ throws NoSuchMethodException
+ {
+ if (System.getSecurityManager() == null)
+ return c.getMethod(name, params);
+
+ Method result = AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Method run()
+ {
+ try
+ {
+ return c.getMethod(name, params);
+ }
+ catch (NoSuchMethodException e)
+ {
+ return null;
+ }
+ }
+ });
+
+ if (result != null)
+ return result;
+
+ throw new NoSuchMethodException();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/ccm/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the cached connection manager.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,736 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.common.api.metadata.common.FlushStrategy;
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager;
+import org.jboss.jca.core.api.connectionmanager.pool.FlushMode;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+import org.jboss.jca.core.spi.transaction.ConnectableResourceListener;
+import org.jboss.jca.core.tracer.Tracer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionEvent;
+import javax.resource.spi.ManagedConnection;
+import javax.transaction.SystemException;
+
+import org.jboss.logging.Messages;
+
+/**
+ * Abstract implementation of the {@link ConnectionListener} interface
+ * contract.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public abstract class AbstractConnectionListener implements ConnectionListener, ConnectableResourceListener
+{
+ private final CoreLogger log;
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** Connection Manager */
+ private final ConnectionManager cm;
+
+ /** Managed connection */
+ private final ManagedConnection managedConnection;
+
+ /** Pool for this connection */
+ private final Pool pool;
+
+ /** Managed connection pool */
+ private final ManagedConnectionPool managedConnectionPool;
+
+ /** Flush strategy */
+ private FlushStrategy flushStrategy;
+
+ /** Connection State */
+ private ConnectionState state = ConnectionState.NORMAL;
+
+ /** Connection handles */
+ protected CopyOnWriteArraySet connectionHandles = new CopyOnWriteArraySet();
+
+ /** Connection traces */
+ protected Map connectionTraces;
+
+ /** Track by transaction or not */
+ private final AtomicBoolean trackByTx = new AtomicBoolean(false);
+
+ /** Connection last returned */
+ private long lastReturned;
+
+ /** Connection last validated time */
+ private long lastValidated;
+
+ /** Connection check out time */
+ private long lastCheckedOut;
+
+ /** Enlisted */
+ private boolean enlisted;
+
+ /** Tracking */
+ protected Boolean tracking;
+
+ /** The reported exception */
+ private Exception reportedException;
+
+ /**
+ * Creates a new instance of the listener that is responsible for
+ * tracking the owned connection instance.
+ * @param cm connection manager
+ * @param managedConnection managed connection
+ * @param pool pool
+ * @param mcp managed connection pool
+ * @param flushStrategy flushStrategy
+ * @param tracking tracking
+ */
+ protected AbstractConnectionListener(ConnectionManager cm, ManagedConnection managedConnection,
+ Pool pool, ManagedConnectionPool mcp, FlushStrategy flushStrategy,
+ Boolean tracking)
+ {
+ this.cm = cm;
+ this.managedConnection = managedConnection;
+ this.pool = pool;
+ this.managedConnectionPool = mcp;
+ this.flushStrategy = flushStrategy;
+ this.log = getLogger();
+ this.enlisted = false;
+
+ long createdTime = System.currentTimeMillis();
+ this.lastReturned = createdTime;
+ this.lastValidated = createdTime;
+ this.lastCheckedOut = createdTime;
+
+ this.tracking = tracking;
+
+ if (tracking != null && tracking.booleanValue())
+ this.connectionTraces = new HashMap();
+
+ this.reportedException = null;
+ }
+
+ /**
+ * Gets cached connection manager
+ * @return cached connection manager
+ */
+ protected CachedConnectionManager getCachedConnectionManager()
+ {
+ return cm.getCachedConnectionManager();
+ }
+
+ /**
+ * Gets connection manager.
+ * @return connection manager
+ */
+ protected ConnectionManager getConnectionManager()
+ {
+ return cm;
+ }
+
+ /**
+ * Get the logger
+ * @return The value
+ */
+ protected abstract CoreLogger getLogger();
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getNumberOfConnections()
+ {
+ return connectionHandles.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnlisted()
+ {
+ return enlisted;
+ }
+
+ /**
+ * Set the enlisted flag
+ * @param v The value
+ */
+ void setEnlisted(boolean v)
+ {
+ enlisted = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean delist() throws ResourceException
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void enlist() throws SystemException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ManagedConnectionPool getManagedConnectionPool()
+ {
+ return managedConnectionPool;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastValidatedTime()
+ {
+ return lastValidated;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastReturnedTime()
+ {
+ return lastReturned;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastCheckedOutTime()
+ {
+ return lastCheckedOut;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLastCheckedOutTime(long v)
+ {
+ lastCheckedOut = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ManagedConnection getManagedConnection()
+ {
+ return managedConnection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Pool getPool()
+ {
+ return pool;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionState getState()
+ {
+ return state;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isManagedConnectionFree()
+ {
+ if (log.isTraceEnabled())
+ log.tracef("[%s] isManagedConnectionFree: %s", getIdentifier(), connectionHandles.isEmpty());
+
+ return connectionHandles.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTimedOut(long timeout)
+ {
+ return lastReturned < timeout;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTrackByTx()
+ {
+ return trackByTx.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void registerConnection(Object handle)
+ {
+ if (handle != null)
+ {
+ connectionHandles.add(handle);
+
+ if (Tracer.isEnabled())
+ Tracer.getConnection(pool != null ? pool.getName() : null, managedConnectionPool, this, handle);
+
+ if (log.isTraceEnabled())
+ log.tracef("[%s] registerConnection: %s [size=%s] (%s)", getIdentifier(), handle,
+ connectionHandles.size(), connectionHandles);
+
+ if (tracking != null && tracking.booleanValue())
+ connectionTraces.put(handle, new Exception());
+ }
+ else
+ {
+ log.registeredNullHandleManagedConnection(managedConnection);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLastValidatedTime(long lastValidated)
+ {
+ this.lastValidated = lastValidated;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setState(ConnectionState newState)
+ {
+ this.state = newState;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setTrackByTx(boolean trackByTx)
+ {
+ this.trackByTx.set(trackByTx);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void tidyup() throws ResourceException
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void unregisterConnection(Object handle)
+ {
+ if (handle != null)
+ {
+ if (!connectionHandles.remove(handle))
+ {
+ log.unregisteredHandleNotRegistered(handle, managedConnection);
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.returnConnection(pool != null ? pool.getName() : null, managedConnectionPool, this, handle);
+
+ if (tracking != null && tracking.booleanValue())
+ connectionTraces.remove(handle);
+ }
+ else
+ {
+ log.unregisteredNullHandleManagedConnection(managedConnection);
+ }
+
+ if (log.isTraceEnabled())
+ log.tracef("[%s] unregisterConnection: " + connectionHandles.size() + " handles left (%s)",
+ getIdentifier(), connectionHandles);
+ }
+
+ /**
+ * Unregister connections.
+ */
+ public void unregisterConnections()
+ {
+ if (log.isTraceEnabled())
+ log.tracef("[%s] unregisterConnections", getIdentifier());
+
+ if (getCachedConnectionManager() != null)
+ {
+ for (Object handle : connectionHandles)
+ {
+ getCachedConnectionManager().unregisterConnection(getConnectionManager(), this, handle);
+ }
+ }
+
+ if (Tracer.isEnabled())
+ {
+ for (Object handle : connectionHandles)
+ {
+ Tracer.returnConnection(pool != null ? pool.getName() : null, managedConnectionPool, this, handle);
+ }
+ }
+
+ connectionHandles.clear();
+
+ if (tracking != null && tracking.booleanValue())
+ connectionTraces.clear();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toPool()
+ {
+ lastReturned = System.currentTimeMillis();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void connectionClosed(ConnectionEvent event)
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void connectionErrorOccurred(ConnectionEvent event)
+ {
+ if (state == ConnectionState.NORMAL)
+ {
+ if (event != null)
+ {
+ Exception cause = event.getException();
+ if (cause == null)
+ {
+ cause = new Exception("No exception was reported");
+ }
+ else
+ {
+ reportedException = cause;
+ }
+
+ log.connectionErrorOccured(this, cause);
+ }
+ else
+ {
+ Exception cause = new Exception("No exception was reported");
+ log.unknownConnectionErrorOccured(this, cause);
+ }
+ }
+
+ try
+ {
+ unregisterConnections();
+ }
+ catch (Throwable t)
+ {
+ //ignore, it wasn't checked out.
+ }
+
+ if (event != null && event.getSource() != getManagedConnection())
+ {
+ log.notifiedErrorDifferentManagedConnection();
+ }
+
+ haltCatchFire();
+
+ getConnectionManager().returnManagedConnection(this, true);
+
+ if (flushStrategy == FlushStrategy.FAILING_CONNECTION_ONLY)
+ {
+ managedConnectionPool.prefill();
+ }
+ else if (flushStrategy == FlushStrategy.INVALID_IDLE_CONNECTIONS)
+ {
+ Collection toDestroy = new ArrayList();
+ managedConnectionPool.flush(FlushMode.INVALID, toDestroy);
+ for (ConnectionListener connectionListener: toDestroy)
+ {
+ connectionListener.destroy();
+ }
+ }
+ else if (flushStrategy == FlushStrategy.IDLE_CONNECTIONS)
+ {
+ Collection toDestroy = new ArrayList();
+ managedConnectionPool.flush(FlushMode.IDLE, toDestroy);
+ for (ConnectionListener connectionListener: toDestroy)
+ {
+ connectionListener.destroy();
+ }
+ }
+ else if (flushStrategy == FlushStrategy.GRACEFULLY)
+ {
+ Collection toDestroy = new ArrayList();
+ managedConnectionPool.flush(FlushMode.GRACEFULLY, toDestroy);
+ for (ConnectionListener connectionListener: toDestroy)
+ {
+ connectionListener.destroy();
+ }
+ }
+ else if (flushStrategy == FlushStrategy.ENTIRE_POOL)
+ {
+ Collection toDestroy = new ArrayList();
+ managedConnectionPool.flush(FlushMode.ALL, toDestroy);
+ for (ConnectionListener connectionListener: toDestroy)
+ {
+ connectionListener.destroy();
+ }
+ }
+ else if (flushStrategy == FlushStrategy.ALL_INVALID_IDLE_CONNECTIONS)
+ {
+ pool.flush(FlushMode.INVALID);
+ }
+ else if (flushStrategy == FlushStrategy.ALL_IDLE_CONNECTIONS)
+ {
+ pool.flush(FlushMode.IDLE);
+ }
+ else if (flushStrategy == FlushStrategy.ALL_GRACEFULLY)
+ {
+ pool.flush(FlushMode.GRACEFULLY);
+ }
+ else if (flushStrategy == FlushStrategy.ALL_CONNECTIONS)
+ {
+ pool.flush(FlushMode.ALL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Exception getException()
+ {
+ return reportedException;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean controls(ManagedConnection mc, Object connection)
+ {
+ if (managedConnection.equals(mc))
+ {
+ if (connection == null || connectionHandles.contains(connection))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dissociate() throws ResourceException
+ {
+ // Nothing by default
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsLazyAssociation()
+ {
+ return managedConnection instanceof javax.resource.spi.DissociatableManagedConnection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean supportsLazyEnlistment()
+ {
+ return managedConnection instanceof javax.resource.spi.LazyEnlistableManagedConnection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void localTransactionCommitted(ConnectionEvent event)
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void localTransactionRolledback(ConnectionEvent event)
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void localTransactionStarted(ConnectionEvent event)
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleCreated(Object h)
+ {
+ registerConnection(h);
+
+ if (getCachedConnectionManager() != null)
+ {
+ getCachedConnectionManager().registerConnection(getConnectionManager(), this, h);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleClosed(Object h)
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void destroy()
+ {
+ if (getState() == ConnectionState.DESTROYED)
+ {
+ log.tracef("ManagedConnection is already destroyed %s", this);
+ return;
+ }
+
+ getManagedConnectionPool().connectionListenerDestroyed(this);
+
+ setState(ConnectionState.DESTROYED);
+
+ final ManagedConnection mc = getManagedConnection();
+ try
+ {
+ mc.destroy();
+ }
+ catch (Throwable t)
+ {
+ if (log.isDebugEnabled())
+ log.debug("Exception destroying ManagedConnection " + this, t);
+ }
+
+ mc.removeConnectionEventListener(this);
+ }
+
+ /**
+ * Halt and Catch Fire
+ */
+ void haltCatchFire()
+ {
+ // Do nothing by default
+ }
+
+ /**
+ * Compare
+ * @param o The other object
+ * @return 0 if equal; -1 if less than based on lastReturned; otherwise 1
+ */
+ public int compareTo(Object o)
+ {
+ if (this == o)
+ return 0;
+
+ if (!(o instanceof AbstractConnectionListener))
+ throw new ClassCastException(bundle.notCorrectTypeWhenClassCast(o.getClass().getName()));
+
+ final AbstractConnectionListener acl = (AbstractConnectionListener)o;
+
+ if (lastReturned < acl.lastReturned)
+ return -1;
+
+ return 1;
+ }
+
+ /**
+ * Get string identifier
+ * @return The value
+ */
+ private String getIdentifier()
+ {
+ StringBuffer buffer = new StringBuffer(100);
+ buffer.append(getClass().getSimpleName()).append('@').append(Integer.toHexString(System.identityHashCode(this)));
+ return buffer.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer(100);
+ buffer.append(getClass().getName()).append('@').append(Integer.toHexString(System.identityHashCode(this)));
+ buffer.append("[state=");
+
+ if (state.equals(ConnectionState.NORMAL))
+ {
+ buffer.append("NORMAL");
+ }
+ else if (state.equals(ConnectionState.DESTROY))
+ {
+ buffer.append("DESTROY");
+ }
+ else if (state.equals(ConnectionState.DESTROYED))
+ {
+ buffer.append("DESTROYED");
+ }
+ else
+ {
+ buffer.append("UNKNOWN?");
+ }
+ buffer.append(" managed connection=").append(managedConnection);
+ buffer.append(" connection handles=").append(connectionHandles.size());
+ buffer.append(" lastReturned=").append(lastReturned);
+ buffer.append(" lastValidated=").append(lastValidated);
+ buffer.append(" lastCheckedOut=").append(lastCheckedOut);
+ buffer.append(" trackByTx=").append(trackByTx.get());
+ buffer.append(" pool=").append(pool);
+ buffer.append(" mcp=").append(managedConnectionPool);
+ toString(buffer);
+ buffer.append(']');
+
+ return buffer.toString();
+ }
+
+ /**
+ * Add specific properties.
+ * @param buffer buffer instance
+ */
+ protected void toString(StringBuffer buffer)
+ {
+
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionCacheListener.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionCacheListener.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionCacheListener.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,49 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.core.connectionmanager.ConnectionRecord;
+
+import java.util.Collection;
+
+import javax.transaction.SystemException;
+
+
+/**
+ * ConnectionCacheListener.
+ *
+ * @author David Jencks
+ * @author Erwin Guib
+ * @author Adrian Brock
+ * @author Jesper Pedersen
+ */
+public interface ConnectionCacheListener
+ extends org.jboss.jca.core.api.connectionmanager.listener.ConnectionCacheListener
+{
+ /**
+ * Notification of transaction started
+ *
+ * @param conns the connections
+ * @throws SystemException for any error
+ */
+ void transactionStarted(Collection conns) throws SystemException;
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,229 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ManagedConnection;
+import javax.transaction.SystemException;
+
+/**
+ * Connection listener.
+ *
+ * @author Gurkan Erdogdu
+ * @author Adrian Brock
+ * @author Weston Price
+ * @author Jesper Pedersen
+ */
+public interface ConnectionListener extends org.jboss.jca.core.api.connectionmanager.listener.ConnectionListener
+{
+ /**
+ * Get number of connection handles
+ * @return The value
+ */
+ public int getNumberOfConnections();
+
+ /**
+ * Retrieve the pool for this listener.
+ *
+ * @return the pool
+ */
+ public Pool getPool();
+
+ /**
+ * Tidyup
+ *
+ * Invoked just before returning the connection to the pool when the
+ * connection is not being destroyed.
+ *
+ * @throws ResourceException for any error
+ */
+ public void tidyup() throws ResourceException;
+
+ /**
+ * Get the managed connection pool
+ * @return The value
+ */
+ public ManagedConnectionPool getManagedConnectionPool();
+
+ /**
+ * Retrieve the state of this connection.
+ *
+ * @return the state
+ */
+ public ConnectionState getState();
+
+ /**
+ * Set the state of this connection.
+ *
+ * @param newState new state
+ */
+ public void setState(ConnectionState newState);
+
+ /**
+ * Has the connection timed out?
+ *
+ * @param timeout the timeout
+ * @return true for timed out, false otherwise
+ */
+ public boolean isTimedOut(long timeout);
+
+ /**
+ * Mark the connection as in pool
+ */
+ public void toPool();
+
+ /**
+ * Register a new connection
+ *
+ * @param handle the connection handle
+ */
+ public void registerConnection(Object handle);
+
+ /**
+ * Unregister a connection
+ *
+ * @param handle the connection handle
+ */
+ public void unregisterConnection(Object handle);
+
+ /**
+ * Unregister all connections
+ */
+ public void unregisterConnections();
+
+ /**
+ * Is the managed connection free?
+ *
+ * @return true when it is free
+ */
+ public boolean isManagedConnectionFree();
+
+ /**
+ * Is enlisted
+ * @return True if enlisted, otherwise false
+ */
+ public boolean isEnlisted();
+
+ /**
+ * Enlist the managed connection
+ *
+ * @throws SystemException for errors
+ */
+ public void enlist() throws SystemException;
+
+ /**
+ * Delist the managed connection
+ * @return True
if the listener was delisted succesfully, otherwise false
+ * @throws ResourceException if exception occurs
+ */
+ public boolean delist() throws ResourceException;
+
+ /**
+ * Get whether the listener is track by transaction
+ *
+ * @return true for track by transaction, false otherwise
+ */
+ public boolean isTrackByTx();
+
+ /**
+ * Set whether the listener is track by transaction
+ *
+ * @param trackByTx true for track by transaction, false otherwise
+ */
+ public void setTrackByTx(boolean trackByTx);
+
+ /**
+ * Retrieve the last time this connection was validated.
+ *
+ * @return the last time the connection was validated
+ */
+ public long getLastValidatedTime();
+
+ /**
+ * Set the last time, in milliseconds, that this connection was validated.
+ *
+ * @param lastValidated the last time the connection was validated in
+ * milliseconds.
+ */
+ public void setLastValidatedTime(long lastValidated);
+
+ /**
+ * Retrieve the last time this connection was returned to the pool
+ *
+ * @return the last time the connection was returned to the pool
+ */
+ public long getLastReturnedTime();
+
+ /**
+ * Retrieve the last time this connection was obtained from the pool
+ *
+ * @return the last time the connection was obtained from the pool
+ */
+ public long getLastCheckedOutTime();
+
+ /**
+ * Set the last time this connection was obtained from the pool
+ *
+ * @param v The value
+ */
+ public void setLastCheckedOutTime(long v);
+
+ /**
+ * Get exception
+ * @return The exception that occured, or null
+ */
+ public Exception getException();
+
+ /**
+ * Controls the managed connection / connection pair
+ * @param mc The managed connection
+ * @param connection The connection; optional
+ * @return True if the connection listener controls the pair, otherwise false
+ */
+ public boolean controls(ManagedConnection mc, Object connection);
+
+ /**
+ * Dissociate the connection listener
+ * @throws ResourceException if exception occurs
+ */
+ public void dissociate() throws ResourceException;
+
+ /**
+ * Supports lazy association
+ * @return True
if supported, otherwise false
+ */
+ public boolean supportsLazyAssociation();
+
+ /**
+ * Supports lazy enlistment
+ * @return True
if supported, otherwise false
+ */
+ public boolean supportsLazyEnlistment();
+
+ /**
+ * Destroys this connection listener and its managed connection.
+ */
+ public void destroy();
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionState.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionState.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/ConnectionState.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,47 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.listener;
+
+/**
+ * Connection listener status flag. Connections can be in three state
+ *
+ * NORMAL
+ * DESTROY
+ * DESTROYED
+ *
+ *
+ * @version $Rev: $
+ * @author Gurkan Erdogdu
+ */
+public enum ConnectionState
+{
+ /**Normal state*/
+ NORMAL,
+
+ /**Destroy this connection*/
+ DESTROY,
+
+ /**Connection is destroyed*/
+ DESTROYED;
+
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,96 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.common.api.metadata.common.FlushStrategy;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+
+import javax.resource.spi.ConnectionEvent;
+import javax.resource.spi.ManagedConnection;
+
+import org.jboss.logging.Logger;
+
+/**
+ * NoTx Connection Listener.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ * @see AbstractConnectionListener
+ */
+public class NoTxConnectionListener extends AbstractConnectionListener
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class,
+ NoTxConnectionListener.class.getName());
+
+ /**
+ * Creates a new no-tx listener.
+ * @param cm connection manager
+ * @param mc managed connection
+ * @param pool pool
+ * @param mcp mcp
+ * @param flushStrategy flushStrategy
+ * @param tracking tracking
+ */
+ public NoTxConnectionListener(final ConnectionManager cm, final ManagedConnection mc,
+ final Pool pool, final ManagedConnectionPool mcp, final FlushStrategy flushStrategy,
+ final Boolean tracking)
+ {
+ super(cm, mc, pool, mcp, flushStrategy, tracking);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected CoreLogger getLogger()
+ {
+ return log;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void connectionClosed(ConnectionEvent ce)
+ {
+ if (getCachedConnectionManager() != null)
+ {
+ try
+ {
+ getCachedConnectionManager().unregisterConnection(getConnectionManager(), this, ce.getConnectionHandle());
+ }
+ catch (Throwable t)
+ {
+ log.debug("Throwable from unregisterConnection", t);
+ }
+ }
+
+ getConnectionManager().unregisterAssociation(this, ce.getConnectionHandle());
+
+ if (isManagedConnectionFree())
+ {
+ getConnectionManager().returnManagedConnection(this, false);
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,50 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.listener;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Get a system property
+ * @param name The property name
+ * @return The property value
+ */
+ static String getSystemProperty(final String name)
+ {
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public String run()
+ {
+ return System.getProperty(name);
+ }
+ });
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,1247 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.common.api.metadata.common.FlushStrategy;
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.TxConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+import org.jboss.jca.core.connectionmanager.transaction.LockKey;
+import org.jboss.jca.core.connectionmanager.transaction.TransactionSynchronizer;
+import org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl;
+import org.jboss.jca.core.spi.transaction.ConnectableResource;
+import org.jboss.jca.core.spi.transaction.TxUtils;
+import org.jboss.jca.core.spi.transaction.local.LocalXAResource;
+import org.jboss.jca.core.tracer.Tracer;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionEvent;
+import javax.resource.spi.LocalTransaction;
+import javax.resource.spi.ManagedConnection;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+
+import org.jboss.logging.Logger;
+import org.jboss.logging.Messages;
+
+/**
+ * Tx connection listener.
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class TxConnectionListener extends AbstractConnectionListener
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class,
+ TxConnectionListener.class.getName());
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** Disable failed to enlist message */
+ private static boolean disableFailedtoEnlist = false;
+
+ /**Transaction synch. instance*/
+ private TransactionSynchronization transactionSynchronization;
+
+ /**XAResource instance*/
+ private final XAResource xaResource;
+
+ /** XAResource timeout */
+ private final int xaResourceTimeout;
+
+ /** Whether there is a local transaction */
+ private final AtomicBoolean localTransaction = new AtomicBoolean(false);
+
+ /** Delist resource */
+ private boolean doDelistResource;
+
+ /** Set rollback */
+ private boolean doSetRollbackOnly;
+
+ /** Enlistment trace */
+ private Boolean enlistmentTrace;
+
+ static
+ {
+ String value = SecurityActions.getSystemProperty("ironjacamar.disable_enlistment_trace");
+
+ if (value != null && !value.trim().equals(""))
+ {
+ try
+ {
+ disableFailedtoEnlist = Boolean.valueOf(value);
+ }
+ catch (Throwable t)
+ {
+ // Assume enable
+ disableFailedtoEnlist = true;
+ }
+ }
+ }
+
+ /**
+ * Creates a new tx listener.
+ * @param cm connection manager
+ * @param mc managed connection
+ * @param pool pool
+ * @param mcp mcp
+ * @param flushStrategy flushStrategy
+ * @param tracking tracking
+ * @param enlistmentTrace enlistmentTrace
+ * @param xaResource xaresource instance
+ * @param xaResourceTimeout timeout for the XAResource
+ * @throws ResourceException if aexception while creating
+ */
+ public TxConnectionListener(final ConnectionManager cm, final ManagedConnection mc,
+ final Pool pool, final ManagedConnectionPool mcp, final FlushStrategy flushStrategy,
+ final Boolean tracking, final Boolean enlistmentTrace,
+ final XAResource xaResource, final int xaResourceTimeout)
+ throws ResourceException
+ {
+ super(cm, mc, pool, mcp, flushStrategy, tracking);
+
+ this.xaResource = xaResource;
+ this.xaResourceTimeout = xaResourceTimeout;
+ this.doDelistResource = true;
+ this.doSetRollbackOnly = true;
+ this.enlistmentTrace = enlistmentTrace;
+
+ if (xaResource instanceof LocalXAResource)
+ {
+ ((LocalXAResource) xaResource).setConnectionListener(this);
+ }
+ if (xaResource instanceof ConnectableResource)
+ {
+ ((ConnectableResource) xaResource).setConnectableResourceListener(this);
+ }
+
+ String value = SecurityActions.getSystemProperty("ironjacamar.no_delist_resource");
+ if (value != null && !value.trim().equals(""))
+ {
+ StringTokenizer st = new StringTokenizer(value, ",");
+ while (doDelistResource && st.hasMoreTokens())
+ {
+ if (getPool().getName().equals(st.nextToken()))
+ doDelistResource = false;
+ }
+ }
+ value = SecurityActions.getSystemProperty("ironjacamar.no_delist_resource_all");
+ if (value != null && !value.trim().equals(""))
+ {
+ doDelistResource = false;
+ }
+
+ value = SecurityActions.getSystemProperty("ironjacamar.rollback_on_fatal_error");
+ if (value != null && !value.trim().equals(""))
+ {
+ if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value))
+ {
+ doSetRollbackOnly = Boolean.parseBoolean(value);
+ }
+ else
+ {
+ StringTokenizer st = new StringTokenizer(value, ",");
+ while (doSetRollbackOnly && st.hasMoreTokens())
+ {
+ if (getPool().getName().equals(st.nextToken()))
+ doSetRollbackOnly = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected CoreLogger getLogger()
+ {
+ return log;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void toPool()
+ {
+ super.toPool();
+
+ // Do a reset of the underlying XAResource timeout
+ if (!(xaResource instanceof LocalXAResource) && xaResourceTimeout > 0)
+ {
+ try
+ {
+ xaResource.setTransactionTimeout(xaResourceTimeout);
+ }
+ catch (XAException e)
+ {
+ log.debugf(e, "XAException happend during return for: %s",
+ getPool() != null ? getPool().getName() : "Unknown");
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void enlist() throws SystemException
+ {
+ // This method is a bit convulted, but it has to be such because
+ // there is a race condition in the transaction manager where it
+ // unlocks during the enlist of the XAResource. It does this
+ // to avoid distributed deadlocks and to ensure the transaction
+ // timeout can fail a badly behaving resource during the enlist.
+ //
+ // When two threads in the same transaction are trying to enlist
+ // connections they could be from the same resource manager
+ // or even the same connection when tracking the connection by transaction.
+ //
+ // For the same connection, we only want to do the real enlist once.
+ // For two connections from the same resource manager we don't
+ // want the join before the initial start request.
+ //
+ // The solution is to build up a list of unenlisted resources
+ // in the TransactionSynchronizer and then choose one of the
+ // threads that is contending in the transaction to enlist them
+ // in order. The actual order doesn't really matter as it is the
+ // transaction manager that calculates the enlist flags and determines
+ // whether the XAResource was already enlisted.
+ //
+ // Once there are no unenlisted resources the threads are released
+ // to return the result of the enlistments.
+ //
+ // In practice, a thread just takes a snapshot to try to avoid one
+ // thread having to do all the work. If it did not do them all
+ // the next waiting thread will do the next snapshot until there
+ // there is either no snapshot or no waiting threads.
+ //
+ // A downside to this design is a thread could have its resource enlisted by
+ // an earlier thread while it enlists some later thread's resource.
+ // Since they are all a part of the same transaction, this is probably
+ // not a real issue.
+
+ // If we are already enlisted there is no reason to check again, as this method
+ // could be called multiple times during a transaction lifecycle.
+ // We know that we can only be inside this method if we are allowed to
+ if (isEnlisted() || getState().equals(ConnectionState.DESTROY) || getState().equals(ConnectionState.DESTROYED))
+ return;
+
+ // No transaction associated with the thread
+ TransactionManager tm = getConnectionManager().getTransactionIntegration().getTransactionManager();
+ int status = tm.getStatus();
+
+ if (status == Status.STATUS_NO_TRANSACTION)
+ {
+ if (transactionSynchronization != null && transactionSynchronization.currentTx != null)
+ {
+ String error = "Attempt to use connection outside a transaction when already a tx!";
+ log.tracef("%s %s", error, this);
+
+
+ throw new IllegalStateException(error);
+ }
+ log.tracef("No transaction, no need to enlist: %s", this);
+
+ return;
+ }
+
+ // Inactive transaction
+ Transaction threadTx = tm.getTransaction();
+ if (threadTx == null || status != Status.STATUS_ACTIVE)
+ {
+ TxConnectionManager txConnectionManager = (TxConnectionManager)getConnectionManager();
+
+ if (!txConnectionManager.isAllowMarkedForRollback())
+ {
+ String error = "Transaction " + threadTx + " is not active " + TxUtils.getStatusAsString(status);
+ log.tracef("%s cl=%s", error, this);
+
+ throw new IllegalStateException(error);
+ }
+ }
+
+ log.tracef("Pre-enlist: %s threadTx=%s", this, threadTx);
+
+ // Our synchronization
+ TransactionSynchronization ourSynchronization = null;
+
+ // Serializes enlistment when two different threads are enlisting
+ // different connections in the same transaction concurrently
+ TransactionSynchronizer synchronizer = null;
+
+ try
+ {
+ TransactionSynchronizer.lock(threadTx,
+ getConnectionManager().getTransactionIntegration());
+ }
+ catch (Exception e)
+ {
+ setTrackByTx(false);
+ TxConnectionManagerImpl.rethrowAsSystemException("Exception during lock", threadTx, e);
+ }
+
+ try
+ {
+ // Interleaving should have an unenlisted transaction
+ // TODO We should be able to do some sharing shouldn't we?
+ if (!isTrackByTx() && transactionSynchronization != null)
+ {
+ String error = "Can't enlist - already a tx!";
+ log.tracef("%s %s", error, this);
+ throw new IllegalStateException(error);
+ }
+
+ // Check for different transaction
+ if (transactionSynchronization != null && !transactionSynchronization.currentTx.equals(threadTx))
+ {
+ String error = "Trying to change transaction " + threadTx + " in enlist!";
+ log.tracef("%s %s", error, this);
+ throw new IllegalStateException(error);
+ }
+
+ // Get the synchronizer
+ try
+ {
+ log.tracef("Get synchronizer %s threadTx=%s", this, threadTx);
+
+ synchronizer =
+ TransactionSynchronizer.getRegisteredSynchronizer(threadTx,
+ getConnectionManager().getTransactionIntegration());
+ }
+ catch (Throwable t)
+ {
+ setTrackByTx(false);
+ TxConnectionManagerImpl.rethrowAsSystemException("Cannot register synchronization", threadTx, t);
+ }
+
+ // First time through, create a transaction synchronization
+ if (transactionSynchronization == null)
+ {
+ TransactionSynchronization synchronization = new TransactionSynchronization(threadTx, isTrackByTx());
+ synchronizer.addUnenlisted(synchronization);
+ transactionSynchronization = synchronization;
+ }
+
+ ourSynchronization = transactionSynchronization;
+ }
+ finally
+ {
+ TransactionSynchronizer.unlock(threadTx, getConnectionManager().getTransactionIntegration());
+ }
+
+ // Perform the enlistment(s)
+ List unenlisted = synchronizer.getUnenlisted();
+ if (unenlisted != null)
+ {
+ try
+ {
+ int size = unenlisted.size();
+ for (int i = 0; i < size; ++i)
+ {
+ TransactionSynchronization sync = (TransactionSynchronization) unenlisted.get(i);
+ if (sync.enlist())
+ {
+ synchronizer.addEnlisted(sync);
+ }
+ }
+ }
+ finally
+ {
+ synchronizer.enlisted();
+ }
+ }
+
+ // What was the result of our enlistment?
+ log.tracef("Check enlisted %s threadTx=%s", this, threadTx);
+
+ ourSynchronization.checkEnlisted();
+ setEnlisted(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean delist() throws ResourceException
+ {
+ log.tracef("delisting %s", this);
+
+ boolean success = true;
+
+ try
+ {
+ if (!isTrackByTx())
+ {
+ if (transactionSynchronization != null)
+ {
+ // SUSPEND
+ Transaction tx = transactionSynchronization.currentTx;
+ TransactionSynchronization synchronization = transactionSynchronization;
+ transactionSynchronization = null;
+ if (TxUtils.isUncommitted(tx))
+ {
+ if (synchronization.enlisted)
+ {
+ TransactionSynchronizer synchronizer =
+ TransactionSynchronizer.getRegisteredSynchronizer(tx,
+ getConnectionManager().
+ getTransactionIntegration());
+
+ if (!synchronizer.removeEnlisted(synchronization))
+ {
+ log.tracef("%s not found in %s", synchronization, synchronizer);
+ }
+ }
+
+ if (!getState().equals(ConnectionState.DESTROYED))
+ {
+ log.tracef("delistResource(%s, TMSUSPEND)", getXAResource());
+
+ boolean suspendResult = tx.delistResource(getXAResource(), XAResource.TMSUSPEND);
+
+ if (Tracer.isEnabled())
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ this, tx.toString(),
+ suspendResult, false, true);
+
+ if (!suspendResult)
+ {
+ throw new ResourceException(bundle.failureDelistResource(this));
+ }
+ else
+ {
+ log.tracef("delist-suspend: %s", this);
+ }
+ }
+ }
+ }
+ else
+ {
+ // SUCCESS / FAIL
+ if (!getState().equals(ConnectionState.DESTROYED) &&
+ isManagedConnectionFree() &&
+ isEnlisted() &&
+ doDelistResource)
+ {
+ if (getConnectionManager().getTransactionIntegration() != null &&
+ getConnectionManager().getTransactionIntegration().getTransactionManager() != null)
+ {
+ Transaction tx = getConnectionManager().getTransactionIntegration().
+ getTransactionManager().getTransaction();
+
+ if (TxUtils.isUncommitted(tx))
+ {
+ if (TxUtils.isActive(tx))
+ {
+ log.tracef("delistResource(%s, TMSUCCESS)", getXAResource());
+
+ boolean successResult = tx.delistResource(getXAResource(), XAResource.TMSUCCESS);
+
+ if (Tracer.isEnabled())
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ this, tx.toString(),
+ true, false, true);
+
+ if (successResult)
+ {
+ log.tracef("delist-success: %s", this);
+ }
+ else
+ {
+ log.debugf("delist-success failed: %s", this);
+ success = false;
+ }
+ }
+ else
+ {
+ log.tracef("delistResource(%s, TMFAIL)", getXAResource());
+
+ boolean failResult = tx.delistResource(getXAResource(), XAResource.TMFAIL);
+
+ if (Tracer.isEnabled())
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ this, tx.toString(),
+ false, false, true);
+
+ if (failResult)
+ {
+ log.tracef("delist-fail: %s", this);
+ }
+ else
+ {
+ log.debugf("delist-fail failed: %s", this);
+
+ success = false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ setEnlisted(false);
+ }
+
+ log.tracef("delisted %s", this);
+
+ return success;
+ }
+ catch (ResourceException re)
+ {
+ throw re;
+ }
+ catch (Throwable t)
+ {
+ throw new ResourceException(bundle.errorInDelist(), t);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void dissociate() throws ResourceException
+ {
+ log.tracef("dissociate: %s", this);
+
+ try
+ {
+ TransactionManager tm = getConnectionManager().getTransactionIntegration().getTransactionManager();
+ int status = tm.getStatus();
+
+ log.tracef("dissociate: status=%s", TxUtils.getStatusAsString(status));
+
+ if (status != Status.STATUS_NO_TRANSACTION)
+ {
+ if (isEnlisted())
+ {
+ if (doDelistResource)
+ {
+ Transaction tx = tm.getTransaction();
+ boolean delistResult = tx.delistResource(getXAResource(), XAResource.TMSUCCESS);
+
+ log.tracef("dissociate: delistResult=%s", delistResult);
+ }
+ }
+ else
+ {
+ log.tracef("dissociate: not enlisted (%s)", this);
+ }
+
+ if (isTrackByTx())
+ {
+ ManagedConnectionPool mcp = getManagedConnectionPool();
+ TransactionSynchronizationRegistry tsr =
+ getConnectionManager().getTransactionIntegration().getTransactionSynchronizationRegistry();
+
+ Lock lock = (Lock)tsr.getResource(LockKey.INSTANCE);
+ if (lock != null)
+ {
+ try
+ {
+ lock.lockInterruptibly();
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.interrupted();
+
+ throw new ResourceException(bundle.unableObtainLock(), ie);
+ }
+
+ try
+ {
+ tsr.putResource(mcp, null);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+ }
+ }
+
+ localTransaction.set(false);
+ setTrackByTx(false);
+
+ if (transactionSynchronization != null)
+ {
+ transactionSynchronization.cancel();
+ transactionSynchronization = null;
+ }
+
+ setEnlisted(false);
+ }
+ catch (Throwable t)
+ {
+ throw new ResourceException(bundle.errorInDissociate(), t);
+ }
+ }
+
+ //local will return this, xa will return one from mc.
+ /**
+ * Get XA resource.
+ * @return xa resource
+ */
+ protected XAResource getXAResource()
+ {
+ return xaResource;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void connectionClosed(ConnectionEvent ce)
+ {
+ log.tracef("connectionClosed called mc=%s", this.getManagedConnection());
+ if (this.getManagedConnection() != (ManagedConnection)ce.getSource())
+ throw new IllegalArgumentException("ConnectionClosed event received from wrong ManagedConnection! Expected: " +
+ this.getManagedConnection() + ", actual: " + ce.getSource());
+
+ if (getCachedConnectionManager() != null)
+ {
+ try
+ {
+ this.getCachedConnectionManager().unregisterConnection(this.getConnectionManager(), this,
+ ce.getConnectionHandle());
+ }
+ catch (Throwable t)
+ {
+ log.throwableFromUnregisterConnection(t);
+ }
+ }
+
+ try
+ {
+ if (wasFreed(ce.getConnectionHandle()))
+ {
+ boolean success = delist();
+
+ log.tracef("isManagedConnectionFree=true mc=%s", this.getManagedConnection());
+
+ if (success || (tracking != null && !tracking.booleanValue()))
+ {
+ this.getConnectionManager().returnManagedConnection(this, false);
+ }
+ else
+ {
+ log.delistingFailed(getPool() != null ? getPool().getName() : "Unknown", new Exception());
+ this.getConnectionManager().returnManagedConnection(this, true);
+ }
+ }
+ else
+ {
+ log.tracef("isManagedConnectionFree=false mc=%s", this.getManagedConnection());
+ }
+ }
+ catch (Throwable t)
+ {
+ log.errorWhileClosingConnectionHandle(t);
+ this.getConnectionManager().returnManagedConnection(this, true);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void localTransactionStarted(ConnectionEvent ce)
+ {
+ localTransaction.set(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void localTransactionCommitted(ConnectionEvent ce)
+ {
+ localTransaction.set(false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void localTransactionRolledback(ConnectionEvent ce)
+ {
+ localTransaction.set(false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void tidyup() throws ResourceException
+ {
+ // We have a hanging transaction
+ if (localTransaction.get())
+ {
+ LocalTransaction local = null;
+ ManagedConnection mc = getManagedConnection();
+ try
+ {
+ local = mc.getLocalTransaction();
+ }
+ catch (Throwable t)
+ {
+ throw new ResourceException(bundle.unfinishedLocalTransaction(this), t);
+ }
+ if (local == null)
+ throw new ResourceException(bundle.unfinishedLocalTransactionNotProvideLocalTransaction(this));
+ else
+ {
+ local.rollback();
+ log.debugf("Unfinished local transaction was rolled back.%s", this);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ void haltCatchFire()
+ {
+ if (isEnlisted())
+ {
+ if (transactionSynchronization != null)
+ transactionSynchronization.cancel();
+
+ String txId = "";
+
+ if (getConnectionManager().getTransactionIntegration() != null &&
+ getConnectionManager().getTransactionIntegration().getTransactionManager() != null)
+ {
+ Transaction tx = null;
+ try
+ {
+ tx = getConnectionManager().getTransactionIntegration().getTransactionManager().getTransaction();
+
+ if (Tracer.isEnabled() && tx != null)
+ txId = tx.toString();
+
+ if (TxUtils.isUncommitted(tx) && doDelistResource)
+ {
+ log.tracef("connectionErrorOccurred: delistResource(%s, TMFAIL)", getXAResource());
+
+ boolean failResult = tx.delistResource(getXAResource(), XAResource.TMFAIL);
+
+ if (failResult)
+ {
+ log.tracef("connectionErrorOccurred: delist-fail: %s", this);
+ }
+ else
+ {
+ log.debugf("connectionErrorOccurred: delist-fail failed: %s", this);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ log.debugf(e, "connectionErrorOccurred: Exception during delistResource=%s", e.getMessage());
+ }
+ finally
+ {
+ if (TxUtils.isUncommitted(tx) && doSetRollbackOnly)
+ {
+ try
+ {
+ tx.setRollbackOnly();
+ }
+ catch (Exception e)
+ {
+ // Just a hint
+ }
+ }
+ }
+ }
+
+ if (Tracer.isEnabled())
+ {
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ this, txId, false, true, false);
+ }
+ }
+
+ // Prepare to explode
+ setEnlisted(false);
+ transactionSynchronization = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ //Important method!!
+ @Override
+ public boolean isManagedConnectionFree()
+ {
+ if (isTrackByTx() && transactionSynchronization != null)
+ return false;
+ return super.isManagedConnectionFree();
+ }
+
+ /**
+ * This method changes the number of handles or
+ * the track-by-tx value depending on the parameter passed in
+ * @param handle The handle; if null
track-by-tx is changed
+ * @return True if the managed connection was freed
+ */
+ boolean wasFreed(Object handle)
+ {
+ if (handle != null)
+ {
+ // Unregister the handle
+ unregisterConnection(handle);
+ }
+ else
+ {
+ if (!isTrackByTx())
+ {
+ // Only change the state once
+ return false;
+ }
+
+ // Set track-by-tx to false
+ setTrackByTx(false);
+ }
+
+ // Return if the managed connection was just freed
+ return isManagedConnectionFree();
+ }
+
+ /**
+ * Transaction sync. class.
+ * Please note this class has public access is for test purposes only.
+ * Except for test purposes it should be considered private!
+ * Don't use it outside enclosing class or testcase!
+ */
+ public class TransactionSynchronization implements Synchronization
+ {
+ /**Error message*/
+ private final Throwable failedToEnlist;
+
+ /** Record enlist */
+ private final boolean recordEnlist;
+
+ /** Transaction */
+ protected final Transaction currentTx;
+
+ /** This is the status when we were registered */
+ private final boolean wasTrackByTx;
+
+ /** Whether we are enlisted */
+ private boolean enlisted;
+
+ /** Any error during enlistment */
+ private Throwable enlistError;
+
+ /** Cancel */
+ private boolean cancel;
+
+ /**
+ * Create a new TransactionSynchronization.transaction
+ * @param tx transaction
+ *
+ * @param trackByTx whether this is track by connection
+ */
+ public TransactionSynchronization(final Transaction tx, final boolean trackByTx)
+ {
+ this.currentTx = tx;
+ this.wasTrackByTx = trackByTx;
+ this.enlisted = false;
+ this.enlistError = null;
+ this.cancel = false;
+
+ if (TxConnectionListener.this.enlistmentTrace != null)
+ {
+ this.recordEnlist = TxConnectionListener.this.enlistmentTrace.booleanValue();
+ }
+ else
+ {
+ this.recordEnlist = !disableFailedtoEnlist;
+ }
+
+ if (this.recordEnlist)
+ {
+ this.failedToEnlist = new Throwable("Unabled to enlist resource, see the previous warnings.");
+ }
+ else
+ {
+ this.failedToEnlist = null;
+ }
+
+ log.tracef("%s: Constructor", toString());
+ }
+
+ /**
+ * Set the cancel flag
+ */
+ public void cancel()
+ {
+ cancel = true;
+ }
+
+ /**
+ * Get the result of the enlistment.
+ *
+ * @throws SystemException for any error
+ */
+ public void checkEnlisted() throws SystemException
+ {
+ if (this.enlistError != null)
+ {
+ String error = "Error enlisting resource in transaction=" + this.currentTx;
+ log.tracef("%s %s", error, TxConnectionListener.this);
+
+ // Wrap the error to give a reasonable stacktrace since the resource
+ // could have been enlisted by a different thread
+ if (recordEnlist && enlistError == failedToEnlist)
+ {
+ SystemException se =
+ new SystemException(bundle.systemExceptionWhenFailedToEnlistEqualsCurrentTx(
+ failedToEnlist, this.currentTx));
+
+ if (Tracer.isEnabled())
+ Tracer.exception(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, se);
+
+ throw se;
+
+ }
+ else
+ {
+ SystemException e = new SystemException(error);
+ e.initCause(enlistError);
+
+ if (Tracer.isEnabled())
+ Tracer.exception(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, e);
+
+ throw e;
+ }
+ }
+ if (!enlisted)
+ {
+ String error = "Resource is not enlisted in transaction=" + currentTx;
+ log.tracef("%s %s", error, TxConnectionListener.this);
+ throw new IllegalStateException("Resource was not enlisted.");
+ }
+ }
+
+ /**
+ * Enlist the resource
+ *
+ * @return true when enlisted, false otherwise
+ */
+ public boolean enlist()
+ {
+ log.tracef("Enlisting resource %s", TxConnectionListener.this);
+ try
+ {
+ XAResource resource = getXAResource();
+ if (!currentTx.enlistResource(resource))
+ {
+ if (Tracer.isEnabled())
+ Tracer.enlistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, currentTx.toString(), false,
+ !TxConnectionListener.this.isTrackByTx());
+
+ if (recordEnlist)
+ {
+ enlistError = failedToEnlist;
+ }
+ else
+ {
+ enlistError = new Throwable("Failed to enlist");
+ }
+ }
+ else
+ {
+ if (Tracer.isEnabled())
+ Tracer.enlistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, currentTx.toString(), true,
+ !TxConnectionListener.this.isTrackByTx());
+ }
+ }
+ catch (Throwable t)
+ {
+ enlistError = t;
+
+ if (Tracer.isEnabled())
+ Tracer.enlistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, currentTx.toString(), false,
+ !TxConnectionListener.this.isTrackByTx());
+ }
+
+ synchronized (this)
+ {
+ if (enlistError != null)
+ {
+ if (log.isTraceEnabled())
+ {
+ log.trace("Failed to enlist resource " + TxConnectionListener.this, enlistError);
+ }
+
+ setTrackByTx(false);
+ transactionSynchronization = null;
+
+ return false;
+ }
+
+ enlisted = true;
+
+ log.tracef("Enlisted resource %s", TxConnectionListener.this);
+
+ return true;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void beforeCompletion()
+ {
+ if (enlisted && !cancel)
+ {
+ try
+ {
+ if (this.equals(transactionSynchronization) && wasTrackByTx && doDelistResource)
+ {
+ if (TxUtils.isUncommitted(currentTx))
+ {
+ if (TxUtils.isActive(currentTx))
+ {
+ log.tracef("delistResource(%s, TMSUCCESS)", TxConnectionListener.this.getXAResource());
+
+ currentTx.delistResource(TxConnectionListener.this.getXAResource(), XAResource.TMSUCCESS);
+
+ if (Tracer.isEnabled())
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, currentTx.toString(),
+ true, false, false);
+ }
+ else
+ {
+ log.tracef("delistResource(%s, TMFAIL)", TxConnectionListener.this.getXAResource());
+
+ currentTx.delistResource(TxConnectionListener.this.getXAResource(), XAResource.TMFAIL);
+
+ if (Tracer.isEnabled())
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, currentTx.toString(),
+ false, false, false);
+ }
+ }
+ else
+ {
+ if (log.isTraceEnabled())
+ log.tracef("Non-uncommitted transaction for %s (%s)", TxConnectionListener.this,
+ currentTx != null ? TxUtils.getStatusAsString(currentTx.getStatus()) : "None");
+ }
+ }
+ else
+ {
+ log.tracef("No delistResource for: %s", TxConnectionListener.this);
+ }
+ }
+ catch (Throwable t)
+ {
+ log.beforeCompletionErrorOccured(TxConnectionListener.this, t);
+ }
+ }
+ else
+ {
+ log.tracef("Unenlisted resource: %s", TxConnectionListener.this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void afterCompletion(int status)
+ {
+ // The connection got destroyed during the transaction
+ if (getState().equals(ConnectionState.DESTROYED))
+ {
+ return;
+ }
+
+ if (!cancel)
+ {
+ // Are we still in the original transaction?
+ if (!this.equals(transactionSynchronization))
+ {
+ // If we are interleaving transactions we have nothing to do
+ if (!wasTrackByTx)
+ {
+ TxConnectionListener.this.setEnlisted(false);
+ return;
+ }
+ else
+ {
+ // There is something wrong with the pooling
+ String message = "afterCompletion called with wrong tx! Expected: " +
+ this + ", actual: " + transactionSynchronization;
+ IllegalStateException e = new IllegalStateException(message);
+ log.somethingWrongWithPooling(e);
+ }
+ }
+ // "Delist"
+ TxConnectionListener.this.setEnlisted(false);
+ transactionSynchronization = null;
+
+ // This is where we close when doing track by transaction
+ if (wasTrackByTx)
+ {
+ log.tracef("afterCompletion(%d) isTrackByTx=%b for %s"
+ , status, isTrackByTx(), TxConnectionListener.this);
+
+ if (wasFreed(null))
+ {
+ if (Tracer.isEnabled() && status == Status.STATUS_ROLLEDBACK)
+ Tracer.delistConnectionListener(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, "", true, true, false);
+
+ getConnectionManager().returnManagedConnection(TxConnectionListener.this, false);
+ }
+ else
+ {
+ if (tracking == null || tracking.booleanValue())
+ {
+ log.activeHandles(getPool() != null ? getPool().getName() : "Unknown", connectionHandles.size());
+
+ if (tracking != null && tracking.booleanValue())
+ {
+ Iterator> it = connectionTraces.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = it.next();
+ log.activeHandle(entry.getKey(), entry.getValue());
+ }
+
+ log.txConnectionListenerBoundary(new Exception());
+ }
+
+ if (Tracer.isEnabled())
+ {
+ for (Object c : connectionHandles)
+ {
+ Tracer.clearConnection(getPool() != null ? getPool().getName() : null,
+ getManagedConnectionPool(),
+ TxConnectionListener.this, c);
+ }
+ }
+
+ getConnectionManager().returnManagedConnection(TxConnectionListener.this, true);
+ }
+ else
+ {
+ if (log.isTraceEnabled())
+ log.tracef(new Exception("Connection across boundary"), "ConnectionListener=%s",
+ TxConnectionListener.this);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("TransactionSynchronization@").append(System.identityHashCode(this));
+ buffer.append("{tx=").append(currentTx);
+ buffer.append(" wasTrackByTx=").append(wasTrackByTx);
+ buffer.append(" enlisted=").append(enlisted);
+ buffer.append(" cancel=").append(cancel);
+ buffer.append("}");
+ return buffer.toString();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // For debugging
+ @Override
+ protected void toString(StringBuffer buffer)
+ {
+ buffer.append(" xaResource=").append(xaResource);
+ buffer.append(" txSync=").append(transactionSynchronization);
+ }
+
+ /**
+ * Get the transactionSynchronization.
+ * Please note this package protected method is for test purposes only. Don't use it!
+ *
+ * @return the transactionSynchronization.
+ */
+ final TransactionSynchronization getTransactionSynchronization()
+ {
+ return transactionSynchronization;
+ }
+
+ /**
+ * Set the transactionSynchronization.
+ * Please note this package protected method is for test purposes only. Don't use it!
+ *
+ * @param transactionSynchronization The transactionSynchronization to set.
+ */
+ final void setTransactionSynchronization(TransactionSynchronization transactionSynchronization)
+ {
+ this.transactionSynchronization = transactionSynchronization;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/listener/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the connection listener implementation.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManagerImpl.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManagerImpl.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManagerImpl.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,107 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.notx;
+
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.ConnectionRecord;
+import org.jboss.jca.core.connectionmanager.NoTxConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.listener.NoTxConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+
+import java.util.Collection;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ManagedConnection;
+import javax.transaction.SystemException;
+
+import org.jboss.logging.Logger;
+import org.jboss.logging.Messages;
+
+/**
+ * Non transactional connection manager implementation.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class NoTxConnectionManagerImpl extends AbstractConnectionManager implements NoTxConnectionManager
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, NoTxConnectionManager.class.getName());
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** Serial version uid */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Default constructor.
+ */
+ public NoTxConnectionManagerImpl()
+ {
+ }
+
+ /**
+ * Get the logger.
+ * @return The value
+ */
+ protected CoreLogger getLogger()
+ {
+ return log;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener createConnectionListener(ManagedConnection managedConnection, ManagedConnectionPool mcp)
+ throws ResourceException
+ {
+ ConnectionListener cli = new NoTxConnectionListener(this, managedConnection, getPool(),
+ mcp, getFlushStrategy(), getTracking());
+ managedConnection.addConnectionEventListener(cli);
+
+ return cli;
+ }
+
+ @Override
+ public void transactionStarted(Collection conns) throws SystemException
+ {
+ // Doing nothing
+ }
+
+ @Override
+ public TransactionIntegration getTransactionIntegration()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isTransactional()
+ {
+ return false;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/notx/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/notx/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/notx/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the non-tx connection manager implementation.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the connection manager implementation.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,1176 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool;
+
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.FlushMode;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolStatistics;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.TxConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.Capacity;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.api.Semaphore;
+import org.jboss.jca.core.connectionmanager.pool.capacity.DefaultCapacity;
+import org.jboss.jca.core.connectionmanager.pool.capacity.TimedOutDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPoolFactory;
+import org.jboss.jca.core.connectionmanager.transaction.LockKey;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+import org.jboss.jca.core.tracer.Tracer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+import org.jboss.logging.Messages;
+
+/**
+ * Abstract pool implementation.
+ *
+ * It can contains sub-pools according to the semantic of
+ * the pool. Concrete implementatins override {@link AbstractPool#getKey(Subject, ConnectionRequestInfo, boolean)}
+ * method to create map key object.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public abstract class AbstractPool implements Pool
+{
+ /** New line */
+ private static String newLine = SecurityActions.getSystemProperty("line.separator");
+
+ /** The logger */
+ protected final CoreLogger log;
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** The managed connection pools, maps key --> pool */
+ private final ConcurrentMap mcpPools =
+ new ConcurrentHashMap();
+
+ /** The managed connection factory for this pool */
+ private final ManagedConnectionFactory mcf;
+
+ /** The connection manager for this pool*/
+ private ConnectionManager cm;
+
+ /** The pool parameters */
+ private final PoolConfiguration poolConfiguration;
+
+ /** Whether to use separate pools for transactional and non-transaction use */
+ private final boolean noTxSeparatePools;
+
+ /** Shutdown */
+ private final AtomicBoolean shutdown = new AtomicBoolean(false);
+
+ /** The poolName */
+ private String poolName;
+
+ /** Statistics */
+ private PoolStatisticsImpl statistics;
+
+ /** The permits used to control who can checkout a connection */
+ private Semaphore permits;
+
+ /** Are the connections sharable */
+ private boolean sharable;
+
+ /** MCP class */
+ private String mcpClass;
+
+ /** The capacity */
+ private Capacity capacity;
+
+ /** Interleaving */
+ private boolean interleaving;
+
+ /** No lazy enlistment available */
+ private AtomicBoolean noLazyEnlistmentAvailable;
+
+ /**
+ * Create a new base pool.
+ *
+ * @param mcf the managed connection factory
+ * @param pc the pool configuration
+ * @param noTxSeparatePools noTxSeparatePool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ protected AbstractPool(final ManagedConnectionFactory mcf, final PoolConfiguration pc,
+ final boolean noTxSeparatePools, final boolean sharable,
+ final String mcp)
+ {
+ if (mcf == null)
+ throw new IllegalArgumentException("MCF is null");
+
+ if (pc == null)
+ throw new IllegalArgumentException("PoolConfiguration is null");
+
+ this.mcf = mcf;
+ this.poolConfiguration = pc;
+ this.noTxSeparatePools = noTxSeparatePools;
+ this.sharable = sharable;
+ this.mcpClass = mcp;
+ this.log = getLogger();
+ this.statistics = new PoolStatisticsImpl(pc.getMaxSize());
+ this.permits = new Semaphore(pc.getMaxSize(), pc.isFair(), statistics);
+ this.capacity = null;
+ this.interleaving = false;
+ this.noLazyEnlistmentAvailable = new AtomicBoolean(false);
+ }
+
+ /**
+ * Sets pool name.
+ * @param poolName pool name
+ */
+ public void setName(String poolName)
+ {
+ this.poolName = poolName;
+ }
+
+ /**
+ * Gets pool name.
+ * @return pool name
+ */
+ public String getName()
+ {
+ return poolName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Semaphore getLock()
+ {
+ return permits;
+ }
+
+ /**
+ * Is sharable
+ * @return The value
+ */
+ public boolean isSharable()
+ {
+ return sharable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Capacity getCapacity()
+ {
+ if (capacity == null)
+ return DefaultCapacity.INSTANCE;
+
+ return capacity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCapacity(Capacity c)
+ {
+ capacity = c;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isFIFO()
+ {
+ if (capacity == null || capacity.getDecrementer() == null ||
+ TimedOutDecrementer.class.getName().equals(capacity.getDecrementer().getClass().getName()))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInterleaving()
+ {
+ return interleaving;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInterleaving(boolean v)
+ {
+ interleaving = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isIdle()
+ {
+ for (ManagedConnectionPool mcp : mcpPools.values())
+ {
+ if (!mcp.isIdle())
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isFull()
+ {
+ return permits.availablePermits() == 0;
+ }
+
+ /**
+ * Retrieve the key for this request.
+ *
+ * @param subject the subject
+ * @param cri the connection request information
+ * @param separateNoTx separateNoTx
+ * @return the key
+ * @throws ResourceException for any error
+ */
+ protected abstract Object getKey(Subject subject, ConnectionRequestInfo cri,
+ boolean separateNoTx) throws ResourceException;
+
+ /**
+ * Determine the correct pool for this request,
+ * creates a new one when necessary.
+ *
+ * @param key the key to the pool
+ * @param subject the subject of the pool
+ * @param cri the connection request info
+ * @return the subpool context
+ * @throws ResourceException for any error
+ */
+ protected ManagedConnectionPool getManagedConnectionPool(Object key, Subject subject, ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ try
+ {
+ ManagedConnectionPool mcp = mcpPools.get(key);
+ if (mcp == null)
+ {
+ // Let sync, since it is expensive to create connections
+ synchronized (this)
+ {
+ mcp = mcpPools.get(key);
+
+ if (mcp == null)
+ {
+ ManagedConnectionPoolFactory mcpf = new ManagedConnectionPoolFactory();
+ ManagedConnectionPool newMcp = mcpf.create(mcpClass, mcf, cm, subject, cri, poolConfiguration, this);
+
+ mcp = mcpPools.putIfAbsent(key, newMcp);
+ if (mcp == null)
+ {
+ mcp = newMcp;
+
+ if (Tracer.isEnabled())
+ Tracer.createManagedConnectionPool(getName(), mcp);
+
+ try
+ {
+ initLock();
+ }
+ catch (Throwable lockThrowable)
+ {
+ // Init later then
+ }
+ }
+ else
+ {
+ // and shut them down again
+ newMcp.shutdown();
+ }
+
+ log.tracef("%s: mcpPools=%s", getName(), mcpPools);
+ }
+ }
+ }
+
+ return mcp;
+ }
+ catch (Throwable t)
+ {
+ throw new ResourceException(bundle.unableGetManagedConnectionPool(), t);
+ }
+ }
+
+ /**
+ * Get any transaction integration associated with the pool.
+ *
+ * @return the transaction integration
+ */
+ protected TransactionIntegration getTransactionIntegration()
+ {
+ if (cm != null)
+ return cm.getTransactionIntegration();
+
+ return null;
+ }
+
+ /**
+ * Get any transaction manager associated with the pool.
+ *
+ * @return the transaction manager
+ */
+ protected TransactionManager getTransactionManager()
+ {
+ if (getTransactionIntegration() != null)
+ return getTransactionIntegration().getTransactionManager();
+
+ return null;
+ }
+
+ /**
+ * Get any transaction synchronization registry associated with the pool.
+ * @return The value
+ */
+ protected TransactionSynchronizationRegistry getTransactionSynchronizationRegistry()
+ {
+ if (getTransactionIntegration() != null)
+ return getTransactionIntegration().getTransactionSynchronizationRegistry();
+
+ return null;
+ }
+
+ /**
+ * Init lock
+ * @return The lock
+ */
+ private Lock initLock()
+ {
+ TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
+
+ if (tsr != null)
+ return initLock(tsr);
+
+ return null;
+ }
+
+ /**
+ * Init lock
+ * @param tsr The transaction synchronization registry
+ * @return The lock
+ */
+ private Lock initLock(TransactionSynchronizationRegistry tsr)
+ {
+ if (tsr.getTransactionKey() != null)
+ {
+ Lock lock = (Lock)tsr.getResource(LockKey.INSTANCE);
+ if (lock == null)
+ {
+ lock = new ReentrantLock(true);
+ tsr.putResource(LockKey.INSTANCE, lock);
+ return lock;
+ }
+ else
+ {
+ return lock;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get TSR lock
+ * @return The lock; null
if TX isn't active
+ */
+ private Lock getTSRLock()
+ {
+ Lock result = null;
+ try
+ {
+ TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
+
+ if (tsr != null && tsr.getTransactionKey() != null)
+ {
+ result = (Lock)tsr.getResource(LockKey.INSTANCE);
+ if (result == null)
+ {
+ result = initLock(tsr);
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ // Catch all exceptions
+ }
+
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void emptyManagedConnectionPool(ManagedConnectionPool pool)
+ {
+ log.debugf("%s: emptyManagedConnectionPool(%s)", poolName, pool);
+
+ if (pool != null)
+ {
+ // We only consider removal if there are more than 1 managed connection pool
+ if (mcpPools.size() > 1 && pool.isEmpty())
+ {
+ if (mcpPools.values().remove(pool))
+ {
+ try
+ {
+ pool.shutdown();
+ }
+ catch (Exception e)
+ {
+ // Should not happen
+ log.trace("MCP.shutdown: " + e.getMessage(), e);
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.destroyManagedConnectionPool(getName(), pool);
+
+ log.tracef("%s: mcpPools=%s", getName(), mcpPools);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void flush()
+ {
+ flush(FlushMode.IDLE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void flush(boolean kill)
+ {
+ if (!kill)
+ {
+ flush(FlushMode.IDLE);
+ }
+ else
+ {
+ flush(FlushMode.ALL);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void flush(FlushMode mode)
+ {
+ final Collection removedConnectionListeners = new ArrayList();
+ synchronized (this)
+ {
+ log.debugf("%s: flush(%s)", poolName, mode);
+
+ Set clearMcpPools = new HashSet();
+ int size = mcpPools.size();
+
+ Iterator it = mcpPools.values().iterator();
+ while (it.hasNext())
+ {
+ ManagedConnectionPool mcp = it.next();
+ try
+ {
+ mcp.flush(mode, removedConnectionListeners);
+ }
+ catch (Exception e)
+ {
+ // Should not happen
+ log.trace("MCP.flush: " + e.getMessage(), e);
+ }
+
+ if (mcp.isEmpty() && !isPrefill() && size > 1)
+ clearMcpPools.add(mcp);
+ }
+
+ if (clearMcpPools.size() > 0)
+ {
+ for (ManagedConnectionPool mcp : clearMcpPools)
+ {
+ if (mcp.isEmpty())
+ {
+ try
+ {
+ mcp.shutdown();
+ }
+ catch (Exception e)
+ {
+ // Should not happen
+ log.trace("MCP.shutdown: " + e.getMessage(), e);
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.destroyManagedConnectionPool(getName(), mcp);
+
+ mcpPools.values().remove(mcp);
+ }
+ }
+
+ log.tracef("%s: mcpPools=%s", getName(), mcpPools);
+ }
+ }
+ if (removedConnectionListeners != null)
+ {
+ removedConnectionListeners.parallelStream().forEach(cl ->{
+ log.tracef("Destroying flushed connection %s", cl);
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(getName(), cl.getManagedConnectionPool(), cl, false, false, false, true,
+ false, false, false, Tracer.isRecordCallstacks() ? new Throwable("CALLSTACK") : null);
+ cl.destroy();
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener getConnection(Transaction trackByTransaction, Subject subject, ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ ConnectionListener cl = null;
+ boolean separateNoTx = false;
+
+ if (shutdown.get())
+ throw new ResourceException(bundle.connectionManagerIsShutdown(poolName));
+
+ if (noTxSeparatePools)
+ {
+ separateNoTx = cm.isTransactional();
+ }
+
+ // Get specific managed connection pool key
+ Object key = getKey(subject, cri, separateNoTx);
+
+ // Get managed connection pool
+ ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri);
+
+ // Are we doing track by transaction ?
+ TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
+ Object transactionKey = tsr != null ? tsr.getTransactionKey() : null;
+
+ if (trackByTransaction == null || transactionKey == null)
+ {
+ return getSimpleConnection(subject, cri, mcp);
+ }
+
+ // Transaction old connections
+ cl = getTransactionOldConnection(trackByTransaction, mcp);
+
+ // Creates a new connection with given transaction
+ if (cl == null)
+ {
+ cl = getTransactionNewConnection(trackByTransaction, mcp, subject, cri);
+ }
+
+ return cl;
+ }
+
+ /**
+ * Gets simple connection listener that wraps connection.
+ * @param subject Subject instance
+ * @param cri Connection request info
+ * @param mcp The managed connection pool
+ * @return connection listener
+ * @throws ResourceException ResourceException
+ */
+ private ConnectionListener getSimpleConnection(final Subject subject, final ConnectionRequestInfo cri,
+ final ManagedConnectionPool mcp)
+ throws ResourceException
+ {
+ // Get connection from the managed connection pool
+ ConnectionListener cl = mcp.getConnection(subject, cri);
+
+ log.tracef("Got connection from pool: %s", cl);
+
+ if (cm instanceof TxConnectionManager && cm.getCachedConnectionManager() == null &&
+ noLazyEnlistmentAvailable.compareAndSet(false, true))
+ log.noLazyEnlistmentAvailable(poolName);
+
+ return cl;
+ }
+
+ /**
+ * Gets connection listener instance associated with transaction.
+ * This method is package protected beacause it is intended only for test case use.
+ * Please don't use it in your production code.
+ * @param trackByTransaction transaction instance
+ * @param mcp the managed connection pool associated with the desired connection listener
+ * @return connection listener instance
+ * @throws ResourceException Thrown if an error occurs
+ */
+ ConnectionListener getTransactionOldConnection(Transaction trackByTransaction, ManagedConnectionPool mcp)
+ throws ResourceException
+ {
+ TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
+ Lock lock = getTSRLock();
+
+ if (lock == null)
+ throw new ResourceException(bundle.unableObtainLock());
+
+ try
+ {
+ lock.lockInterruptibly();
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.interrupted();
+
+ throw new ResourceException(bundle.unableObtainLock(), ie);
+ }
+ try
+ {
+ // Already got one
+ ConnectionListener cl = (ConnectionListener)tsr.getResource(mcp);
+ if (cl != null)
+ {
+ log.tracef("Previous connection tracked by transaction=%s tx=%s", cl, trackByTransaction);
+ return cl;
+ }
+
+ return null;
+ }
+ catch (Throwable t)
+ {
+ throw new ResourceException(bundle.unableGetConnectionListener(), t);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Gets new connection listener if necessary instance with transaction.
+ * This method is package protected beacause it is intended only for test case use.
+ * Please don't use it in your production code.
+ * @param trackByTransaction transaction instance
+ * @param mcp pool instance
+ * @param subject subject instance
+ * @param cri connection request info
+ * @return connection listener instance
+ * @throws ResourceException ResourceException
+ */
+ ConnectionListener getTransactionNewConnection(Transaction trackByTransaction, ManagedConnectionPool mcp,
+ Subject subject, ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ // Need a new one for this transaction
+ // This must be done outside the tx local lock, otherwise
+ // the tx timeout won't work and get connection can do a lot of other work
+ // with many opportunities for deadlocks.
+ // Instead we do a double check after we got the transaction to see
+ // whether another thread beat us to the punch.
+ ConnectionListener cl = mcp.getConnection(subject, cri);
+ log.tracef("Got connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);
+
+ if (cm.isEnlistment() && cl.supportsLazyEnlistment())
+ {
+ log.tracef("Lazy enlistment connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);
+
+ return cl;
+ }
+
+ TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
+ Lock lock = getTSRLock();
+
+ if (lock == null)
+ {
+ if (cl != null)
+ {
+ log.tracef("Killing connection tracked by transaction=%s tx=%s", cl, trackByTransaction);
+
+ returnConnection(cl, true);
+ }
+
+ throw new ResourceException(bundle.unableObtainLock());
+ }
+
+ try
+ {
+ lock.lockInterruptibly();
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.interrupted();
+
+ if (cl != null)
+ {
+ log.tracef("Killing connection tracked by transaction=%s tx=%s", cl, trackByTransaction);
+
+ returnConnection(cl, true);
+ }
+
+ throw new ResourceException(bundle.unableObtainLock(), ie);
+ }
+ try
+ {
+ // Check we weren't racing with another transaction
+ ConnectionListener other =
+ (ConnectionListener)tsr.getResource(mcp);
+
+ if (other != null)
+ {
+ returnConnection(cl, false);
+
+ log.tracef("Another thread already got a connection tracked by transaction=%s tx=%s",
+ other, trackByTransaction);
+
+ cl = other;
+ }
+
+ // This is the connection for this transaction
+ cl.setTrackByTx(true);
+ tsr.putResource(mcp, cl);
+
+ log.tracef("Using connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);
+
+ return cl;
+ }
+ catch (Throwable t)
+ {
+ if (cl != null)
+ {
+ log.tracef("Killing connection tracked by transaction=%s tx=%s", cl, trackByTransaction);
+
+ returnConnection(cl, true);
+ }
+
+ throw new ResourceException(bundle.unableGetConnectionListener(), t);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc)
+ {
+ return findConnectionListener(mc, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc, Object connection)
+ {
+ for (ManagedConnectionPool mcp : mcpPools.values())
+ {
+ ConnectionListener cl = mcp.findConnectionListener(mc, connection);
+ if (cl != null)
+ return cl;
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ManagedConnectionFactory getManagedConnectionFactory()
+ {
+ return mcf;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill) throws ResourceException
+ {
+ cl.setTrackByTx(false);
+ //Get connection listener pool
+ ManagedConnectionPool mcp = cl.getManagedConnectionPool();
+
+ if (Tracer.isEnabled())
+ {
+ if (kill && cl.getException() != null)
+ Tracer.exception(poolName, cl.getManagedConnectionPool(), cl, cl.getException());
+
+ Tracer.returnConnectionListener(poolName, cl.getManagedConnectionPool(), cl, kill, interleaving,
+ Tracer.isRecordCallstacks() ? new Throwable("CALLSTACK") : null);
+ }
+
+ //Return connection to the pool
+ mcp.returnConnection(cl, kill);
+
+ log.tracef("Returning connection to pool %s", cl);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasConnection(Subject subject, ConnectionRequestInfo cri)
+ {
+ TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
+ Lock lock = getTSRLock();
+
+ if (lock == null)
+ return false;
+
+ try
+ {
+ lock.lockInterruptibly();
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.interrupted();
+ return false;
+ }
+ try
+ {
+ boolean separateNoTx = false;
+
+ if (noTxSeparatePools)
+ {
+ separateNoTx = cm.isTransactional();
+ }
+
+ // Get specific managed connection pool key
+ Object key = getKey(subject, cri, separateNoTx);
+
+ // Get managed connection pool
+ ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri);
+
+ // Already got one
+ ConnectionListener cl = (ConnectionListener)tsr.getResource(mcp);
+ if (cl != null)
+ {
+ return true;
+ }
+ }
+ catch (Throwable t)
+ {
+ log.debugf(t, "hasConnection error: %s", t.getMessage());
+ }
+ finally
+ {
+ lock.unlock();
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the connection manager
+ * @return The value
+ */
+ protected ConnectionManager getConnectionManager()
+ {
+ return cm;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setConnectionManager(ConnectionManager cm)
+ {
+ this.cm = cm;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isShutdown()
+ {
+ return shutdown.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void shutdown()
+ {
+ log.debugf("%s: shutdown", poolName);
+ shutdown.set(true);
+
+ Iterator it = mcpPools.values().iterator();
+ while (it.hasNext())
+ {
+ ManagedConnectionPool mcp = it.next();
+ try
+ {
+ mcp.shutdown();
+ }
+ catch (Exception e)
+ {
+ // Should not happen
+ log.tracef(e, "MCP.shutdown: %s", e.getMessage());
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.destroyManagedConnectionPool(getName(), mcp);
+ }
+
+ mcpPools.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prepareShutdown()
+ {
+ log.debugf("%s: prepareShutdown", poolName);
+ shutdown.set(true);
+
+ flush(FlushMode.GRACEFULLY);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean cancelShutdown()
+ {
+ log.debugf("%s: cancelShutdown", poolName);
+
+ if (shutdown.get())
+ {
+ shutdown.set(false);
+
+ if (isPrefill())
+ {
+ Iterator it = mcpPools.values().iterator();
+ while (it.hasNext())
+ {
+ ManagedConnectionPool mcp = it.next();
+ try
+ {
+ mcp.prefill();
+ }
+ catch (Exception e)
+ {
+ // Should not happen
+ log.trace("MCP.prefill: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PoolStatistics getStatistics()
+ {
+ return statistics;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PoolStatisticsImpl getInternalStatistics()
+ {
+ return statistics;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract boolean testConnection();
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract boolean testConnection(ConnectionRequestInfo cri, Subject subject);
+
+ /**
+ * Test if a connection can be obtained
+ * @param subject Optional subject
+ * @param cri Optional CRI
+ * @return True if possible; otherwise false
+ */
+ protected boolean internalTestConnection(ConnectionRequestInfo cri, Subject subject)
+ {
+ log.debugf("%s: testConnection(%s, %s) (%s)", poolName, cri, subject,
+ Integer.toHexString(System.identityHashCode(subject)));
+
+ log.debugf("%s: Statistics=%s", poolName, statistics);
+
+ boolean result = false;
+ boolean kill = false;
+ ConnectionListener cl = null;
+
+ if (shutdown.get())
+ return false;
+
+ if (isFull())
+ return false;
+
+ try
+ {
+ boolean separateNoTx = false;
+
+ if (noTxSeparatePools)
+ {
+ separateNoTx = cm.isTransactional();
+ }
+
+ Object key = getKey(subject, cri, separateNoTx);
+ ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri);
+
+ cl = mcp.getConnection(subject, cri);
+ result = true;
+ }
+ catch (Throwable t)
+ {
+ kill = true;
+ }
+ finally
+ {
+ if (cl != null)
+ {
+ try
+ {
+ returnConnection(cl, kill);
+ }
+ catch (ResourceException ire)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] dumpQueuedThreads()
+ {
+ List result = new ArrayList();
+
+ if (permits.hasQueuedThreads())
+ {
+ Collection queuedThreads = new ArrayList(permits.getQueuedThreads());
+ for (Thread t : queuedThreads)
+ {
+ result.add(dumpQueuedThread(t));
+ }
+ }
+
+ return result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * Dump a thread
+ * @param t The thread
+ * @return The stack trace
+ */
+ private String dumpQueuedThread(Thread t)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ // Header
+ sb = sb.append("Queued thread: ");
+ sb = sb.append(t.getName());
+ sb = sb.append(newLine);
+
+ // Body
+ StackTraceElement[] stes = SecurityActions.getStackTrace(t);
+ if (stes != null)
+ {
+ for (StackTraceElement ste : stes)
+ {
+ sb = sb.append(" ");
+ sb = sb.append(ste.getClassName());
+ sb = sb.append(":");
+ sb = sb.append(ste.getMethodName());
+ sb = sb.append(":");
+ sb = sb.append(ste.getLineNumber());
+ sb = sb.append(newLine);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Get the managed connection pools.
+ * @return The managed connection pools
+ */
+ protected ConcurrentMap getManagedConnectionPools()
+ {
+ return mcpPools;
+ }
+
+ /**
+ * Get the pool configuration
+ * @return The value
+ */
+ protected PoolConfiguration getPoolConfiguration()
+ {
+ return poolConfiguration;
+ }
+
+ /**
+ * Is prefill
+ * @return The value
+ */
+ protected boolean isPrefill()
+ {
+ return false;
+ }
+
+ /**
+ * Get the logger
+ * @return The value
+ */
+ public abstract CoreLogger getLogger();
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/AbstractPrefillPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/AbstractPrefillPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/AbstractPrefillPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,93 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool;
+
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.pool.api.PrefillPool;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+/**
+ * Abstract pool implementation which can be prefilled.
+ *
+ * @author Jesper Pedersen
+ */
+public abstract class AbstractPrefillPool extends AbstractPool implements PrefillPool
+{
+ /** Should prefill be performed */
+ private boolean shouldPrefill = false;
+
+ /**
+ * Create a new prefill pool.
+ *
+ * @param mcf the managed connection factory
+ * @param pc the pool configuration
+ * @param noTxSeparatePools noTxSeparatePool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ protected AbstractPrefillPool(final ManagedConnectionFactory mcf, final PoolConfiguration pc,
+ final boolean noTxSeparatePools, final boolean sharable, final String mcp)
+ {
+ super(mcf, pc, noTxSeparatePools, sharable, mcp);
+ this.shouldPrefill = pc.isPrefill() || pc.isStrictMin();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prefill(Subject subject, ConnectionRequestInfo cri, boolean noTxnSeperatePool)
+ {
+ if (shouldPrefill)
+ {
+ if (log.isDebugEnabled())
+ log.debug("Attempting to prefill pool: " + getName());
+
+ try
+ {
+ //Get pool key
+ Object key = getKey(subject, cri, noTxnSeperatePool);
+
+ //Get pool automatically initializes pool
+ getManagedConnectionPool(key, subject, cri);
+ }
+ catch (Throwable t)
+ {
+ //No real need to throw here being that pool remains in the same state as before.
+ log.error("Unable to prefill pool: " + getName(), t);
+ }
+ }
+ }
+
+ /**
+ * Is prefill
+ * @return The value
+ */
+ @Override
+ protected boolean isPrefill()
+ {
+ return getPoolConfiguration().getMinSize() > 0;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/PoolStatisticsImpl.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/PoolStatisticsImpl.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/PoolStatisticsImpl.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,1752 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool;
+
+import org.jboss.jca.core.api.connectionmanager.pool.PoolStatistics;
+import org.jboss.jca.core.spi.transaction.XAResourceStatistics;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Pool statistics
+ *
+ * @author Jesper Pedersen
+ */
+public class PoolStatisticsImpl implements PoolStatistics, XAResourceStatistics
+{
+ /** Serial version uid */
+ private static final long serialVersionUID = 9L;
+
+ private static final String ACTIVE_COUNT = "ActiveCount";
+ private static final String AVAILABLE_COUNT = "AvailableCount";
+ private static final String AVERAGE_BLOCKING_TIME = "AverageBlockingTime";
+ private static final String AVERAGE_CREATION_TIME = "AverageCreationTime";
+ private static final String AVERAGE_GET_TIME = "AverageGetTime";
+ private static final String AVERAGE_POOL_TIME = "AveragePoolTime";
+ private static final String AVERAGE_USAGE_TIME = "AverageUsageTime";
+ private static final String BLOCKING_FAILURE_COUNT = "BlockingFailureCount";
+ private static final String CREATED_COUNT = "CreatedCount";
+ private static final String DESTROYED_COUNT = "DestroyedCount";
+ private static final String IDLE_COUNT = "IdleCount";
+ private static final String IN_USE_COUNT = "InUseCount";
+ private static final String MAX_CREATION_TIME = "MaxCreationTime";
+ private static final String MAX_GET_TIME = "MaxGetTime";
+ private static final String MAX_POOL_TIME = "MaxPoolTime";
+ private static final String MAX_USAGE_TIME = "MaxUsageTime";
+ private static final String MAX_USED_COUNT = "MaxUsedCount";
+ private static final String MAX_WAIT_COUNT = "MaxWaitCount";
+ private static final String MAX_WAIT_TIME = "MaxWaitTime";
+ private static final String TIMED_OUT = "TimedOut";
+ private static final String TOTAL_BLOCKING_TIME = "TotalBlockingTime";
+ private static final String TOTAL_CREATION_TIME = "TotalCreationTime";
+ private static final String TOTAL_GET_TIME = "TotalGetTime";
+ private static final String TOTAL_POOL_TIME = "TotalPoolTime";
+ private static final String TOTAL_USAGE_TIME = "TotalUsageTime";
+ private static final String WAIT_COUNT = "WaitCount";
+
+ private static final String XA_COMMIT_COUNT = "XACommitCount";
+ private static final String XA_COMMIT_AVERAGE_TIME = "XACommitAverageTime";
+ private static final String XA_COMMIT_TOTAL_TIME = "XACommitTotalTime";
+ private static final String XA_COMMIT_MAX_TIME = "XACommitMaxTime";
+ private static final String XA_END_COUNT = "XAEndCount";
+ private static final String XA_END_AVERAGE_TIME = "XAEndAverageTime";
+ private static final String XA_END_TOTAL_TIME = "XAEndTotalTime";
+ private static final String XA_END_MAX_TIME = "XAEndMaxTime";
+ private static final String XA_FORGET_COUNT = "XAForgetCount";
+ private static final String XA_FORGET_AVERAGE_TIME = "XAForgetAverageTime";
+ private static final String XA_FORGET_TOTAL_TIME = "XAForgetTotalTime";
+ private static final String XA_FORGET_MAX_TIME = "XAForgetMaxTime";
+ private static final String XA_PREPARE_COUNT = "XAPrepareCount";
+ private static final String XA_PREPARE_AVERAGE_TIME = "XAPrepareAverageTime";
+ private static final String XA_PREPARE_TOTAL_TIME = "XAPrepareTotalTime";
+ private static final String XA_PREPARE_MAX_TIME = "XAPrepareMaxTime";
+ private static final String XA_RECOVER_COUNT = "XARecoverCount";
+ private static final String XA_RECOVER_AVERAGE_TIME = "XARecoverAverageTime";
+ private static final String XA_RECOVER_TOTAL_TIME = "XARecoverTotalTime";
+ private static final String XA_RECOVER_MAX_TIME = "XARecoverMaxTime";
+ private static final String XA_ROLLBACK_COUNT = "XARollbackCount";
+ private static final String XA_ROLLBACK_AVERAGE_TIME = "XARollbackAverageTime";
+ private static final String XA_ROLLBACK_TOTAL_TIME = "XARollbackTotalTime";
+ private static final String XA_ROLLBACK_MAX_TIME = "XARollbackMaxTime";
+ private static final String XA_START_COUNT = "XAStartCount";
+ private static final String XA_START_AVERAGE_TIME = "XAStartAverageTime";
+ private static final String XA_START_TOTAL_TIME = "XAStartTotalTime";
+ private static final String XA_START_MAX_TIME = "XAStartMaxTime";
+
+ private int maxPoolSize;
+ private transient SortedSet names;
+ private transient Map types;
+ private transient Map rbs;
+
+ private transient AtomicBoolean enabled;
+ private transient AtomicInteger createdCount;
+ private transient AtomicInteger destroyedCount;
+ private transient AtomicInteger maxUsedCount;
+ private transient AtomicLong maxCreationTime;
+ private transient AtomicLong maxGetTime;
+ private transient AtomicLong maxPoolTime;
+ private transient AtomicLong maxUsageTime;
+ private transient AtomicInteger maxWaitCount;
+ private transient AtomicLong maxWaitTime;
+ private transient AtomicInteger timedOut;
+ private transient AtomicLong totalBlockingTime;
+ private transient AtomicLong totalBlockingTimeInvocations;
+ private transient AtomicLong totalCreationTime;
+ private transient AtomicLong totalGetTime;
+ private transient AtomicLong totalGetTimeInvocations;
+ private transient AtomicLong totalPoolTime;
+ private transient AtomicLong totalPoolTimeInvocations;
+ private transient AtomicLong totalUsageTime;
+ private transient AtomicLong totalUsageTimeInvocations;
+ private transient AtomicInteger inUseCount;
+ private transient AtomicInteger blockingFailureCount;
+ private transient AtomicInteger waitCount;
+
+
+ private transient AtomicLong commitCount;
+ private transient AtomicLong commitTotalTime;
+ private transient AtomicLong commitMaxTime;
+ private transient AtomicLong endCount;
+ private transient AtomicLong endTotalTime;
+ private transient AtomicLong endMaxTime;
+ private transient AtomicLong forgetCount;
+ private transient AtomicLong forgetTotalTime;
+ private transient AtomicLong forgetMaxTime;
+ private transient AtomicLong prepareCount;
+ private transient AtomicLong prepareTotalTime;
+ private transient AtomicLong prepareMaxTime;
+ private transient AtomicLong recoverCount;
+ private transient AtomicLong recoverTotalTime;
+ private transient AtomicLong recoverMaxTime;
+ private transient AtomicLong rollbackCount;
+ private transient AtomicLong rollbackTotalTime;
+ private transient AtomicLong rollbackMaxTime;
+ private transient AtomicLong startCount;
+ private transient AtomicLong startTotalTime;
+ private transient AtomicLong startMaxTime;
+
+ /**
+ * Constructor
+ * @param maxPoolSize The maximum pool size
+ */
+ public PoolStatisticsImpl(int maxPoolSize)
+ {
+ init(maxPoolSize);
+ }
+
+ /**
+ * Init
+ * @param maxPoolSize The maximum pool size
+ */
+ private void init(int maxPoolSize)
+ {
+ this.maxPoolSize = maxPoolSize;
+
+ this.createdCount = new AtomicInteger(0);
+ this.destroyedCount = new AtomicInteger(0);
+ this.maxCreationTime = new AtomicLong(Long.MIN_VALUE);
+ this.maxGetTime = new AtomicLong(Long.MIN_VALUE);
+ this.maxPoolTime = new AtomicLong(Long.MIN_VALUE);
+ this.maxUsageTime = new AtomicLong(Long.MIN_VALUE);
+ this.maxUsedCount = new AtomicInteger(Integer.MIN_VALUE);
+ this.maxWaitCount = new AtomicInteger(0);
+ this.maxWaitTime = new AtomicLong(Long.MIN_VALUE);
+ this.timedOut = new AtomicInteger(0);
+ this.totalBlockingTime = new AtomicLong(0);
+ this.totalBlockingTimeInvocations = new AtomicLong(0);
+ this.totalCreationTime = new AtomicLong(0);
+ this.totalGetTime = new AtomicLong(0);
+ this.totalGetTimeInvocations = new AtomicLong(0);
+ this.totalPoolTime = new AtomicLong(0);
+ this.totalPoolTimeInvocations = new AtomicLong(0);
+ this.totalUsageTime = new AtomicLong(0);
+ this.totalUsageTimeInvocations = new AtomicLong(0);
+ this.inUseCount = new AtomicInteger(0);
+ this.blockingFailureCount = new AtomicInteger(0);
+ this.waitCount = new AtomicInteger(0);
+
+ this.commitCount = new AtomicLong(0L);
+ this.commitTotalTime = new AtomicLong(0L);
+ this.commitMaxTime = new AtomicLong(0L);
+ this.endCount = new AtomicLong(0L);
+ this.endTotalTime = new AtomicLong(0L);
+ this.endMaxTime = new AtomicLong(0L);
+ this.forgetCount = new AtomicLong(0L);
+ this.forgetTotalTime = new AtomicLong(0L);
+ this.forgetMaxTime = new AtomicLong(0L);
+ this.prepareCount = new AtomicLong(0L);
+ this.prepareTotalTime = new AtomicLong(0L);
+ this.prepareMaxTime = new AtomicLong(0L);
+ this.recoverCount = new AtomicLong(0L);
+ this.recoverTotalTime = new AtomicLong(0L);
+ this.recoverMaxTime = new AtomicLong(0L);
+ this.rollbackCount = new AtomicLong(0L);
+ this.rollbackTotalTime = new AtomicLong(0L);
+ this.rollbackMaxTime = new AtomicLong(0L);
+ this.startCount = new AtomicLong(0L);
+ this.startTotalTime = new AtomicLong(0L);
+ this.startMaxTime = new AtomicLong(0L);
+
+ SortedSet n = new TreeSet();
+ Map t = new HashMap();
+
+ n.add(ACTIVE_COUNT);
+ t.put(ACTIVE_COUNT, int.class);
+
+ n.add(AVAILABLE_COUNT);
+ t.put(AVAILABLE_COUNT, int.class);
+
+ n.add(AVERAGE_BLOCKING_TIME);
+ t.put(AVERAGE_BLOCKING_TIME, long.class);
+
+ n.add(AVERAGE_CREATION_TIME);
+ t.put(AVERAGE_CREATION_TIME, long.class);
+
+ n.add(AVERAGE_GET_TIME);
+ t.put(AVERAGE_GET_TIME, long.class);
+
+ n.add(AVERAGE_USAGE_TIME);
+ t.put(AVERAGE_USAGE_TIME, long.class);
+
+ n.add(AVERAGE_POOL_TIME);
+ t.put(AVERAGE_POOL_TIME, long.class);
+
+ n.add(BLOCKING_FAILURE_COUNT);
+ t.put(BLOCKING_FAILURE_COUNT, int.class);
+
+ n.add(CREATED_COUNT);
+ t.put(CREATED_COUNT, int.class);
+
+ n.add(DESTROYED_COUNT);
+ t.put(DESTROYED_COUNT, int.class);
+
+ n.add(IDLE_COUNT);
+ t.put(IDLE_COUNT, int.class);
+
+ n.add(IN_USE_COUNT);
+ t.put(IN_USE_COUNT, int.class);
+
+ n.add(MAX_CREATION_TIME);
+ t.put(MAX_CREATION_TIME, long.class);
+
+ n.add(MAX_GET_TIME);
+ t.put(MAX_GET_TIME, long.class);
+
+ n.add(MAX_POOL_TIME);
+ t.put(MAX_POOL_TIME, long.class);
+
+ n.add(MAX_USAGE_TIME);
+ t.put(MAX_USAGE_TIME, long.class);
+
+ n.add(MAX_USED_COUNT);
+ t.put(MAX_USED_COUNT, int.class);
+
+ n.add(MAX_WAIT_COUNT);
+ t.put(MAX_WAIT_COUNT, int.class);
+
+ n.add(MAX_WAIT_TIME);
+ t.put(MAX_WAIT_TIME, long.class);
+
+ n.add(TIMED_OUT);
+ t.put(TIMED_OUT, int.class);
+
+ n.add(TOTAL_BLOCKING_TIME);
+ t.put(TOTAL_BLOCKING_TIME, long.class);
+
+ n.add(TOTAL_CREATION_TIME);
+ t.put(TOTAL_CREATION_TIME, long.class);
+
+ n.add(TOTAL_GET_TIME);
+ t.put(TOTAL_GET_TIME, long.class);
+
+ n.add(TOTAL_POOL_TIME);
+ t.put(TOTAL_POOL_TIME, long.class);
+
+ n.add(TOTAL_USAGE_TIME);
+ t.put(TOTAL_USAGE_TIME, long.class);
+
+ n.add(WAIT_COUNT);
+ t.put(WAIT_COUNT, int.class);
+
+ n.add(XA_COMMIT_COUNT);
+ t.put(XA_COMMIT_COUNT, long.class);
+ n.add(XA_COMMIT_AVERAGE_TIME);
+ t.put(XA_COMMIT_AVERAGE_TIME, long.class);
+ n.add(XA_COMMIT_TOTAL_TIME);
+ t.put(XA_COMMIT_TOTAL_TIME, long.class);
+ n.add(XA_COMMIT_MAX_TIME);
+ t.put(XA_COMMIT_MAX_TIME, long.class);
+
+ n.add(XA_END_COUNT);
+ t.put(XA_END_COUNT, long.class);
+ n.add(XA_END_AVERAGE_TIME);
+ t.put(XA_END_AVERAGE_TIME, long.class);
+ n.add(XA_END_TOTAL_TIME);
+ t.put(XA_END_TOTAL_TIME, long.class);
+ n.add(XA_END_MAX_TIME);
+ t.put(XA_END_MAX_TIME, long.class);
+
+ n.add(XA_FORGET_COUNT);
+ t.put(XA_FORGET_COUNT, long.class);
+ n.add(XA_FORGET_AVERAGE_TIME);
+ t.put(XA_FORGET_AVERAGE_TIME, long.class);
+ n.add(XA_FORGET_TOTAL_TIME);
+ t.put(XA_FORGET_TOTAL_TIME, long.class);
+ n.add(XA_FORGET_MAX_TIME);
+ t.put(XA_FORGET_MAX_TIME, long.class);
+
+ n.add(XA_PREPARE_COUNT);
+ t.put(XA_PREPARE_COUNT, long.class);
+ n.add(XA_PREPARE_AVERAGE_TIME);
+ t.put(XA_PREPARE_AVERAGE_TIME, long.class);
+ n.add(XA_PREPARE_TOTAL_TIME);
+ t.put(XA_PREPARE_TOTAL_TIME, long.class);
+ n.add(XA_PREPARE_MAX_TIME);
+ t.put(XA_PREPARE_MAX_TIME, long.class);
+
+ n.add(XA_RECOVER_COUNT);
+ t.put(XA_RECOVER_COUNT, long.class);
+ n.add(XA_RECOVER_AVERAGE_TIME);
+ t.put(XA_RECOVER_AVERAGE_TIME, long.class);
+ n.add(XA_RECOVER_TOTAL_TIME);
+ t.put(XA_RECOVER_TOTAL_TIME, long.class);
+ n.add(XA_RECOVER_MAX_TIME);
+ t.put(XA_RECOVER_MAX_TIME, long.class);
+
+ n.add(XA_ROLLBACK_COUNT);
+ t.put(XA_ROLLBACK_COUNT, long.class);
+ n.add(XA_ROLLBACK_AVERAGE_TIME);
+ t.put(XA_ROLLBACK_AVERAGE_TIME, long.class);
+ n.add(XA_ROLLBACK_TOTAL_TIME);
+ t.put(XA_ROLLBACK_TOTAL_TIME, long.class);
+ n.add(XA_ROLLBACK_MAX_TIME);
+ t.put(XA_ROLLBACK_MAX_TIME, long.class);
+
+ n.add(XA_START_COUNT);
+ t.put(XA_START_COUNT, long.class);
+ n.add(XA_START_AVERAGE_TIME);
+ t.put(XA_START_AVERAGE_TIME, long.class);
+ n.add(XA_START_TOTAL_TIME);
+ t.put(XA_START_TOTAL_TIME, long.class);
+ n.add(XA_START_MAX_TIME);
+ t.put(XA_START_MAX_TIME, long.class);
+
+ this.names = Collections.unmodifiableSortedSet(n);
+ this.types = Collections.unmodifiableMap(t);
+ this.enabled = new AtomicBoolean(true);
+
+ ResourceBundle defaultResourceBundle =
+ ResourceBundle.getBundle("poolstatistics", Locale.US,
+ SecurityActions.getClassLoader(PoolStatisticsImpl.class));
+ this.rbs = new HashMap(1);
+ this.rbs.put(Locale.US, defaultResourceBundle);
+
+ clear();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set getNames()
+ {
+ return names;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class getType(String name)
+ {
+ return types.get(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDescription(String name)
+ {
+ return getDescription(name, Locale.US);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDescription(String name, Locale locale)
+ {
+ ResourceBundle rb = rbs.get(locale);
+
+ if (rb == null)
+ {
+ ResourceBundle newResourceBundle =
+ ResourceBundle.getBundle("poolstatistics", locale,
+ SecurityActions.getClassLoader(PoolStatisticsImpl.class));
+
+ if (newResourceBundle != null)
+ rbs.put(locale, newResourceBundle);
+ }
+
+ if (rb == null)
+ rb = rbs.get(Locale.US);
+
+ if (rb != null)
+ return rb.getString(name);
+
+ return "";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object getValue(String name)
+ {
+ if (ACTIVE_COUNT.equals(name))
+ {
+ return getActiveCount();
+ }
+ else if (AVAILABLE_COUNT.equals(name))
+ {
+ return getAvailableCount();
+ }
+ else if (AVERAGE_BLOCKING_TIME.equals(name))
+ {
+ return getAverageBlockingTime();
+ }
+ else if (AVERAGE_CREATION_TIME.equals(name))
+ {
+ return getAverageCreationTime();
+ }
+ else if (AVERAGE_GET_TIME.equals(name))
+ {
+ return getAverageGetTime();
+ }
+ else if (AVERAGE_USAGE_TIME.equals(name))
+ {
+ return getAverageUsageTime();
+ }
+ else if (AVERAGE_POOL_TIME.equals(name))
+ {
+ return getAveragePoolTime();
+ }
+ else if (BLOCKING_FAILURE_COUNT.equals(name))
+ {
+ return getBlockingFailureCount();
+ }
+ else if (CREATED_COUNT.equals(name))
+ {
+ return getCreatedCount();
+ }
+ else if (DESTROYED_COUNT.equals(name))
+ {
+ return getDestroyedCount();
+ }
+ else if (IDLE_COUNT.equals(name))
+ {
+ return getIdleCount();
+ }
+ else if (IN_USE_COUNT.equals(name))
+ {
+ return getInUseCount();
+ }
+ else if (MAX_CREATION_TIME.equals(name))
+ {
+ return getMaxCreationTime();
+ }
+ else if (MAX_GET_TIME.equals(name))
+ {
+ return getMaxGetTime();
+ }
+ else if (MAX_POOL_TIME.equals(name))
+ {
+ return getMaxPoolTime();
+ }
+ else if (MAX_USAGE_TIME.equals(name))
+ {
+ return getMaxUsageTime();
+ }
+ else if (MAX_USED_COUNT.equals(name))
+ {
+ return getMaxUsedCount();
+ }
+ else if (MAX_WAIT_COUNT.equals(name))
+ {
+ return getMaxWaitCount();
+ }
+ else if (MAX_WAIT_TIME.equals(name))
+ {
+ return getMaxWaitTime();
+ }
+ else if (TIMED_OUT.equals(name))
+ {
+ return getTimedOut();
+ }
+ else if (TOTAL_BLOCKING_TIME.equals(name))
+ {
+ return getTotalBlockingTime();
+ }
+ else if (TOTAL_CREATION_TIME.equals(name))
+ {
+ return getTotalCreationTime();
+ }
+ else if (TOTAL_GET_TIME.equals(name))
+ {
+ return getTotalGetTime();
+ }
+ else if (TOTAL_POOL_TIME.equals(name))
+ {
+ return getTotalPoolTime();
+ }
+ else if (TOTAL_USAGE_TIME.equals(name))
+ {
+ return getTotalUsageTime();
+ }
+ else if (WAIT_COUNT.equals(name))
+ {
+ return getWaitCount();
+ }
+ else if (XA_COMMIT_COUNT.equals(name))
+ {
+ return getCommitCount();
+ }
+ else if (XA_COMMIT_AVERAGE_TIME.equals(name))
+ {
+ return getCommitAverageTime();
+ }
+ else if (XA_COMMIT_TOTAL_TIME.equals(name))
+ {
+ return getCommitTotalTime();
+ }
+ else if (XA_COMMIT_MAX_TIME.equals(name))
+ {
+ return getCommitMaxTime();
+ }
+ else if (XA_END_COUNT.equals(name))
+ {
+ return getEndCount();
+ }
+ else if (XA_END_AVERAGE_TIME.equals(name))
+ {
+ return getEndAverageTime();
+ }
+ else if (XA_END_TOTAL_TIME.equals(name))
+ {
+ return getEndTotalTime();
+ }
+ else if (XA_END_MAX_TIME.equals(name))
+ {
+ return getEndMaxTime();
+ }
+ else if (XA_FORGET_COUNT.equals(name))
+ {
+ return getForgetCount();
+ }
+ else if (XA_FORGET_AVERAGE_TIME.equals(name))
+ {
+ return getForgetAverageTime();
+ }
+ else if (XA_FORGET_TOTAL_TIME.equals(name))
+ {
+ return getForgetTotalTime();
+ }
+ else if (XA_FORGET_MAX_TIME.equals(name))
+ {
+ return getForgetMaxTime();
+ }
+ else if (XA_PREPARE_COUNT.equals(name))
+ {
+ return getPrepareCount();
+ }
+ else if (XA_PREPARE_AVERAGE_TIME.equals(name))
+ {
+ return getPrepareAverageTime();
+ }
+ else if (XA_PREPARE_TOTAL_TIME.equals(name))
+ {
+ return getPrepareTotalTime();
+ }
+ else if (XA_PREPARE_MAX_TIME.equals(name))
+ {
+ return getPrepareMaxTime();
+ }
+ else if (XA_RECOVER_COUNT.equals(name))
+ {
+ return getRecoverCount();
+ }
+ else if (XA_RECOVER_AVERAGE_TIME.equals(name))
+ {
+ return getRecoverAverageTime();
+ }
+ else if (XA_RECOVER_TOTAL_TIME.equals(name))
+ {
+ return getRecoverTotalTime();
+ }
+ else if (XA_RECOVER_MAX_TIME.equals(name))
+ {
+ return getRecoverMaxTime();
+ }
+ else if (XA_ROLLBACK_COUNT.equals(name))
+ {
+ return getRollbackCount();
+ }
+ else if (XA_ROLLBACK_AVERAGE_TIME.equals(name))
+ {
+ return getRollbackAverageTime();
+ }
+ else if (XA_ROLLBACK_TOTAL_TIME.equals(name))
+ {
+ return getRollbackTotalTime();
+ }
+ else if (XA_ROLLBACK_MAX_TIME.equals(name))
+ {
+ return getRollbackMaxTime();
+ }
+ else if (XA_START_COUNT.equals(name))
+ {
+ return getStartCount();
+ }
+ else if (XA_START_AVERAGE_TIME.equals(name))
+ {
+ return getStartAverageTime();
+ }
+ else if (XA_START_TOTAL_TIME.equals(name))
+ {
+ return getStartTotalTime();
+ }
+ else if (XA_START_MAX_TIME.equals(name))
+ {
+ return getStartMaxTime();
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled()
+ {
+ return enabled.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setEnabled(boolean v)
+ {
+ if (enabled.get() != v)
+ {
+ enabled.set(v);
+ clear();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getActiveCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ if (createdCount.get() < destroyedCount.get())
+ clear();
+
+ return createdCount.get() - destroyedCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getAvailableCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return maxPoolSize - inUseCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getAverageBlockingTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalBlockingTimeInvocations.get() != 0 ? totalBlockingTime.get() / totalBlockingTimeInvocations.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getAverageCreationTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return createdCount.get() != 0 ? totalCreationTime.get() / createdCount.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getAverageGetTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalGetTimeInvocations.get() != 0 ? totalGetTime.get() / totalGetTimeInvocations.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getAverageUsageTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalUsageTimeInvocations.get() != 0 ? totalUsageTime.get() / totalUsageTimeInvocations.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getAveragePoolTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalPoolTimeInvocations.get() != 0 ? totalPoolTime.get() / totalPoolTimeInvocations.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getBlockingFailureCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return blockingFailureCount.get();
+ }
+
+ /**
+ * Delta the blocking failure count value
+ */
+ public void deltaBlockingFailureCount()
+ {
+ if (enabled.get())
+ blockingFailureCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getCreatedCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return createdCount.get();
+ }
+
+ /**
+ * Delta the created count value
+ */
+ public void deltaCreatedCount()
+ {
+ if (enabled.get())
+ createdCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDestroyedCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return destroyedCount.get();
+ }
+
+ /**
+ * Delta the destroyed count value
+ */
+ public void deltaDestroyedCount()
+ {
+ if (enabled.get())
+ destroyedCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getIdleCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return getActiveCount() - getInUseCount();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getInUseCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return inUseCount.get();
+ }
+
+ /**
+ * Set in used count
+ * @param v The value
+ */
+ public void setInUsedCount(int v)
+ {
+ inUseCount.set(v);
+ setMaxUsedCount(v);
+ }
+
+ /**
+ * Get max used count
+ * @return The value
+ */
+ public int getMaxUsedCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return maxUsedCount.get() != Integer.MIN_VALUE ? maxUsedCount.get() : 0;
+ }
+
+ /**
+ * Set max used count
+ * @param v The value
+ */
+ private void setMaxUsedCount(int v)
+ {
+ if (v > maxUsedCount.get())
+ maxUsedCount.set(v);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getMaxCreationTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return maxCreationTime.get() != Long.MIN_VALUE ? maxCreationTime.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getMaxGetTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return maxGetTime.get() != Long.MIN_VALUE ? maxGetTime.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getMaxPoolTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return maxPoolTime.get() != Long.MIN_VALUE ? maxPoolTime.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getMaxUsageTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return maxUsageTime.get() != Long.MIN_VALUE ? maxUsageTime.get() : 0;
+ }
+
+ /**
+ * Get max wait count
+ * @return The value
+ */
+ public int getMaxWaitCount()
+ {
+ if (!isEnabled())
+ return 0;
+
+ return maxWaitCount.get() != Integer.MIN_VALUE ? maxWaitCount.get() : 0;
+ }
+
+ /**
+ * Set max wait count
+ * @param v The value
+ */
+ public void setMaxWaitCount(int v)
+ {
+ if (v > maxWaitCount.get())
+ maxWaitCount.set(v);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getMaxWaitTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return maxWaitTime.get() != Long.MIN_VALUE ? maxWaitTime.get() : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTimedOut()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return timedOut.get();
+ }
+
+ /**
+ * Delta the timed out value
+ */
+ public void deltaTimedOut()
+ {
+ if (enabled.get())
+ timedOut.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getTotalBlockingTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalBlockingTime.get();
+ }
+
+ /**
+ * Add delta to total blocking timeout
+ * @param delta The value
+ */
+ public void deltaTotalBlockingTime(long delta)
+ {
+ if (enabled.get() && delta > 0)
+ {
+ totalBlockingTime.addAndGet(delta);
+ totalBlockingTimeInvocations.incrementAndGet();
+
+ if (delta > maxWaitTime.get())
+ maxWaitTime.set(delta);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getTotalCreationTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalCreationTime.get();
+ }
+
+ /**
+ * Add delta to total creation time
+ * @param delta The value
+ */
+ public void deltaTotalCreationTime(long delta)
+ {
+ if (enabled.get() && delta > 0)
+ {
+ totalCreationTime.addAndGet(delta);
+
+ if (delta > maxCreationTime.get())
+ maxCreationTime.set(delta);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getTotalGetTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalGetTime.get();
+ }
+
+ /**
+ * Add delta to total get time
+ * @param delta The value
+ */
+ public void deltaTotalGetTime(long delta)
+ {
+ if (enabled.get() && delta > 0)
+ {
+ totalGetTime.addAndGet(delta);
+ totalGetTimeInvocations.incrementAndGet();
+
+ if (delta > maxGetTime.get())
+ maxGetTime.set(delta);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getTotalPoolTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalPoolTime.get();
+ }
+
+ /**
+ * Add delta to total pool time
+ * @param delta The value
+ */
+ public void deltaTotalPoolTime(long delta)
+ {
+ if (enabled.get() && delta > 0)
+ {
+ totalPoolTime.addAndGet(delta);
+ totalPoolTimeInvocations.incrementAndGet();
+
+ if (delta > maxPoolTime.get())
+ maxPoolTime.set(delta);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getTotalUsageTime()
+ {
+ if (!enabled.get())
+ return 0L;
+
+ return totalUsageTime.get();
+ }
+
+ /**
+ * Add delta to total usage time
+ * @param delta The value
+ */
+ public void deltaTotalUsageTime(long delta)
+ {
+ if (enabled.get() && delta > 0)
+ {
+ totalUsageTime.addAndGet(delta);
+ totalUsageTimeInvocations.incrementAndGet();
+
+ if (delta > maxUsageTime.get())
+ maxUsageTime.set(delta);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getWaitCount()
+ {
+ if (!enabled.get())
+ return 0;
+
+ return waitCount.get();
+ }
+
+ /**
+ * Add delta wait count
+ */
+ public void deltaWaitCount()
+ {
+ if (enabled.get())
+ waitCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getCommitCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return commitCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getCommitTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return commitTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getCommitAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (commitCount.get() > 0)
+ return commitTotalTime.get() / commitCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getCommitMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return commitMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaCommit(long time)
+ {
+ commitCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ commitTotalTime.addAndGet(time);
+
+ if (time > commitMaxTime.get())
+ commitMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getEndCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return endCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getEndTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return endTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getEndAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (endCount.get() > 0)
+ return endTotalTime.get() / endCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getEndMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return endMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaEnd(long time)
+ {
+ endCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ endTotalTime.addAndGet(time);
+
+ if (time > endMaxTime.get())
+ endMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getForgetCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return forgetCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getForgetTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return forgetTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getForgetAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (forgetCount.get() > 0)
+ return forgetTotalTime.get() / forgetCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getForgetMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return forgetMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaForget(long time)
+ {
+ forgetCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ forgetTotalTime.addAndGet(time);
+
+ if (time > forgetMaxTime.get())
+ forgetMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getPrepareCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return prepareCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getPrepareTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return prepareTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getPrepareAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (prepareCount.get() > 0)
+ return prepareTotalTime.get() / prepareCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getPrepareMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return prepareMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaPrepare(long time)
+ {
+ prepareCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ prepareTotalTime.addAndGet(time);
+
+ if (time > prepareMaxTime.get())
+ prepareMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRecoverCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return recoverCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRecoverTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return recoverTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRecoverAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (recoverCount.get() > 0)
+ return recoverTotalTime.get() / recoverCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRecoverMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return recoverMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaRecover(long time)
+ {
+ recoverCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ recoverTotalTime.addAndGet(time);
+
+ if (time > recoverMaxTime.get())
+ recoverMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRollbackCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return rollbackCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRollbackTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return rollbackTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRollbackAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (rollbackCount.get() > 0)
+ return rollbackTotalTime.get() / rollbackCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getRollbackMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return rollbackMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaRollback(long time)
+ {
+ rollbackCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ rollbackTotalTime.addAndGet(time);
+
+ if (time > rollbackMaxTime.get())
+ rollbackMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getStartCount()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return startCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getStartTotalTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return startTotalTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getStartAverageTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ if (startCount.get() > 0)
+ return startTotalTime.get() / startCount.get();
+
+ return 0L;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getStartMaxTime()
+ {
+ if (!isEnabled())
+ return 0L;
+
+ return startMaxTime.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deltaStart(long time)
+ {
+ startCount.incrementAndGet();
+
+ if (time > 0)
+ {
+ startTotalTime.addAndGet(time);
+
+ if (time > startMaxTime.get())
+ startMaxTime.set(time);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clear()
+ {
+ this.createdCount.set(0);
+ this.destroyedCount.set(0);
+ this.maxCreationTime.set(Long.MIN_VALUE);
+ this.maxGetTime.set(Long.MIN_VALUE);
+ this.maxPoolTime.set(Long.MIN_VALUE);
+ this.maxUsageTime.set(Long.MIN_VALUE);
+ this.maxUsedCount.set(Integer.MIN_VALUE);
+ this.maxWaitTime.set(Long.MIN_VALUE);
+ this.timedOut.set(0);
+ this.totalBlockingTime.set(0L);
+ this.totalBlockingTimeInvocations.set(0L);
+ this.totalCreationTime.set(0L);
+ this.totalGetTime.set(0L);
+ this.totalGetTimeInvocations.set(0L);
+ this.totalPoolTime.set(0L);
+ this.totalPoolTimeInvocations.set(0L);
+ this.totalUsageTime.set(0L);
+ this.totalUsageTimeInvocations.set(0L);
+ this.inUseCount.set(0);
+ this.blockingFailureCount.set(0);
+ this.waitCount.set(0);
+
+ this.commitCount = new AtomicLong(0L);
+ this.commitTotalTime = new AtomicLong(0L);
+ this.commitMaxTime = new AtomicLong(0L);
+ this.endCount = new AtomicLong(0L);
+ this.endTotalTime = new AtomicLong(0L);
+ this.endMaxTime = new AtomicLong(0L);
+ this.forgetCount = new AtomicLong(0L);
+ this.forgetTotalTime = new AtomicLong(0L);
+ this.forgetMaxTime = new AtomicLong(0L);
+ this.prepareCount = new AtomicLong(0L);
+ this.prepareTotalTime = new AtomicLong(0L);
+ this.prepareMaxTime = new AtomicLong(0L);
+ this.recoverCount = new AtomicLong(0L);
+ this.recoverTotalTime = new AtomicLong(0L);
+ this.recoverMaxTime = new AtomicLong(0L);
+ this.rollbackCount = new AtomicLong(0L);
+ this.rollbackTotalTime = new AtomicLong(0L);
+ this.rollbackMaxTime = new AtomicLong(0L);
+ this.startCount = new AtomicLong(0L);
+ this.startTotalTime = new AtomicLong(0L);
+ this.startMaxTime = new AtomicLong(0L);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ out.defaultWriteObject();
+ out.writeInt(maxPoolSize);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ init(in.readInt());
+ }
+
+ /**
+ * toString
+ * @return The value
+ */
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("PoolStatistics@").append(Integer.toHexString(System.identityHashCode(this)));
+
+ sb.append("[");
+
+ sb.append("Enabled=").append(isEnabled());
+ sb.append(",");
+ sb.append(ACTIVE_COUNT).append("=").append(getActiveCount());
+ sb.append(",");
+ sb.append(AVAILABLE_COUNT).append("=").append(getAvailableCount());
+ sb.append(",");
+ sb.append(AVERAGE_BLOCKING_TIME).append("=").append(getAverageBlockingTime());
+ sb.append(",");
+ sb.append(AVERAGE_CREATION_TIME).append("=").append(getAverageCreationTime());
+ sb.append(",");
+ sb.append(AVERAGE_GET_TIME).append("=").append(getAverageGetTime());
+ sb.append(",");
+ sb.append(AVERAGE_POOL_TIME).append("=").append(getAveragePoolTime());
+ sb.append(",");
+ sb.append(AVERAGE_USAGE_TIME).append("=").append(getAverageUsageTime());
+ sb.append(",");
+ sb.append(BLOCKING_FAILURE_COUNT).append("=").append(getBlockingFailureCount());
+ sb.append(",");
+ sb.append(CREATED_COUNT).append("=").append(getCreatedCount());
+ sb.append(",");
+ sb.append(DESTROYED_COUNT).append("=").append(getDestroyedCount());
+ sb.append(",");
+ sb.append(IDLE_COUNT).append("=").append(getIdleCount());
+ sb.append(",");
+ sb.append(IN_USE_COUNT).append("=").append(getInUseCount());
+ sb.append(",");
+ sb.append(MAX_CREATION_TIME).append("=").append(getMaxCreationTime());
+ sb.append(",");
+ sb.append(MAX_GET_TIME).append("=").append(getMaxGetTime());
+ sb.append(",");
+ sb.append(MAX_POOL_TIME).append("=").append(getMaxPoolTime());
+ sb.append(",");
+ sb.append(MAX_USAGE_TIME).append("=").append(getMaxUsageTime());
+ sb.append(",");
+ sb.append(MAX_USED_COUNT).append("=").append(getMaxUsedCount());
+ sb.append(",");
+ sb.append(MAX_WAIT_COUNT).append("=").append(getMaxWaitCount());
+ sb.append(",");
+ sb.append(MAX_WAIT_TIME).append("=").append(getMaxWaitTime());
+ sb.append(",");
+ sb.append(TIMED_OUT).append("=").append(getTimedOut());
+ sb.append(",");
+ sb.append(TOTAL_BLOCKING_TIME).append("=").append(getTotalBlockingTime());
+ sb.append(",");
+ sb.append(TOTAL_CREATION_TIME).append("=").append(getTotalCreationTime());
+ sb.append(",");
+ sb.append(TOTAL_GET_TIME).append("=").append(getTotalGetTime());
+ sb.append(",");
+ sb.append(TOTAL_POOL_TIME).append("=").append(getTotalPoolTime());
+ sb.append(",");
+ sb.append(TOTAL_USAGE_TIME).append("=").append(getTotalUsageTime());
+ sb.append(",");
+ sb.append(WAIT_COUNT).append("=").append(getWaitCount());
+
+ sb.append(",");
+ sb.append(XA_COMMIT_COUNT).append("=").append(getCommitCount());
+ sb.append(",");
+ sb.append(XA_COMMIT_AVERAGE_TIME).append("=").append(getCommitAverageTime());
+ sb.append(",");
+ sb.append(XA_COMMIT_TOTAL_TIME).append("=").append(getCommitTotalTime());
+ sb.append(",");
+ sb.append(XA_COMMIT_MAX_TIME).append("=").append(getCommitMaxTime());
+ sb.append(",");
+ sb.append(XA_END_COUNT).append("=").append(getEndCount());
+ sb.append(",");
+ sb.append(XA_END_AVERAGE_TIME).append("=").append(getEndAverageTime());
+ sb.append(",");
+ sb.append(XA_END_TOTAL_TIME).append("=").append(getEndTotalTime());
+ sb.append(",");
+ sb.append(XA_END_MAX_TIME).append("=").append(getEndMaxTime());
+ sb.append(",");
+ sb.append(XA_FORGET_COUNT).append("=").append(getForgetCount());
+ sb.append(",");
+ sb.append(XA_FORGET_AVERAGE_TIME).append("=").append(getForgetAverageTime());
+ sb.append(",");
+ sb.append(XA_FORGET_TOTAL_TIME).append("=").append(getForgetTotalTime());
+ sb.append(",");
+ sb.append(XA_FORGET_MAX_TIME).append("=").append(getForgetMaxTime());
+ sb.append(",");
+ sb.append(XA_PREPARE_COUNT).append("=").append(getPrepareCount());
+ sb.append(",");
+ sb.append(XA_PREPARE_AVERAGE_TIME).append("=").append(getPrepareAverageTime());
+ sb.append(",");
+ sb.append(XA_PREPARE_TOTAL_TIME).append("=").append(getPrepareTotalTime());
+ sb.append(",");
+ sb.append(XA_PREPARE_MAX_TIME).append("=").append(getPrepareMaxTime());
+ sb.append(",");
+ sb.append(XA_RECOVER_COUNT).append("=").append(getRecoverCount());
+ sb.append(",");
+ sb.append(XA_RECOVER_AVERAGE_TIME).append("=").append(getRecoverAverageTime());
+ sb.append(",");
+ sb.append(XA_RECOVER_TOTAL_TIME).append("=").append(getRecoverTotalTime());
+ sb.append(",");
+ sb.append(XA_RECOVER_MAX_TIME).append("=").append(getRecoverMaxTime());
+ sb.append(",");
+ sb.append(XA_ROLLBACK_COUNT).append("=").append(getRollbackCount());
+ sb.append(",");
+ sb.append(XA_ROLLBACK_AVERAGE_TIME).append("=").append(getRollbackAverageTime());
+ sb.append(",");
+ sb.append(XA_ROLLBACK_TOTAL_TIME).append("=").append(getRollbackTotalTime());
+ sb.append(",");
+ sb.append(XA_ROLLBACK_MAX_TIME).append("=").append(getRollbackMaxTime());
+ sb.append(",");
+ sb.append(XA_START_COUNT).append("=").append(getStartCount());
+ sb.append(",");
+ sb.append(XA_START_AVERAGE_TIME).append("=").append(getStartAverageTime());
+ sb.append(",");
+ sb.append(XA_START_TOTAL_TIME).append("=").append(getStartTotalTime());
+ sb.append(",");
+ sb.append(XA_START_MAX_TIME).append("=").append(getStartMaxTime());
+
+ sb.append("]");
+
+ return sb.toString();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,88 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Get a system property
+ * @param name The property name
+ * @return The property value
+ */
+ static String getSystemProperty(final String name)
+ {
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public String run()
+ {
+ return System.getProperty(name);
+ }
+ });
+ }
+
+ /**
+ * Get the classloader.
+ * @param c The class
+ * @return The classloader
+ */
+ static ClassLoader getClassLoader(final Class> c)
+ {
+ if (System.getSecurityManager() == null)
+ return c.getClassLoader();
+
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public ClassLoader run()
+ {
+ return c.getClassLoader();
+ }
+ });
+ }
+
+ /**
+ * Get stack trace
+ * @param t The thread
+ * @return The trace
+ */
+ static StackTraceElement[] getStackTrace(final Thread t)
+ {
+ if (System.getSecurityManager() == null)
+ return t.getStackTrace();
+
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public StackTraceElement[] run()
+ {
+ return t.getStackTrace();
+ }
+ });
+ }
+
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Capacity.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Capacity.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Capacity.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,42 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+/**
+ * The capacity policy
+ *
+ * @author Jesper Pedersen
+ */
+public interface Capacity
+{
+ /**
+ * Get the incrementer policy
+ * @return The policy; can be null
for container default policy
+ */
+ public CapacityIncrementer getIncrementer();
+
+ /**
+ * Get the decrementer policy
+ * @return The policy; can be null
for container default policy
+ */
+ public CapacityDecrementer getDecrementer();
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/CapacityDecrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/CapacityDecrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/CapacityDecrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,43 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+
+/**
+ * The capacity decrementer policy
+ *
+ * @author Jesper Pedersen
+ */
+public interface CapacityDecrementer
+{
+ /**
+ * Should the connection listener be destroyed
+ * @param cl The connection listener
+ * @param timeout The timeout watermark
+ * @param currentSize The current pool size
+ * @param minPoolSize The minimum pool size
+ * @param destroyed The number of connection listeners destroyed during this call cycle
+ * @return True
if the connection listener should be destroyed; otherwise false
+ */
+ public boolean shouldDestroy(ConnectionListener cl, long timeout, int currentSize, int minPoolSize, int destroyed);
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/CapacityIncrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/CapacityIncrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/CapacityIncrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,39 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+/**
+ * The capacity incrementer policy
+ *
+ * @author Jesper Pedersen
+ */
+public interface CapacityIncrementer
+{
+ /**
+ * Should the connection listener be created
+ * @param currentSize The current pool size
+ * @param maxSize The maximum pool size
+ * @param created The number of connection listeners created during this call cycle
+ * @return True
if a connection listener should be created; otherwise false
+ */
+ public boolean shouldCreate(int currentSize, int maxSize, int created);
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Pool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Pool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Pool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,205 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.PoolStatisticsImpl;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+import javax.transaction.Transaction;
+
+/**
+ * A pool.
+ *
+ * @author Gurkan Erdogdu
+ * @author David Jencks
+ * @author Jesper Pedersen
+ */
+public interface Pool extends org.jboss.jca.core.api.connectionmanager.pool.Pool
+{
+ /**
+ * Sets pool name.
+ * @param poolName pool name
+ */
+ public void setName(String poolName);
+
+ /**
+ * Is sharable
+ * @return The value
+ */
+ public boolean isSharable();
+
+ /**
+ * Retrieve the managed connection factory for this pool.
+ *
+ * @return the managed connection factory
+ */
+ public ManagedConnectionFactory getManagedConnectionFactory();
+
+ /**
+ * Set the connection manager
+ *
+ * @param cm the connection manager
+ */
+ public void setConnectionManager(ConnectionManager cm);
+
+ /**
+ * Get the lock
+ * @return The value
+ */
+ public Semaphore getLock();
+
+ /**
+ * Get the capacity policy
+ * @return The value
+ */
+ public Capacity getCapacity();
+
+ /**
+ * Is the pool a FIFO or FILO pool
+ * @return True if FIFO
+ */
+ public boolean isFIFO();
+
+ /**
+ * Set the capacity policy
+ * @param c The value
+ */
+ public void setCapacity(Capacity c);
+
+ /**
+ * Get the interleaving flag
+ * @return The value
+ */
+ public boolean isInterleaving();
+
+ /**
+ * Set the interleaving flag
+ * @param v The value
+ */
+ public void setInterleaving(boolean v);
+
+ /**
+ * Is the pool idle
+ * @return True if idle, otherwise false
+ */
+ public boolean isIdle();
+
+ /**
+ * Is the pool full
+ * @return True if full, otherwise false
+ */
+ public boolean isFull();
+
+ /**
+ * Get internal statistics
+ * @return The value
+ */
+ public PoolStatisticsImpl getInternalStatistics();
+
+ /**
+ * Get a connection
+ *
+ * @param trackByTransaction for transaction stickiness
+ * @param subject the subject for connection
+ * @param cri the connection request information
+ * @return a connection event listener wrapping the connection
+ * @throws ResourceException for any error
+ */
+ public ConnectionListener getConnection(Transaction trackByTransaction, Subject subject, ConnectionRequestInfo cri)
+ throws ResourceException;
+
+ /**
+ * Find a connection listener
+ * @param mc The managed connection
+ * @return The connection listener
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc);
+
+ /**
+ * Find a connection listener
+ * @param mc The managed connection
+ * @param connection The connection
+ * @return The connection listener
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc, Object connection);
+
+ /**
+ * Return a connection
+ *
+ * @param cl the connection event listener wrapping the connection
+ * @param kill whether to destroy the managed connection
+ * @throws ResourceException for any error
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill)
+ throws ResourceException;
+
+ /**
+ * Has an existing connection
+ *
+ * @param subject the subject for connection
+ * @param cri the connection request information
+ * @return true
if there is an existing connection enlisted, otherwise false
+ */
+ public boolean hasConnection(Subject subject, ConnectionRequestInfo cri);
+
+ /**
+ * Is shutdown
+ * @return The value
+ */
+ public boolean isShutdown();
+
+ /**
+ * Shutdown the pool
+ */
+ public void shutdown();
+
+ /**
+ * Prepare Shutdown
+ */
+ public void prepareShutdown();
+
+ /**
+ * Cancel shutdown
+ * @return True if the shutdown was canceled; false otherwise
+ */
+ public boolean cancelShutdown();
+
+ /**
+ * Remove the matching managed connection pool if the pool is empty
+ * @param pool The pool
+ */
+ public void emptyManagedConnectionPool(ManagedConnectionPool pool);
+
+ /**
+ * Get the logger
+ * @return The value
+ */
+ public CoreLogger getLogger();
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PoolFactory.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PoolFactory.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PoolFactory.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,93 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.pool.strategy.OnePool;
+import org.jboss.jca.core.connectionmanager.pool.strategy.PoolByCri;
+import org.jboss.jca.core.connectionmanager.pool.strategy.PoolBySubject;
+import org.jboss.jca.core.connectionmanager.pool.strategy.PoolBySubjectAndCri;
+import org.jboss.jca.core.connectionmanager.pool.strategy.ReauthPool;
+
+import javax.resource.spi.ManagedConnectionFactory;
+
+/**
+ * The pool factory.
+ * @author Jesper Pedersen
+ */
+public class PoolFactory
+{
+ /**
+ * Constructor
+ */
+ public PoolFactory()
+ {
+ }
+
+ /**
+ * Create a pool
+ * @param strategy The pool strategy
+ * @param mcf The managed connection factory
+ * @param pc The pool configuration
+ * @param noTxSeparatePools no-tx separate pool
+ * @param sharable Are the connections sharable
+ * @param mcp ManagedConnectionPool
+ * @return The pool instance
+ */
+ public Pool create(final PoolStrategy strategy,
+ final ManagedConnectionFactory mcf,
+ final PoolConfiguration pc,
+ final boolean noTxSeparatePools,
+ final boolean sharable,
+ final String mcp)
+ {
+ if (strategy == null)
+ throw new IllegalArgumentException("Strategy is null");
+
+ if (mcf == null)
+ throw new IllegalArgumentException("MCF is null");
+
+ if (pc == null)
+ throw new IllegalArgumentException("PoolConfiguration is null");
+
+ switch (strategy)
+ {
+ case POOL_BY_CRI:
+ return new PoolByCri(mcf, pc, noTxSeparatePools, sharable, mcp);
+
+ case POOL_BY_SUBJECT:
+ return new PoolBySubject(mcf, pc, noTxSeparatePools, sharable, mcp);
+
+ case POOL_BY_SUBJECT_AND_CRI:
+ return new PoolBySubjectAndCri(mcf, pc, noTxSeparatePools, sharable, mcp);
+
+ case ONE_POOL:
+ return new OnePool(mcf, pc, noTxSeparatePools, sharable, mcp);
+
+ case REAUTH:
+ return new ReauthPool(mcf, pc, noTxSeparatePools, sharable, mcp);
+ }
+
+ throw new IllegalArgumentException("Unknown strategy " + strategy);
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PoolStrategy.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PoolStrategy.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PoolStrategy.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,45 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+/**
+ * Defines a pool strategy.
+ * @author Jesper Pedersen
+ */
+public enum PoolStrategy
+{
+ /** POOL_BY_CRI */
+ POOL_BY_CRI,
+
+ /** POOL_BY_SUBJECT */
+ POOL_BY_SUBJECT,
+
+ /** POOL_BY_SUBJECT_AND_CRI */
+ POOL_BY_SUBJECT_AND_CRI,
+
+ /** ONE_POOL */
+ ONE_POOL,
+
+ /** REAUTH */
+ REAUTH
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PrefillPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PrefillPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/PrefillPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,44 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.security.auth.Subject;
+
+/**
+ * Prefill pool allows for prefilling connection pools.
+ *
+ * @author Weston Price
+ * @author Jesper Pedersen
+ */
+public interface PrefillPool extends Pool
+{
+ /**
+ * Prefill the connection pool
+ *
+ * @param subject the subject the subject
+ * @param cri the connection request info
+ * @param noTxnSeperatePool whether or not we are seperating non transaction and transaction pools
+ *
+ */
+ public void prefill(Subject subject, ConnectionRequestInfo cri, boolean noTxnSeperatePool);
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Semaphore.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Semaphore.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/Semaphore.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,100 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2010, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.api;
+
+import org.jboss.jca.core.connectionmanager.pool.PoolStatisticsImpl;
+
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A semaphore implementation that supports statistics
+ *
+ * @author Jesper Pedersen
+ */
+public class Semaphore extends java.util.concurrent.Semaphore
+{
+ /** Serial version uid */
+ private static final long serialVersionUID = 4L;
+
+ /** Max size */
+ private int maxSize;
+
+ /** Statistics */
+ private PoolStatisticsImpl statistics;
+
+ /**
+ * Constructor
+ * @param maxSize The maxumum size
+ * @param fairness The fairness
+ * @param statistics The statistics module
+ */
+ public Semaphore(int maxSize, boolean fairness, PoolStatisticsImpl statistics)
+ {
+ super(maxSize, fairness);
+ this.maxSize = maxSize;
+ this.statistics = statistics;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
+ {
+ if (statistics.isEnabled())
+ statistics.setMaxWaitCount(getQueueLength());
+
+ boolean result = super.tryAcquire(timeout, unit);
+
+ if (result && statistics.isEnabled())
+ {
+ statistics.setInUsedCount(maxSize - availablePermits());
+ }
+
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void release()
+ {
+ super.release();
+
+ if (statistics.isEnabled())
+ {
+ statistics.setInUsedCount(maxSize - availablePermits());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection getQueuedThreads()
+ {
+ return super.getQueuedThreads();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/api/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the connection pool api.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/CapacityFactory.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/CapacityFactory.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/CapacityFactory.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,243 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityIncrementer;
+import org.jboss.jca.core.util.Injection;
+
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+
+/**
+ * The capacity factory
+ *
+ * @author Jesper Pedersen
+ */
+public class CapacityFactory
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, CapacityFactory.class.getName());
+
+ /**
+ * Constructor
+ */
+ private CapacityFactory()
+ {
+ }
+
+ /**
+ * Create a capacity instance based on the metadata
+ * @param metadata The metadata
+ * @param isCRI Is the pool CRI based
+ * @return The instance
+ */
+ public static org.jboss.jca.core.connectionmanager.pool.api.Capacity
+ create(org.jboss.jca.common.api.metadata.common.Capacity metadata,
+ boolean isCRI)
+ {
+ if (metadata == null)
+ return DefaultCapacity.INSTANCE;
+
+ CapacityIncrementer incrementer = null;
+ CapacityDecrementer decrementer = null;
+
+ // Incrementer
+ if (metadata.getIncrementer() != null && metadata.getIncrementer().getClassName() != null)
+ {
+ incrementer = loadIncrementer(metadata.getIncrementer().getClassName());
+
+ if (incrementer != null)
+ {
+ if (metadata.getIncrementer().getConfigPropertiesMap().size() > 0)
+ {
+ Injection injector = new Injection();
+
+ Map properties = metadata.getIncrementer().getConfigPropertiesMap();
+ for (Map.Entry property : properties.entrySet())
+ {
+ try
+ {
+ injector.inject(incrementer, property.getKey(), property.getValue());
+ }
+ catch (Throwable t)
+ {
+ log.invalidCapacityOption(property.getKey(),
+ property.getValue(), incrementer.getClass().getName());
+ }
+ }
+ }
+ }
+ else
+ {
+ log.invalidCapacityIncrementer(metadata.getIncrementer().getClassName());
+ }
+ }
+
+ if (incrementer == null)
+ incrementer = DefaultCapacity.DEFAULT_INCREMENTER;
+
+ // Decrementer
+ if (metadata.getDecrementer() != null && metadata.getDecrementer().getClassName() != null)
+ {
+ if (!isCRI)
+ {
+ decrementer = loadDecrementer(metadata.getDecrementer().getClassName());
+
+ if (decrementer != null)
+ {
+ if (metadata.getDecrementer().getConfigPropertiesMap().size() > 0)
+ {
+ Injection injector = new Injection();
+
+ Map properties = metadata.getDecrementer().getConfigPropertiesMap();
+ for (Map.Entry property : properties.entrySet())
+ {
+ try
+ {
+ injector.inject(decrementer, property.getKey(), property.getValue());
+ }
+ catch (Throwable t)
+ {
+ log.invalidCapacityOption(property.getKey(),
+ property.getValue(), decrementer.getClass().getName());
+ }
+ }
+ }
+ }
+ else
+ {
+ log.invalidCapacityDecrementer(metadata.getDecrementer().getClassName());
+ }
+ }
+ else
+ {
+ // Explicit allow TimedOutDecrementer, MinPoolSizeDecrementer and SizeDecrementer for CRI based pools
+ if (TimedOutDecrementer.class.getName().equals(metadata.getDecrementer().getClassName()) ||
+ TimedOutFIFODecrementer.class.getName().equals(metadata.getDecrementer().getClassName()) ||
+ MinPoolSizeDecrementer.class.getName().equals(metadata.getDecrementer().getClassName()) ||
+ SizeDecrementer.class.getName().equals(metadata.getDecrementer().getClassName()))
+ {
+ decrementer = loadDecrementer(metadata.getDecrementer().getClassName());
+
+ if (metadata.getDecrementer().getConfigPropertiesMap().size() > 0)
+ {
+ Injection injector = new Injection();
+
+ Map properties = metadata.getDecrementer().getConfigPropertiesMap();
+ for (Map.Entry property : properties.entrySet())
+ {
+ try
+ {
+ injector.inject(decrementer, property.getKey(), property.getValue());
+ }
+ catch (Throwable t)
+ {
+ log.invalidCapacityOption(property.getKey(),
+ property.getValue(), decrementer.getClass().getName());
+ }
+ }
+ }
+ }
+ else
+ {
+ log.invalidCapacityDecrementer(metadata.getDecrementer().getClassName());
+ }
+ }
+ }
+
+ if (decrementer == null)
+ decrementer = DefaultCapacity.DEFAULT_DECREMENTER;
+
+ return new ExplicitCapacity(incrementer, decrementer);
+ }
+
+ /**
+ * Load the incrementer
+ * @param clz The incrementer class name
+ * @return The incrementer
+ */
+ private static CapacityIncrementer loadIncrementer(String clz)
+ {
+ Object result = loadClass(clz);
+
+ if (result != null && result instanceof CapacityIncrementer)
+ {
+ return (CapacityIncrementer)result;
+ }
+
+ log.debugf("%s wasn't a CapacityIncrementer", clz);
+
+ return null;
+ }
+
+ /**
+ * Load the decrementer
+ * @param clz The decrementer class name
+ * @return The decrementer
+ */
+ private static CapacityDecrementer loadDecrementer(String clz)
+ {
+ Object result = loadClass(clz);
+
+ if (result != null && result instanceof CapacityDecrementer)
+ {
+ return (CapacityDecrementer)result;
+ }
+
+ log.debugf("%s wasn't a CapacityDecrementer", clz);
+
+ return null;
+ }
+
+ /**
+ * Load the class
+ * @param clz The class name
+ * @return The object
+ */
+ private static Object loadClass(String clz)
+ {
+ try
+ {
+ Class> c = Class.forName(clz, true, SecurityActions.getClassLoader(CapacityFactory.class));
+ return c.newInstance();
+ }
+ catch (Throwable t)
+ {
+ log.tracef("Throwable while loading %s using own classloader: %s", clz, t.getMessage());
+ }
+
+ try
+ {
+ Class> c = Class.forName(clz, true, SecurityActions.getThreadContextClassLoader());
+ return c.newInstance();
+ }
+ catch (Throwable t)
+ {
+ log.tracef("Throwable while loading %s using TCCL: %s", clz, t.getMessage());
+ }
+
+ return null;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/DefaultCapacity.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/DefaultCapacity.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/DefaultCapacity.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,66 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.pool.api.Capacity;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityIncrementer;
+
+/**
+ * The default capacity policy
+ *
+ * @author Jesper Pedersen
+ */
+public class DefaultCapacity implements Capacity
+{
+ /** The instance */
+ public static final Capacity INSTANCE = new DefaultCapacity();
+
+ /** The default incrementer */
+ public static final CapacityIncrementer DEFAULT_INCREMENTER = null;
+
+ /** The default decrementer */
+ public static final CapacityDecrementer DEFAULT_DECREMENTER = new TimedOutDecrementer();
+
+ /**
+ * Constructor
+ */
+ private DefaultCapacity()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CapacityIncrementer getIncrementer()
+ {
+ return DEFAULT_INCREMENTER;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CapacityDecrementer getDecrementer()
+ {
+ return DEFAULT_DECREMENTER;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/ExplicitCapacity.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/ExplicitCapacity.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/ExplicitCapacity.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,67 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.pool.api.Capacity;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityIncrementer;
+
+/**
+ * Explicit capacity policy
+ *
+ * @author Jesper Pedersen
+ */
+public class ExplicitCapacity implements Capacity
+{
+ /** The incrementer */
+ private CapacityIncrementer incrementer;
+
+ /** The decrementer */
+ private CapacityDecrementer decrementer;
+
+ /**
+ * Constructor
+ * @param incrementer The incrementer
+ * @param decrementer The decrementer
+ */
+ public ExplicitCapacity(CapacityIncrementer incrementer, CapacityDecrementer decrementer)
+ {
+ this.incrementer = incrementer;
+ this.decrementer = decrementer;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CapacityIncrementer getIncrementer()
+ {
+ return incrementer;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CapacityDecrementer getDecrementer()
+ {
+ return decrementer;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/MaxPoolSizeIncrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/MaxPoolSizeIncrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/MaxPoolSizeIncrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,55 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityIncrementer;
+
+/**
+ * Keep incrementing until max-pool-size is reached
+ *
+ * @author Jesper Pedersen
+ */
+public class MaxPoolSizeIncrementer implements CapacityIncrementer
+{
+ /**
+ * Constructor
+ */
+ public MaxPoolSizeIncrementer()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldCreate(int currentSize, int maxSize, int created)
+ {
+ return currentSize < maxSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/MinPoolSizeDecrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/MinPoolSizeDecrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/MinPoolSizeDecrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,56 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+
+/**
+ * Keep destroying connection listeners until min-pool-size is reached
+ *
+ * @author Jesper Pedersen
+ */
+public class MinPoolSizeDecrementer implements CapacityDecrementer
+{
+ /**
+ * Constructor
+ */
+ public MinPoolSizeDecrementer()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldDestroy(ConnectionListener cl, long timeout, int currentSize, int minPoolSize, int destroyed)
+ {
+ return currentSize > minPoolSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,74 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Get the classloader.
+ * @param c The class
+ * @return The classloader
+ */
+ static ClassLoader getClassLoader(final Class> c)
+ {
+ if (System.getSecurityManager() == null)
+ return c.getClassLoader();
+
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public ClassLoader run()
+ {
+ return c.getClassLoader();
+ }
+ });
+ }
+
+ /**
+ * Get the context classloader.
+ * @return The classloader
+ */
+ public static ClassLoader getThreadContextClassLoader()
+ {
+ if (System.getSecurityManager() == null)
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ else
+ {
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public ClassLoader run()
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SizeDecrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SizeDecrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SizeDecrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,71 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+
+/**
+ * Decrement until the defined number of connection has been destroyed.
+ *
+ * Default value is 1
+ * @author Jesper Pedersen
+ */
+public class SizeDecrementer implements CapacityDecrementer
+{
+ /** Size */
+ private int size;
+
+ /**
+ * Constructor
+ */
+ public SizeDecrementer()
+ {
+ this.size = 1;
+ }
+
+ /**
+ * Set the size
+ * @param v The value
+ */
+ public void setSize(int v)
+ {
+ if (v > 0)
+ size = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldDestroy(ConnectionListener cl, long timeout, int currentSize, int minPoolSize, int destroyed)
+ {
+ return size > destroyed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName() + "(" + size + ")";
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SizeIncrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SizeIncrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/SizeIncrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,70 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityIncrementer;
+
+/**
+ * Increment until the defined number of connection has been created.
+ *
+ * Default value is 1
+ * @author Jesper Pedersen
+ */
+public class SizeIncrementer implements CapacityIncrementer
+{
+ /** Size */
+ private int size;
+
+ /**
+ * Constructor
+ */
+ public SizeIncrementer()
+ {
+ this.size = 1;
+ }
+
+ /**
+ * Set the size
+ * @param v The value
+ */
+ public void setSize(int v)
+ {
+ if (v > 0)
+ size = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldCreate(int currentSize, int maxSize, int created)
+ {
+ return size > created;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName() + "(" + size + ")";
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/TimedOutDecrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/TimedOutDecrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/TimedOutDecrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,56 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+
+/**
+ * Decrement all timed out connection listeners
+ *
+ * @author Jesper Pedersen
+ */
+public class TimedOutDecrementer implements CapacityDecrementer
+{
+ /**
+ * Constructor
+ */
+ public TimedOutDecrementer()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldDestroy(ConnectionListener cl, long timeout, int currentSize, int minPoolSize, int destroyed)
+ {
+ return cl.isTimedOut(timeout);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/TimedOutFIFODecrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/TimedOutFIFODecrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/TimedOutFIFODecrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,37 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2015, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+/**
+ * Decrement all timed out connection listeners (FIFO marker)
+ *
+ * @author Jesper Pedersen
+ */
+public class TimedOutFIFODecrementer extends TimedOutDecrementer
+{
+ /**
+ * Constructor
+ */
+ public TimedOutFIFODecrementer()
+ {
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/WatermarkDecrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/WatermarkDecrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/WatermarkDecrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,73 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+
+/**
+ * Decrement until the defined pool size is reached.
+ *
+ * Default value is min-pool-size
+ * @author Jesper Pedersen
+ */
+public class WatermarkDecrementer implements CapacityDecrementer
+{
+ /** Watermark */
+ private int watermark;
+
+ /**
+ * Constructor
+ */
+ public WatermarkDecrementer()
+ {
+ this.watermark = -1;
+ }
+
+ /**
+ * Set the watermark
+ * @param v The value
+ */
+ public void setWatermark(int v)
+ {
+ watermark = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldDestroy(ConnectionListener cl, long timeout, int currentSize, int minPoolSize, int destroyed)
+ {
+ if (watermark < 0)
+ return currentSize > minPoolSize;
+
+ return watermark < currentSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName() + "(" + watermark + ")";
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/WatermarkIncrementer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/WatermarkIncrementer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/WatermarkIncrementer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,72 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.capacity;
+
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityIncrementer;
+
+/**
+ * Increment until the defined pool size is reached.
+ *
+ * Default value is max-pool-size
+ * @author Jesper Pedersen
+ */
+public class WatermarkIncrementer implements CapacityIncrementer
+{
+ /** Watermark */
+ private int watermark;
+
+ /**
+ * Constructor
+ */
+ public WatermarkIncrementer()
+ {
+ this.watermark = -1;
+ }
+
+ /**
+ * Set the watermark
+ * @param v The value
+ */
+ public void setWatermark(int v)
+ {
+ watermark = v;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldCreate(int currentSize, int maxSize, int created)
+ {
+ if (watermark < 0)
+ return currentSize < maxSize;
+
+ return watermark > currentSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName() + "(" + watermark + ")";
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/capacity/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the capacity policy implementations
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/IdleConnectionRemovalSupport.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/IdleConnectionRemovalSupport.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/IdleConnectionRemovalSupport.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,39 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.idle;
+
+/**
+ * A IdleConnectionRemovalSupport specified contract for a pool that is able
+ * to remove an idle connection.
+ *
+ * @author gurkanerdogdu
+ * @author Weston Price
+ * @version $Revision$
+ */
+public interface IdleConnectionRemovalSupport
+{
+ /**
+ * Pool removes idle connections.
+ */
+ public void removeIdleConnections();
+
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/IdleRemover.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/IdleRemover.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/IdleRemover.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,306 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.idle;
+
+import org.jboss.jca.core.CoreLogger;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Idle remover
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class IdleRemover
+{
+ /** Logger instance */
+ private static CoreLogger logger = Logger.getMessageLogger(CoreLogger.class, IdleRemover.class.getName());
+
+ /** Thread name */
+ private static final String THREAD_NAME = "IdleRemover";
+
+ /** Singleton instance */
+ private static IdleRemover instance = new IdleRemover();
+
+ /** Registered pool instances */
+ private CopyOnWriteArrayList registeredPools =
+ new CopyOnWriteArrayList();
+
+ /** Executor service */
+ private ExecutorService executorService;
+
+ /** Is the executor external */
+ private boolean isExternal;
+
+ /** The interval */
+ private long interval;
+
+ /** The next scan */
+ private long next;
+
+ /** Shutdown */
+ private AtomicBoolean shutdown;
+
+ /** Lock */
+ private Lock lock;
+
+ /** Condition */
+ private Condition condition;
+
+ /**
+ * Private constructor.
+ */
+ private IdleRemover()
+ {
+ this.executorService = null;
+ this.isExternal = false;
+ this.interval = Long.MAX_VALUE;
+ this.next = Long.MAX_VALUE;
+ this.shutdown = new AtomicBoolean(false);
+ this.lock = new ReentrantLock(true);
+ this.condition = lock.newCondition();
+ }
+
+ /**
+ * Get the instance
+ * @return The value
+ */
+ public static IdleRemover getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Set the executor service
+ * @param v The value
+ */
+ public void setExecutorService(ExecutorService v)
+ {
+ if (v != null)
+ {
+ this.executorService = v;
+ this.isExternal = true;
+ }
+ else
+ {
+ this.executorService = null;
+ this.isExternal = false;
+ }
+ }
+
+ /**
+ * Start
+ * @exception Throwable Thrown if an error occurs
+ */
+ public void start() throws Throwable
+ {
+ if (!isExternal)
+ {
+ this.executorService = Executors.newSingleThreadExecutor(new IdleRemoverThreadFactory());
+ }
+
+ this.shutdown.set(false);
+ this.interval = Long.MAX_VALUE;
+ this.next = Long.MAX_VALUE;
+
+ this.executorService.execute(new IdleRemoverRunner());
+ }
+
+ /**
+ * Stop
+ * @exception Throwable Thrown if an error occurs
+ */
+ public void stop() throws Throwable
+ {
+ instance.shutdown.set(true);
+
+ if (!isExternal)
+ {
+ instance.executorService.shutdownNow();
+ instance.executorService = null;
+ }
+
+ instance.registeredPools.clear();
+ }
+
+ /**
+ * Register pool for connection validation.
+ * @param mcp managed connection pool
+ * @param interval validation interval
+ */
+ public void registerPool(IdleConnectionRemovalSupport mcp, long interval)
+ {
+ logger.debugf("Register pool: %s (interval=%s)", mcp, interval);
+
+ instance.internalRegisterPool(mcp, interval);
+ }
+
+ /**
+ * Unregister pool instance for connection validation.
+ * @param mcp pool instance
+ */
+ public void unregisterPool(IdleConnectionRemovalSupport mcp)
+ {
+ logger.debugf("Unregister pool: %s", mcp);
+
+ instance.internalUnregisterPool(mcp);
+ }
+
+ private void internalRegisterPool(IdleConnectionRemovalSupport mcp, long interval)
+ {
+ try
+ {
+ this.lock.lock();
+
+ this.registeredPools.addIfAbsent(mcp);
+
+ if (interval > 1 && interval / 2 < this.interval)
+ {
+ this.interval = interval / 2;
+ long maybeNext = System.currentTimeMillis() + this.interval;
+ if (next > maybeNext && maybeNext > 0)
+ {
+ next = maybeNext;
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("About to notify thread: old next: " + next + ", new next: " + maybeNext);
+ }
+
+ this.condition.signal();
+ }
+ }
+ }
+ finally
+ {
+ this.lock.unlock();
+ }
+ }
+
+ private void internalUnregisterPool(IdleConnectionRemovalSupport mcp)
+ {
+ this.registeredPools.remove(mcp);
+
+ if (this.registeredPools.size() == 0)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Setting interval to Long.MAX_VALUE");
+ }
+
+ interval = Long.MAX_VALUE;
+ }
+ }
+
+ /**
+ * Thread factory.
+ */
+ private static class IdleRemoverThreadFactory implements ThreadFactory
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public Thread newThread(Runnable r)
+ {
+ Thread thread = new Thread(r, IdleRemover.THREAD_NAME);
+ thread.setDaemon(true);
+
+ return thread;
+ }
+ }
+
+ /**
+ * IdleRemoverRunner
+ */
+ private class IdleRemoverRunner implements Runnable
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public void run()
+ {
+ final ClassLoader oldTccl = SecurityActions.getThreadContextClassLoader();
+ SecurityActions.setThreadContextClassLoader(IdleRemover.class.getClassLoader());
+
+ try
+ {
+ lock.lock();
+
+ while (!shutdown.get())
+ {
+ boolean result = instance.condition.await(instance.interval, TimeUnit.MILLISECONDS);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("Result of await: " + result);
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Notifying pools, interval: " + interval);
+ }
+
+ for (IdleConnectionRemovalSupport mcp : registeredPools)
+ {
+ mcp.removeIdleConnections();
+ }
+
+ next = System.currentTimeMillis() + interval;
+
+ if (next < 0)
+ {
+ next = Long.MAX_VALUE;
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ if (!shutdown.get())
+ logger.returningConnectionValidatorInterrupted();
+ }
+ catch (RuntimeException e)
+ {
+ logger.connectionValidatorIgnoredUnexpectedRuntimeException(e);
+ }
+ catch (Exception e)
+ {
+ logger.connectionValidatorIgnoredUnexpectedError(e);
+ }
+ finally
+ {
+ lock.unlock();
+ SecurityActions.setThreadContextClassLoader(oldTccl);
+ }
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,83 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.idle;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Get the context classloader.
+ * @return The classloader
+ */
+ public static ClassLoader getThreadContextClassLoader()
+ {
+ if (System.getSecurityManager() == null)
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ else
+ {
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public ClassLoader run()
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+ }
+
+ /**
+ * Set the context classloader.
+ * @param cl classloader
+ */
+ public static void setThreadContextClassLoader(final ClassLoader cl)
+ {
+ if (cl == null)
+ return;
+
+ if (System.getSecurityManager() == null)
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ else
+ {
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+
+ return null;
+ }
+ });
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/idle/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the infrastructure for removing idle connections.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/CapacityFiller.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/CapacityFiller.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/CapacityFiller.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,132 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import java.util.LinkedList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Capacity filler
+ *
+ * @author Jesper Pedersen
+ */
+class CapacityFiller implements Runnable
+{
+ /** Singleton instance */
+ private static final CapacityFiller INSTANCE = new CapacityFiller();
+
+ /** Managed connection pool list */
+ private final LinkedList crs = new LinkedList();
+
+ /** Filler thread */
+ private final Thread fillerThread;
+
+ /** Thread name */
+ private static final String THREAD_FILLER_NAME = "JCA CapacityFiller";
+
+ /**Thread is configured or not*/
+ private AtomicBoolean threadStarted = new AtomicBoolean(false);
+
+ /**
+ * Schedule capacity request
+ * @param cr The value
+ */
+ static void schedule(CapacityRequest cr)
+ {
+ INSTANCE.internalSchedule(cr);
+ }
+
+ /**
+ * Constructor
+ */
+ CapacityFiller()
+ {
+ fillerThread = new Thread(this, THREAD_FILLER_NAME);
+ fillerThread.setDaemon(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run()
+ {
+ final ClassLoader myClassLoader = SecurityActions.getClassLoader(getClass());
+ SecurityActions.setThreadContextClassLoader(myClassLoader);
+
+ while (true)
+ {
+ boolean empty = false;
+
+ while (!empty)
+ {
+ CapacityRequest cr = null;
+
+ synchronized (crs)
+ {
+ empty = crs.isEmpty();
+ if (!empty)
+ cr = crs.removeFirst();
+ }
+
+ if (!empty)
+ {
+ cr.getManagedConnectionPool().increaseCapacity(cr.getSubject(), cr.getConnectionRequestInfo());
+ }
+ }
+
+ try
+ {
+ synchronized (crs)
+ {
+ while (crs.isEmpty())
+ {
+ crs.wait();
+ }
+ }
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+ }
+
+ /**
+ * Internal: Schedule
+ * @param cr The value
+ */
+ private void internalSchedule(CapacityRequest cr)
+ {
+ if (this.threadStarted.compareAndSet(false, true))
+ {
+ this.fillerThread.start();
+ }
+
+ // Multiple instances of the same ManagedConnectionPool is allowed
+ synchronized (crs)
+ {
+ crs.addLast(cr);
+ crs.notifyAll();
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/CapacityRequest.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/CapacityRequest.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/CapacityRequest.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,138 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.security.auth.Subject;
+
+/**
+ * Represents a capacity request for a managed connection pool
+ *
+ * @author Jesper Pedersen
+ */
+class CapacityRequest
+{
+ /** Managed connection pool */
+ private ManagedConnectionPool mcp;
+
+ /** Subject */
+ private Subject subject;
+
+ /** ConnectionRequestInfo */
+ private ConnectionRequestInfo cri;
+
+ /**
+ * Constructor
+ * @param mcp The managed connection pool
+ * @param subject The subject
+ * @param cri The connection request info object
+ */
+ CapacityRequest(ManagedConnectionPool mcp, Subject subject, ConnectionRequestInfo cri)
+ {
+ this.mcp = mcp;
+ this.subject = subject;
+ this.cri = cri;
+ }
+
+ /**
+ * Get the managed connection pool
+ * @return The value
+ */
+ ManagedConnectionPool getManagedConnectionPool()
+ {
+ return mcp;
+ }
+
+ /**
+ * Get the subject
+ * @return The value
+ */
+ Subject getSubject()
+ {
+ return subject;
+ }
+
+ /**
+ * Get the connection request info object
+ * @return The value
+ */
+ ConnectionRequestInfo getConnectionRequestInfo()
+ {
+ return cri;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ int result = 31;
+ result += 7 * mcp.hashCode();
+ result += subject != null ? 7 * SecurityActions.hashCode(subject) : 7;
+ result += cri != null ? 7 * cri.hashCode() : 7;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+
+ if (obj == null)
+ return false;
+
+ if (!(obj instanceof CapacityRequest))
+ return false;
+
+ CapacityRequest other = (CapacityRequest) obj;
+
+ if (mcp == null)
+ {
+ if (other.mcp != null)
+ return false;
+ }
+ else if (System.identityHashCode(mcp) != System.identityHashCode(other.mcp))
+ return false;
+
+ if (subject == null)
+ {
+ if (other.subject != null)
+ return false;
+ }
+ else if (!SecurityActions.equals(subject, other.subject))
+ return false;
+
+ if (cri == null)
+ {
+ if (other.cri != null)
+ return false;
+ }
+ else if (!cri.equals(other.cri))
+ return false;
+
+ return true;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/FillRequest.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/FillRequest.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/FillRequest.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,107 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2012, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+/**
+ * Represents a fill request for a managed connection pool
+ *
+ * @author Jesper Pedersen
+ */
+class FillRequest
+{
+ /** Managed connection pool */
+ private ManagedConnectionPool mcp;
+
+ /** Fill size */
+ private int fillSize;
+
+ /**
+ * Constructor
+ * @param mcp The managed connection pool
+ * @param fillSize The fill size
+ */
+ FillRequest(ManagedConnectionPool mcp, int fillSize)
+ {
+ this.mcp = mcp;
+ this.fillSize = fillSize;
+ }
+
+ /**
+ * Get the managed connection pool
+ * @return The value
+ */
+ ManagedConnectionPool getManagedConnectionPool()
+ {
+ return mcp;
+ }
+
+ /**
+ * Get the fill size
+ * @return The value
+ */
+ int getFillSize()
+ {
+ return fillSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ int result = 31;
+ result += 7 * mcp.hashCode();
+ result += 7 * fillSize;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+
+ if (obj == null)
+ return false;
+
+ if (!(obj instanceof FillRequest))
+ return false;
+
+ FillRequest other = (FillRequest) obj;
+
+ if (mcp == null)
+ {
+ if (other.mcp != null)
+ return false;
+ }
+ else if (System.identityHashCode(mcp) != System.identityHashCode(other.mcp))
+ return false;
+
+ if (fillSize != other.fillSize)
+ return false;
+
+ return true;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/LeakDumperManagedConnectionPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/LeakDumperManagedConnectionPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/LeakDumperManagedConnectionPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,225 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2013, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * A managed connection pool which dumps any leaks at shutdown
+ *
+ * @author Jesper Pedersen
+ */
+public class LeakDumperManagedConnectionPool extends SemaphoreArrayListManagedConnectionPool
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class,
+ LeakDumperManagedConnectionPool.class.getName());
+
+ /** Dump to special file too */
+ private static boolean useFile = false;
+
+ /** Special file name */
+ private static String leakFileName = null;
+
+ /** Leak lock */
+ private static Object leakLock = new Object();
+
+ /** The tracker map of connection listeners */
+ private final ConcurrentMap tracker =
+ new ConcurrentHashMap();
+
+ /** The time map of connection listeners */
+ private final ConcurrentMap times =
+ new ConcurrentHashMap();
+
+ static
+ {
+ String f = SecurityActions.getSystemProperty("ironjacamar.leaklog");
+ if (f != null && !f.trim().equals(""))
+ {
+ useFile = true;
+ leakFileName = f;
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public LeakDumperManagedConnectionPool()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ConnectionListener getConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException
+ {
+ ConnectionListener cl = super.getConnection(subject, cri);
+
+ tracker.put(cl, new Throwable("ALLOCATION LEAK"));
+ times.put(cl, Long.valueOf(System.currentTimeMillis()));
+
+ return cl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void returnConnection(ConnectionListener cl, boolean kill, boolean cleanup)
+ {
+ tracker.remove(cl);
+ times.remove(cl);
+ super.returnConnection(cl, kill, cleanup);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void connectionListenerDestroyed(ConnectionListener cl)
+ {
+ if (tracker.containsKey(cl))
+ {
+ Throwable t = tracker.get(cl);
+ Long l = times.get(cl);
+ log.connectionLeak(getPoolName(), Integer.toHexString(System.identityHashCode(cl)), l.longValue(), t);
+
+ if (useFile)
+ dump(cl, t, l.longValue());
+
+ tracker.remove(cl);
+ times.remove(cl);
+ }
+ super.connectionListenerDestroyed(cl);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void shutdown()
+ {
+ if (tracker.size() > 0)
+ {
+ Iterator> it = tracker.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = it.next();
+ Long l = times.get(entry.getKey());
+
+ log.connectionLeak(getPoolName(), Integer.toHexString(System.identityHashCode(entry.getKey())),
+ l.longValue(), entry.getValue());
+
+ if (useFile)
+ dump(entry.getKey(), entry.getValue(), l.longValue());
+ }
+
+ tracker.clear();
+ times.clear();
+ }
+
+ super.shutdown();
+ }
+
+ private void dump(ConnectionListener cl, Throwable t, long time)
+ {
+ synchronized (leakLock)
+ {
+ OutputStream os = null;
+ try
+ {
+ os = new FileOutputStream(leakFileName, true);
+
+ PrintStream ps = new PrintStream(os, true);
+
+ ps.print("Leak detected in pool: ");
+ ps.println(getPoolName());
+
+ ps.print(" ConnectionListener: ");
+ ps.println(Integer.toHexString(System.identityHashCode(cl)));
+
+ ps.print(" Allocation timestamp: ");
+ ps.println(time);
+
+ ps.println(" Allocation stacktrack:");
+
+ t.printStackTrace(ps);
+
+ ps.println();
+
+ ps.flush();
+ }
+ catch (Exception e)
+ {
+ log.debug(e.getMessage(), e);
+ }
+ finally
+ {
+ if (os != null)
+ {
+ try
+ {
+ os.close();
+ }
+ catch (IOException ioe)
+ {
+ // Ignore
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * String representation
+ * @return The string
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("LeakDumperManagedConnectionPool@").append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append("[super=").append(super.toString());
+ sb.append("]");
+
+ return sb.toString();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,173 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2010, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import org.jboss.jca.core.api.connectionmanager.pool.FlushMode;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.idle.IdleConnectionRemovalSupport;
+
+import java.util.Collection;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+/**
+ * Represents a managed connection pool, which manages all connection listeners
+ *
+ * @author Jesper Pedersen
+ */
+public interface ManagedConnectionPool extends IdleConnectionRemovalSupport
+{
+ /**
+ * Get the last used timestamp
+ * @return The value
+ */
+ public long getLastUsed();
+
+ /**
+ * Initialize the managed connection pool
+ *
+ * @param mcf The managed connection factory
+ * @param cm The connection manager
+ * @param subject The subject
+ * @param cri The connection request info
+ * @param pc The pool configuration
+ * @param p The pool
+ */
+ public void initialize(ManagedConnectionFactory mcf, ConnectionManager cm, Subject subject,
+ ConnectionRequestInfo cri, PoolConfiguration pc, Pool p);
+
+ /**
+ * Returns a connection listener that wraps managed connection.
+ * @param subject subject
+ * @param cri connection request info
+ * @return connection listener wrapped managed connection
+ * @throws ResourceException exception
+ */
+ public ConnectionListener getConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException;
+
+ /**
+ * Find a connection listener
+ * @param mc The managed connection
+ * @return The connection listener; null
if the connection listener doesn't belong
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc);
+
+ /**
+ * Find a connection listener
+ * @param mc The managed connection
+ * @param connection The connection
+ * @return The connection listener; null
if the connection listener doesn't belong
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc, Object connection);
+
+ /**
+ * Return connection to the pool.
+ * @param cl connection listener
+ * @param kill kill connection
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill);
+
+ /**
+ * Checks if the pool is empty or not
+ * @return True if is emtpy; otherwise false
+ */
+ public boolean isEmpty();
+
+ /**
+ * Is the pool idle ?
+ * @return True if idle, otherwise false
+ */
+ public boolean isIdle();
+
+ /**
+ * Checks if the pool is running or not
+ * @return True if is running; otherwise false
+ */
+ public boolean isRunning();
+
+ /**
+ * Get number of active connections
+ * @return The value
+ */
+ public int getActive();
+
+ /**
+ * Prefill
+ */
+ public void prefill();
+
+ /**
+ * Flush
+ * @param mode The flush mode
+ * @param toDestroy list of connection listeners to be destroyed
+ */
+ public void flush(FlushMode mode, Collection toDestroy);
+
+ /**
+ * Shutdown
+ */
+ public void shutdown();
+
+ /**
+ * Fill to
+ * @param size The size
+ */
+ public void fillTo(int size);
+
+ /**
+ * Validate connecitons.
+ * @throws Exception for exception
+ */
+ public void validateConnections() throws Exception;
+
+ /**
+ * Increase capacity
+ * @param subject The subject
+ * @param cri The connection request information object
+ */
+ public void increaseCapacity(Subject subject, ConnectionRequestInfo cri);
+
+ /**
+ * Add a connection to the pool
+ * @param cl The connection listener
+ */
+ public void addConnectionListener(ConnectionListener cl);
+
+ /**
+ * Remove an idle connection from the pool
+ * @return A connection listener; null
if no connection listener was available
+ */
+ public ConnectionListener removeConnectionListener();
+
+ /**
+ * Notify that a connection listener belonging to this pool was destroyed.
+ */
+ public void connectionListenerDestroyed(ConnectionListener cl);
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPoolFactory.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPoolFactory.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPoolFactory.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,195 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2010, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Factory to create a managed connection pool
+ *
+ * @author Jesper Pedersen
+ */
+public class ManagedConnectionPoolFactory
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class,
+ ManagedConnectionPoolFactory.class.getName());
+
+ /** Default implementation */
+ public static final String DEFAULT_IMPLEMENTATION =
+ "org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool";
+
+ /** Experimental implementation */
+ public static final String EXPERIMENTAL_IMPLEMENTATION =
+ "org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreConcurrentLinkedDequeManagedConnectionPool";
+
+ /** Deprecated implementations */
+ private static final String[] DEPRECATED_IMPLEMENTATIONS = new String[] {
+ "org.jboss.jca.core.connectionmanager.pool.mcp.ArrayBlockingQueueManagedConnectionPool",
+ "org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreConcurrentLinkedQueueManagedConnectionPool"
+ };
+
+ /** Default class definition */
+ private static Class> defaultImplementation;
+
+ /** Override */
+ private static boolean override;
+
+ static
+ {
+ String clz = SecurityActions.getSystemProperty("ironjacamar.mcp");
+
+ if (clz != null && !clz.trim().equals(""))
+ {
+ clz = clz.trim();
+ for (String impl : DEPRECATED_IMPLEMENTATIONS)
+ {
+ if (clz.equals(impl))
+ {
+ log.deprecatedPool(clz, EXPERIMENTAL_IMPLEMENTATION);
+ clz = EXPERIMENTAL_IMPLEMENTATION;
+ }
+ }
+
+ override = true;
+ }
+ else
+ {
+ clz = DEFAULT_IMPLEMENTATION;
+ override = false;
+ }
+
+ try
+ {
+ defaultImplementation = Class.forName(clz,
+ true,
+ SecurityActions.getClassLoader(ManagedConnectionPoolFactory.class));
+ }
+ catch (Throwable t)
+ {
+ throw new RuntimeException("Unable to load default managed connection pool implementation: " + clz);
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public ManagedConnectionPoolFactory()
+ {
+ }
+
+ /**
+ * Get the default implementation
+ * @return The value
+ */
+ public String getDefaultImplementation()
+ {
+ return defaultImplementation.getName();
+ }
+
+ /**
+ * Is override
+ * @return The value
+ */
+ public boolean isOverride()
+ {
+ return override;
+ }
+
+ /**
+ * Create a managed connection pool using the default implementation strategy
+ *
+ * @param mcf the managed connection factory
+ * @param cm the connection manager
+ * @param subject the subject
+ * @param cri the connection request info
+ * @param pc the pool configuration
+ * @param p The pool
+ * @return The initialized managed connection pool
+ * @exception Throwable Thrown in case of an error
+ */
+ public ManagedConnectionPool create(ManagedConnectionFactory mcf, ConnectionManager cm, Subject subject,
+ ConnectionRequestInfo cri, PoolConfiguration pc, Pool p)
+ throws Throwable
+ {
+ ManagedConnectionPool mcp = (ManagedConnectionPool)defaultImplementation.newInstance();
+
+ return init(mcp, mcf, cm, subject, cri, pc, p);
+ }
+
+ /**
+ * Create a managed connection pool using a specific implementation strategy
+ *
+ * @param strategy Fullt qualified class name for the managed connection pool strategy
+ * @param mcf the managed connection factory
+ * @param cm the connection manager
+ * @param subject the subject
+ * @param cri the connection request info
+ * @param pc the pool configuration
+ * @param p The pool
+ * @return The initialized managed connection pool
+ * @exception Throwable Thrown in case of an error
+ */
+ public ManagedConnectionPool create(String strategy,
+ ManagedConnectionFactory mcf, ConnectionManager cm, Subject subject,
+ ConnectionRequestInfo cri, PoolConfiguration pc, Pool p)
+ throws Throwable
+ {
+ Class> clz = Class.forName(strategy,
+ true,
+ SecurityActions.getClassLoader(ManagedConnectionPoolFactory.class));
+
+ ManagedConnectionPool mcp = (ManagedConnectionPool)clz.newInstance();
+
+ return init(mcp, mcf, cm, subject, cri, pc, p);
+ }
+
+ /**
+ * Initialize
+ * @param mcp The managed connection pool
+ * @param mcf the managed connection factory
+ * @param cm the connection manager
+ * @param subject the subject
+ * @param cri the connection request info
+ * @param pc the pool configuration
+ * @param p The pool
+ * @return The initialized managed connection pool
+ */
+ private ManagedConnectionPool init(ManagedConnectionPool mcp,
+ ManagedConnectionFactory mcf, ConnectionManager cm, Subject subject,
+ ConnectionRequestInfo cri, PoolConfiguration pc, Pool p)
+ {
+ mcp.initialize(mcf, cm, subject, cri, pc, p);
+
+ return mcp;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPoolUtility.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPoolUtility.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/ManagedConnectionPoolUtility.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,219 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.pool.PoolStatisticsImpl;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+
+import java.util.Collection;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+/**
+ * Managed connection pool utility class
+ *
+ * @author Jesper Pedersen
+ */
+class ManagedConnectionPoolUtility
+{
+ private static String newLine = SecurityActions.getSystemProperty("line.separator");
+
+ /**
+ * Get the full details of a managed connection pool state
+ * @param method The method identifier
+ * @param poolName The pool name
+ * @param inUse The in use count
+ * @param max The max
+ * @return The state
+ */
+ static String details(String method, String poolName, int inUse, int max)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+
+ sb.append(poolName).append(": ");
+ sb.append(method).append(" ");
+ sb.append("[");
+ sb.append(Integer.toString(inUse));
+ sb.append("/");
+ sb.append(Integer.toString(max));
+ sb.append("]");
+
+ return sb.toString();
+ }
+
+ /**
+ * Get the full details of a managed connection pool state
+ * @param mcp The managed connection pool
+ * @param method The method identifier
+ * @param mcf The managed connection factory
+ * @param cm The connection manager
+ * @param pool The pool
+ * @param pc The pool configuration
+ * @param available The available connection listeners
+ * @param inUse The in-use connection listeners
+ * @param ps The statistics
+ * @param subject The subject
+ * @param cri The ConnectionRequestInfo
+ * @return The state
+ */
+ static String fullDetails(ManagedConnectionPool mcp, String method, ManagedConnectionFactory mcf,
+ ConnectionManager cm, Pool pool, PoolConfiguration pc,
+ Collection available, Collection inUse,
+ PoolStatisticsImpl ps, Subject subject, ConnectionRequestInfo cri)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ long now = System.currentTimeMillis();
+
+ sb.append(method).append(newLine);
+ sb.append("Method: ").append(method).append(newLine);
+ sb.append(" Subject: ").append(subject == null ? "null" :
+ Integer.toHexString(System.identityHashCode(subject))).append(newLine);
+ sb.append(" CRI: ").append(cri == null ? "null" :
+ Integer.toHexString(System.identityHashCode(cri))).append(newLine);
+ sb.append("ManagedConnectionPool:").append(newLine);
+ sb.append(" Class: ").append(mcp.getClass().getName()).append(newLine);
+ sb.append(" Object: ").append(Integer.toHexString(System.identityHashCode(mcp))).append(newLine);
+ sb.append("ManagedConnectionFactory:").append(newLine);
+ sb.append(" Class: ").append(mcf.getClass().getName()).append(newLine);
+ sb.append(" Object: ").append(Integer.toHexString(System.identityHashCode(mcf))).append(newLine);
+ sb.append("ConnectionManager:").append(newLine);
+ sb.append(" Class: ").append(cm.getClass().getName()).append(newLine);
+ sb.append(" Object: ").append(Integer.toHexString(System.identityHashCode(cm))).append(newLine);
+ sb.append("Pool:").append(newLine);
+ sb.append(" Name: ").append(pool.getName()).append(newLine);
+ sb.append(" Class: ").append(pool.getClass().getName()).append(newLine);
+ sb.append(" Object: ").append(Integer.toHexString(System.identityHashCode(pool))).append(newLine);
+ sb.append(" FIFO: ").append(pool.isFIFO()).append(newLine);
+ sb.append("PoolConfiguration:").append(newLine);
+ sb.append(" MinSize: ").append(pc.getMinSize()).append(newLine);
+ sb.append(" InitialSize: ").append(pc.getInitialSize()).append(newLine);
+ sb.append(" MaxSize: ").append(pc.getMaxSize()).append(newLine);
+ sb.append(" BlockingTimeout: ").append(pc.getBlockingTimeout()).append(newLine);
+ sb.append(" IdleTimeoutMinutes: ").append(pc.getIdleTimeoutMinutes()).append(newLine);
+ sb.append(" ValidateOnMatch: ").append(pc.isValidateOnMatch()).append(newLine);
+ sb.append(" BackgroundValidation: ").append(pc.isBackgroundValidation()).append(newLine);
+ sb.append(" BackgroundValidationMillis: ").append(pc.getBackgroundValidationMillis()).append(newLine);
+ sb.append(" StrictMin: ").append(pc.isStrictMin()).append(newLine);
+ sb.append(" UseFastFail: ").append(pc.isUseFastFail()).append(newLine);
+ if (pool.getCapacity() != null)
+ {
+ if (pool.getCapacity().getIncrementer() != null)
+ sb.append(" Incrementer: ").append(pool.getCapacity().getIncrementer()).append(newLine);
+
+ if (pool.getCapacity().getDecrementer() != null)
+ sb.append(" Decrementer: ").append(pool.getCapacity().getDecrementer()).append(newLine);
+ }
+
+ int availableSize = (available != null ? available.size() : 0);
+ sb.append("Available (").append(availableSize).append("):").append(newLine);
+ if (available != null)
+ {
+ for (ConnectionListener cl : available)
+ {
+ sb.append(" ").append(Integer.toHexString(System.identityHashCode(cl)));
+ sb.append(" (").append(cl.getState()).append(")");
+ sb.append(" (Returned: ").append(cl.getLastReturnedTime()).append(")");
+ sb.append(" (Validated: ").append(cl.getLastValidatedTime()).append(")");
+ sb.append(" (Pool: ").append(now - cl.getLastReturnedTime()).append(")").append(newLine);
+ }
+ }
+
+ int inUseSize = (inUse != null ? inUse.size() : 0);
+ sb.append("InUse (").append(inUseSize).append("):").append(newLine);
+ if (inUse != null)
+ {
+ for (ConnectionListener cl : inUse)
+ {
+ sb.append(" ").append(Integer.toHexString(System.identityHashCode(cl)));
+ sb.append(" (").append(cl.getState()).append(")");
+ sb.append(" (CheckedOut: ").append(cl.getLastCheckedOutTime()).append(")");
+ sb.append(" (Validated: ").append(cl.getLastValidatedTime()).append(")");
+ sb.append(" (Usage: ").append(now - cl.getLastCheckedOutTime()).append(")").append(newLine);
+ }
+ }
+
+ sb.append("Statistics:").append(newLine);
+ sb.append(" ActiveCount: ").append(ps.getActiveCount()).append(newLine);
+ sb.append(" AvailableCount: ").append(ps.getAvailableCount()).append(newLine);
+ sb.append(" AverageBlockingTime: ").append(ps.getAverageBlockingTime()).append(newLine);
+ sb.append(" AverageCreationTime: ").append(ps.getAverageCreationTime()).append(newLine);
+ sb.append(" AverageGetTime: ").append(ps.getAverageGetTime()).append(newLine);
+ sb.append(" AveragePoolTime: ").append(ps.getAveragePoolTime()).append(newLine);
+ sb.append(" AverageUsageTime: ").append(ps.getAverageUsageTime()).append(newLine);
+ sb.append(" BlockingFailureCount: ").append(ps.getBlockingFailureCount()).append(newLine);
+ sb.append(" CreatedCount: ").append(ps.getCreatedCount()).append(newLine);
+ sb.append(" DestroyedCount: ").append(ps.getDestroyedCount()).append(newLine);
+ sb.append(" IdleCount: ").append(ps.getIdleCount()).append(newLine);
+ sb.append(" InUseCount: ").append(ps.getInUseCount()).append(newLine);
+ sb.append(" MaxCreationTime: ").append(ps.getMaxCreationTime()).append(newLine);
+ sb.append(" MaxGetTime: ").append(ps.getMaxGetTime()).append(newLine);
+ sb.append(" MaxPoolTime: ").append(ps.getMaxPoolTime()).append(newLine);
+ sb.append(" MaxUsageTime: ").append(ps.getMaxUsageTime()).append(newLine);
+ sb.append(" MaxUsedCount: ").append(ps.getMaxUsedCount()).append(newLine);
+ sb.append(" MaxWaitTime: ").append(ps.getMaxWaitTime()).append(newLine);
+ sb.append(" TimedOut: ").append(ps.getTimedOut()).append(newLine);
+ sb.append(" TotalBlockingTime: ").append(ps.getTotalBlockingTime()).append(newLine);
+ sb.append(" TotalCreationTime: ").append(ps.getTotalCreationTime()).append(newLine);
+ sb.append(" TotalGetTime: ").append(ps.getTotalGetTime()).append(newLine);
+ sb.append(" TotalPoolTime: ").append(ps.getTotalPoolTime()).append(newLine);
+ sb.append(" TotalUsageTime: ").append(ps.getTotalUsageTime()).append(newLine);
+ sb.append(" WaitCount: ").append(ps.getWaitCount()).append(newLine);
+
+ sb.append("XAResource:").append(newLine);
+ sb.append(" CommitCount: ").append(ps.getCommitCount()).append(newLine);
+ sb.append(" CommitTotalTime: ").append(ps.getCommitTotalTime()).append(newLine);
+ sb.append(" CommitAverageTime: ").append(ps.getCommitAverageTime()).append(newLine);
+ sb.append(" CommitMaxTime: ").append(ps.getCommitMaxTime()).append(newLine);
+ sb.append(" EndCount: ").append(ps.getEndCount()).append(newLine);
+ sb.append(" EndTotalTime: ").append(ps.getEndTotalTime()).append(newLine);
+ sb.append(" EndAverageTime: ").append(ps.getEndAverageTime()).append(newLine);
+ sb.append(" EndMaxTime: ").append(ps.getEndMaxTime()).append(newLine);
+ sb.append(" ForgetCount: ").append(ps.getForgetCount()).append(newLine);
+ sb.append(" ForgetTotalTime: ").append(ps.getForgetTotalTime()).append(newLine);
+ sb.append(" ForgetAverageTime: ").append(ps.getForgetAverageTime()).append(newLine);
+ sb.append(" ForgetMaxTime: ").append(ps.getForgetMaxTime()).append(newLine);
+ sb.append(" PrepareCount: ").append(ps.getPrepareCount()).append(newLine);
+ sb.append(" PrepareTotalTime: ").append(ps.getPrepareTotalTime()).append(newLine);
+ sb.append(" PrepareAverageTime: ").append(ps.getPrepareAverageTime()).append(newLine);
+ sb.append(" PrepareMaxTime: ").append(ps.getPrepareMaxTime()).append(newLine);
+ sb.append(" RecoverCount: ").append(ps.getRecoverCount()).append(newLine);
+ sb.append(" RecoverTotalTime: ").append(ps.getRecoverTotalTime()).append(newLine);
+ sb.append(" RecoverAverageTime: ").append(ps.getRecoverAverageTime()).append(newLine);
+ sb.append(" RecoverMaxTime: ").append(ps.getRecoverMaxTime()).append(newLine);
+ sb.append(" RollbackCount: ").append(ps.getRollbackCount()).append(newLine);
+ sb.append(" RollbackTotalTime: ").append(ps.getRollbackTotalTime()).append(newLine);
+ sb.append(" RollbackAverageTime: ").append(ps.getRollbackAverageTime()).append(newLine);
+ sb.append(" RollbackMaxTime: ").append(ps.getRollbackMaxTime()).append(newLine);
+ sb.append(" StartCount: ").append(ps.getStartCount()).append(newLine);
+ sb.append(" StartTotalTime: ").append(ps.getStartTotalTime()).append(newLine);
+ sb.append(" StartAverageTime: ").append(ps.getStartAverageTime()).append(newLine);
+ sb.append(" StartMaxTime: ").append(ps.getStartMaxTime());
+
+ return sb.toString();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/PoolFiller.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/PoolFiller.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/PoolFiller.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,139 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import java.util.LinkedList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * PoolFiller
+ *
+ * @author David Jencks
+ * @author Scott Stark
+ * @author Adrian Brock
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+class PoolFiller implements Runnable
+{
+
+ /** Singleton instance */
+ private static final PoolFiller FILLER = new PoolFiller();
+
+ /** Pools list */
+ private final LinkedList pools = new LinkedList();
+
+ /** Filler thread */
+ private final Thread fillerThread;
+
+ /** Thread name */
+ private static final String THREAD_FILLER_NAME = "JCA PoolFiller";
+
+ /**Thread is configured or not*/
+ private AtomicBoolean threadStarted = new AtomicBoolean(false);
+
+ /**
+ * Fill given pool
+ * @param fr The fill request
+ */
+ static void fillPool(FillRequest fr)
+ {
+ FILLER.internalFillPool(fr);
+ }
+
+ /**
+ * Creates a new pool filler instance.
+ */
+ PoolFiller()
+ {
+ fillerThread = new Thread(this, THREAD_FILLER_NAME);
+ fillerThread.setDaemon(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run()
+ {
+ final ClassLoader myClassLoader = SecurityActions.getClassLoader(getClass());
+ SecurityActions.setThreadContextClassLoader(myClassLoader);
+
+ while (true)
+ {
+ boolean empty = false;
+
+ while (!empty)
+ {
+ FillRequest fr = null;
+
+ synchronized (pools)
+ {
+ empty = pools.isEmpty();
+ if (!empty)
+ fr = pools.removeFirst();
+ }
+
+ if (!empty)
+ {
+ fr.getManagedConnectionPool().fillTo(fr.getFillSize());
+ }
+ }
+
+ try
+ {
+ synchronized (pools)
+ {
+ while (pools.isEmpty())
+ {
+ pools.wait();
+ }
+ }
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+ }
+
+ /**
+ * Fill pool
+ * @param fr The fill request
+ */
+ private void internalFillPool(FillRequest fr)
+ {
+ if (this.threadStarted.compareAndSet(false, true))
+ {
+ this.fillerThread.start();
+ }
+
+ synchronized (pools)
+ {
+ if (!pools.contains(fr))
+ {
+ pools.addLast(fr);
+ pools.notifyAll();
+ }
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,138 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Gurkan Erdogdu
+ */
+class SecurityActions
+{
+ /**
+ * Get the classloader.
+ * @param c The class
+ * @return The classloader
+ */
+ static ClassLoader getClassLoader(final Class> c)
+ {
+ if (System.getSecurityManager() == null)
+ return c.getClassLoader();
+
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public ClassLoader run()
+ {
+ return c.getClassLoader();
+ }
+ });
+ }
+
+ /**
+ * Set the context classloader.
+ * @param cl classloader
+ */
+ public static void setThreadContextClassLoader(final ClassLoader cl)
+ {
+ if (System.getSecurityManager() == null)
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ else
+ {
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+
+ return null;
+ }
+ });
+ }
+ }
+
+ /**
+ * Get a system property
+ * @param name The property name
+ * @return The property value
+ */
+ static String getSystemProperty(final String name)
+ {
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public String run()
+ {
+ return System.getProperty(name);
+ }
+ });
+ }
+
+ /**
+ * Get the hash code for a Subject
+ * @param subject The Subject
+ * @return The hash code
+ */
+ static int hashCode(final Subject subject)
+ {
+ if (System.getSecurityManager() == null)
+ return subject.hashCode();
+
+ Integer hashCode = AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Integer run()
+ {
+ return subject.hashCode();
+ }
+ });
+
+ return hashCode.intValue();
+ }
+
+ /**
+ * Verify if two Subject's are equal
+ * @param s1 The first Subject
+ * @param s2 The second Subject
+ * @return True if equal; otherwise false
+ */
+ static boolean equals(final Subject s1, final Subject s2)
+ {
+ if (System.getSecurityManager() == null)
+ return s1 != null ? s1.equals(s2) : s2 == null;
+
+ Boolean equals = AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Boolean run()
+ {
+ return s1 != null ? s1.equals(s2) : s2 == null;
+ }
+ });
+
+ return equals.booleanValue();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SemaphoreArrayListManagedConnectionPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SemaphoreArrayListManagedConnectionPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SemaphoreArrayListManagedConnectionPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,1602 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2010, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.FlushMode;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionState;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.api.PrefillPool;
+import org.jboss.jca.core.connectionmanager.pool.capacity.DefaultCapacity;
+import org.jboss.jca.core.connectionmanager.pool.capacity.TimedOutDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.capacity.TimedOutFIFODecrementer;
+import org.jboss.jca.core.connectionmanager.pool.idle.IdleRemover;
+import org.jboss.jca.core.connectionmanager.pool.validator.ConnectionValidator;
+import org.jboss.jca.core.tracer.Tracer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import javax.resource.ResourceException;
+import javax.resource.cci.Connection;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.DissociatableManagedConnection;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.RetryableException;
+import javax.resource.spi.ValidatingManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Messages;
+
+/**
+ * The internal pool implementation
+ *
+ * @author David Jencks
+ * @author Adrian Brock
+ * @author Weston Price
+ * @author Jesper Pedersen
+ */
+public class SemaphoreArrayListManagedConnectionPool implements ManagedConnectionPool
+{
+ /** The log */
+ private CoreLogger log;
+
+ /** Whether debug is enabled */
+ private boolean debug;
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** The managed connection factory */
+ private ManagedConnectionFactory mcf;
+
+ /** The connection manager */
+ private ConnectionManager cm;
+
+ /** The default subject */
+ private Subject defaultSubject;
+
+ /** The default connection request information */
+ private ConnectionRequestInfo defaultCri;
+
+ /** The pool configuration */
+ private PoolConfiguration poolConfiguration;
+
+ /** The pool */
+ private Pool pool;
+
+ /** FIFO / FILO */
+ private boolean fifo;
+
+ /**
+ * Copy of the maximum size from the pooling parameters.
+ * Dynamic changes to this value are not compatible with
+ * the semaphore which cannot change be dynamically changed.
+ */
+ private int maxSize;
+
+ /** The available connection event listeners */
+ private ArrayList cls;
+
+ /** The map of connection listeners which has a permit */
+ private final ConcurrentMap clPermits =
+ new ConcurrentHashMap();
+
+ /** The checked out connections */
+ private final ArrayList checkedOut = new ArrayList();
+
+ /** Supports lazy association */
+ private Boolean supportsLazyAssociation;
+
+ /** Last idle check */
+ private long lastIdleCheck;
+
+ /** Last used */
+ private long lastUsed;
+
+ /**
+ * Constructor
+ */
+ public SemaphoreArrayListManagedConnectionPool()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initialize(ManagedConnectionFactory mcf, ConnectionManager cm, Subject subject,
+ ConnectionRequestInfo cri, PoolConfiguration pc, Pool p)
+ {
+ if (mcf == null)
+ throw new IllegalArgumentException("ManagedConnectionFactory is null");
+
+ if (cm == null)
+ throw new IllegalArgumentException("ConnectionManager is null");
+
+ if (pc == null)
+ throw new IllegalArgumentException("PoolConfiguration is null");
+
+ if (p == null)
+ throw new IllegalArgumentException("Pool is null");
+
+ this.mcf = mcf;
+ this.cm = cm;
+ this.defaultSubject = subject;
+ this.defaultCri = cri;
+ this.poolConfiguration = pc;
+ this.maxSize = pc.getMaxSize();
+ this.pool = p;
+ this.fifo = p.isFIFO();
+ this.log = pool.getLogger();
+ this.debug = log.isDebugEnabled();
+ this.cls = new ArrayList(this.maxSize);
+ this.supportsLazyAssociation = null;
+ this.lastIdleCheck = System.currentTimeMillis();
+ this.lastUsed = Long.MAX_VALUE;
+
+ // Schedule managed connection pool for prefill
+ if ((pc.isPrefill() || pc.isStrictMin()) && p instanceof PrefillPool && pc.getInitialSize() > 0)
+ {
+ PoolFiller.fillPool(new FillRequest(this, pc.getInitialSize()));
+ }
+
+ if (poolConfiguration.getIdleTimeoutMinutes() > 0)
+ {
+ //Register removal support
+ IdleRemover.getInstance().registerPool(this, poolConfiguration.getIdleTimeoutMinutes() * 1000L * 60);
+ }
+
+ if (poolConfiguration.isBackgroundValidation() && poolConfiguration.getBackgroundValidationMillis() > 0)
+ {
+ if (debug)
+ log.debug("Registering for background validation at interval " +
+ poolConfiguration.getBackgroundValidationMillis());
+
+ //Register validation
+ ConnectionValidator.getInstance().registerPool(this, poolConfiguration.getBackgroundValidationMillis());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastUsed()
+ {
+ return lastUsed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRunning()
+ {
+ return !pool.isShutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty()
+ {
+ synchronized (cls)
+ {
+ return cls.size() == 0 && checkedOut.size() == 0;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isIdle()
+ {
+ synchronized (cls)
+ {
+ return checkedOut.size() == 0;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getActive()
+ {
+ synchronized (cls)
+ {
+ return cls.size() + checkedOut.size();
+ }
+ }
+
+ /**
+ * Check if the pool has reached a certain size
+ * @param size The size
+ * @return True if reached; otherwise false
+ */
+ private boolean isSize(int size)
+ {
+ synchronized (cls)
+ {
+ return (cls.size() + checkedOut.size()) >= size;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prefill()
+ {
+ if (isRunning() &&
+ (poolConfiguration.isPrefill() || poolConfiguration.isStrictMin()) &&
+ pool instanceof PrefillPool &&
+ poolConfiguration.getMinSize() > 0)
+ PoolFiller.fillPool(new FillRequest(this, poolConfiguration.getMinSize()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener getConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException
+ {
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "getConnection(" + subject + ", " + cri + ")";
+ log.trace(ManagedConnectionPoolUtility.fullDetails(this, method,
+ mcf, cm, pool, poolConfiguration,
+ cls, checkedOut, pool.getInternalStatistics(),
+ subject, cri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "getConnection(" + subject + ", " + cri + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ subject = (subject == null) ? defaultSubject : subject;
+ cri = (cri == null) ? defaultCri : cri;
+
+ if (pool.isFull())
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaWaitCount();
+
+ if (pool.isSharable() && (supportsLazyAssociation == null || supportsLazyAssociation.booleanValue()))
+ {
+ if (supportsLazyAssociation == null)
+ checkLazyAssociation();
+
+ if (supportsLazyAssociation != null && supportsLazyAssociation.booleanValue())
+ {
+ if (log.isTraceEnabled())
+ log.tracef("Trying to detach - Pool: %s MCP: %s", pool.getName(),
+ Integer.toHexString(System.identityHashCode(this)));
+
+ if (!detachConnectionListener())
+ {
+ log.tracef("Detaching didn't succeed - Pool: %s MCP: %s", pool.getName(),
+ Integer.toHexString(System.identityHashCode(this)));
+ }
+ }
+ }
+ }
+
+ long startWait = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+ try
+ {
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalBlockingTime(System.currentTimeMillis() - startWait);
+
+ //We have a permit to get a connection. Is there one in the pool already?
+ ConnectionListener cl = null;
+ do
+ {
+ if (!isRunning())
+ {
+ pool.getLock().release();
+ throw new ResourceException(
+ bundle.thePoolHasBeenShutdown(pool.getName(),
+ Integer.toHexString(System.identityHashCode(this))));
+ }
+
+ synchronized (cls)
+ {
+ if (cls.size() > 0)
+ {
+ if (fifo)
+ {
+ cl = cls.remove(0);
+ }
+ else
+ {
+ cl = cls.remove(cls.size() - 1);
+ }
+ checkedOut.add(cl);
+ }
+ }
+
+ if (cl != null)
+ {
+ //Yes, we retrieved a ManagedConnection from the pool. Does it match?
+ try
+ {
+ Object matchedMC = mcf.matchManagedConnections(Collections.singleton(cl.getManagedConnection()),
+ subject, cri);
+
+ boolean valid = true;
+ if (matchedMC != null)
+ {
+ if (poolConfiguration.isValidateOnMatch())
+ {
+ if (mcf instanceof ValidatingManagedConnectionFactory)
+ {
+ try
+ {
+ ValidatingManagedConnectionFactory vcf = (ValidatingManagedConnectionFactory) mcf;
+ Set candidateSet = Collections.singleton(cl.getManagedConnection());
+ candidateSet = vcf.getInvalidConnections(candidateSet);
+
+ if (candidateSet != null && candidateSet.size() > 0)
+ {
+ valid = false;
+ }
+ }
+ catch (Throwable t)
+ {
+ valid = false;
+ if (log.isTraceEnabled())
+ log.trace("Exception while ValidateOnMatch: " + t.getMessage(), t);
+ }
+ }
+ else
+ {
+ log.validateOnMatchNonCompliantManagedConnectionFactory(mcf.getClass().getName());
+ }
+ }
+
+ if (valid)
+ {
+ log.tracef("supplying ManagedConnection from pool: %s", cl);
+
+ clPermits.put(cl, cl);
+
+ lastUsed = System.currentTimeMillis();
+ cl.setLastCheckedOutTime(lastUsed);
+
+ if (pool.getInternalStatistics().isEnabled())
+ {
+ pool.getInternalStatistics().deltaTotalGetTime(lastUsed - startWait);
+ pool.getInternalStatistics().deltaTotalPoolTime(lastUsed - cl.getLastReturnedTime());
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.getConnectionListener(pool.getName(), this, cl, true, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ return cl;
+ }
+ }
+
+ // Match did not succeed but no exception was thrown.
+ // Either we have the matching strategy wrong or the
+ // connection died while being checked. We need to
+ // distinguish these cases, but for now we always
+ // destroy the connection.
+ if (valid)
+ {
+ log.destroyingConnectionNotSuccessfullyMatched(cl);
+ }
+ else
+ {
+ log.destroyingConnectionNotValidated(cl);
+ }
+
+ synchronized (cls)
+ {
+ checkedOut.remove(cl);
+ }
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ cl.getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, true, false, false,
+ false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ cl = null;
+ }
+ catch (Throwable t)
+ {
+ log.throwableWhileTryingMatchManagedConnectionThenDestroyingConnection(cl, t);
+
+ synchronized (cls)
+ {
+ checkedOut.remove(cl);
+ }
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ cl.getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, false, false, true,
+ false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ cl = null;
+ }
+
+ // We made it here, something went wrong and we should validate
+ // if we should continue attempting to acquire a connection
+ if (poolConfiguration.isUseFastFail())
+ {
+ if (log.isTraceEnabled())
+ log.trace("Fast failing for connection attempt. No more attempts will be made to " +
+ "acquire connection from pool and a new connection will be created immeadiately");
+ break;
+ }
+
+ }
+ }
+ while (cls.size() > 0);
+
+ // OK, we couldnt find a working connection from the pool. Make a new one.
+ try
+ {
+ // No, the pool was empty, so we have to make a new one.
+ cl = createConnectionEventListener(subject, cri);
+
+ if (Tracer.isEnabled())
+ Tracer.createConnectionListener(pool.getName(), this, cl, cl.getManagedConnection(),
+ true, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ synchronized (cls)
+ {
+ checkedOut.add(cl);
+ }
+
+ log.tracef("supplying new ManagedConnection: %s", cl);
+
+ clPermits.put(cl, cl);
+
+ lastUsed = System.currentTimeMillis();
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalGetTime(lastUsed - startWait);
+
+ // Trigger prefill
+ prefill();
+
+ // Trigger capacity increase
+ if (pool.getCapacity().getIncrementer() != null)
+ CapacityFiller.schedule(new CapacityRequest(this, subject, cri));
+
+ if (Tracer.isEnabled())
+ Tracer.getConnectionListener(pool.getName(), this, cl, false, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ return cl;
+ }
+ catch (Throwable t)
+ {
+ if (cl != null || !(t instanceof RetryableException))
+ log.throwableWhileAttemptingGetNewGonnection(cl, t);
+
+ if (cl != null)
+ {
+ // Return permit and rethrow
+ synchronized (cls)
+ {
+ checkedOut.remove(cl);
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, false, false, true,
+ false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ }
+
+ pool.getLock().release();
+
+ if (t instanceof ResourceException)
+ {
+ throw (ResourceException)t;
+ }
+ else
+ {
+ throw new ResourceException(bundle.unexpectedThrowableWhileTryingCreateConnection(cl), t);
+ }
+ }
+ }
+ else
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaBlockingFailureCount();
+
+ // We timed out
+ throw new ResourceException(bundle.noMManagedConnectionsAvailableWithinConfiguredBlockingTimeout(
+ poolConfiguration.getBlockingTimeout()));
+ }
+
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.interrupted();
+
+ long end = pool.getInternalStatistics().isEnabled() ? (System.currentTimeMillis() - startWait) : 0L;
+ pool.getInternalStatistics().deltaTotalBlockingTime(end);
+ throw new ResourceException(bundle.interruptedWhileRequestingPermit(end));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc)
+ {
+ return findConnectionListener(mc, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc, Object connection)
+ {
+ synchronized (cls)
+ {
+ for (ConnectionListener cl : checkedOut)
+ {
+ if (cl.controls(mc, connection))
+ return cl;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addConnectionListener(ConnectionListener cl)
+ {
+ synchronized (cls)
+ {
+ cls.add(cl);
+ }
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaCreatedCount();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener removeConnectionListener()
+ {
+ synchronized (cls)
+ {
+ if (cls.size() > 0)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaDestroyedCount();
+ return cls.remove(0);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill)
+ {
+ returnConnection(cl, kill, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill, boolean cleanup)
+ {
+ if (pool.getInternalStatistics().isEnabled() && cl.getState() != ConnectionState.DESTROYED)
+ pool.getInternalStatistics().deltaTotalUsageTime(System.currentTimeMillis() - cl.getLastCheckedOutTime());
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "returnConnection(" + Integer.toHexString(System.identityHashCode(cl)) + ", " + kill + ")";
+ log.trace(ManagedConnectionPoolUtility.fullDetails(this, method,
+ mcf, cm, pool, poolConfiguration,
+ cls, checkedOut, pool.getInternalStatistics(),
+ defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "returnConnection(" + Integer.toHexString(System.identityHashCode(cl)) + ", " + kill + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ if (cl.getState() == ConnectionState.DESTROYED)
+ {
+ log.tracef("ManagedConnection is being returned after it was destroyed: %s", cl);
+
+ ConnectionListener present = clPermits.remove(cl);
+ if (present != null)
+ {
+ pool.getLock().release();
+ }
+
+ return;
+ }
+
+ if (cleanup)
+ {
+ try
+ {
+ cl.getManagedConnection().cleanup();
+ }
+ catch (ResourceException re)
+ {
+ log.resourceExceptionCleaningUpManagedConnection(cl, re);
+ kill = true;
+ }
+ }
+
+ // We need to destroy this one
+ if (cl.getState() == ConnectionState.DESTROY || cl.getState() == ConnectionState.DESTROYED)
+ kill = true;
+
+ // This is really an error
+ if (!kill && isSize(poolConfiguration.getMaxSize() + 1))
+ {
+ log.destroyingReturnedConnectionMaximumPoolSizeExceeded(cl);
+ kill = true;
+ }
+
+ // If we are destroying, check the connection is not in the pool
+ if (kill)
+ {
+ synchronized (cls)
+ {
+ // Adrian Brock: A resource adapter can asynchronously notify us that
+ // a connection error occurred.
+ // This could happen while the connection is not checked out.
+ // e.g. JMS can do this via an ExceptionListener on the connection.
+ // I have twice had to reinstate this line of code, PLEASE DO NOT REMOVE IT!
+ checkedOut.remove(cl);
+ cls.remove(cl);
+
+ if (clPermits.remove(cl) != null)
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+ // return to the pool
+ else
+ {
+ cl.toPool();
+ synchronized (cls)
+ {
+ checkedOut.remove(cl);
+ if (!cls.contains(cl))
+ {
+ cls.add(cl);
+ }
+ else
+ {
+ log.attemptReturnConnectionTwice(cl, new Throwable("STACKTRACE"));
+ }
+
+ if (clPermits.remove(cl) != null)
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+
+ if (kill)
+ {
+ log.tracef("Destroying returned connection %s", cl);
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, true, false, false, false, false,
+ false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ cl = null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void flush(FlushMode mode, Collection toDestroy)
+ {
+ ArrayList keep = null;
+
+ synchronized (cls)
+ {
+ if (FlushMode.ALL == mode)
+ {
+ log.tracef("Flushing pool checkedOut=%s inPool=%s", checkedOut, cls);
+
+ // Mark checked out connections as requiring destruction
+ while (checkedOut.size() > 0)
+ {
+ ConnectionListener cl = checkedOut.remove(0);
+
+ log.tracef("Flush marking checked out connection for destruction %s", cl);
+
+ cl.setState(ConnectionState.DESTROY);
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalUsageTime(System.currentTimeMillis() -
+ cl.getLastCheckedOutTime());
+
+ toDestroy.add(cl);
+
+ ConnectionListener present = clPermits.remove(cl);
+ if (present != null)
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+ else if (FlushMode.GRACEFULLY == mode)
+ {
+ log.tracef("Gracefully flushing pool checkedOut=%s inPool=%s", checkedOut , cls);
+
+ // Mark checked out connections as requiring destruction upon return
+ for (ConnectionListener cl : checkedOut)
+ {
+ log.tracef("Graceful flush marking checked out connection for destruction %s", cl);
+
+ cl.setState(ConnectionState.DESTROY);
+ }
+ }
+
+ // Destroy connections in the pool
+ while (cls.size() > 0)
+ {
+ ConnectionListener cl = cls.remove(0);
+ boolean kill = true;
+
+ if (FlushMode.INVALID == mode && cl.getState().equals(ConnectionState.NORMAL))
+ {
+ if (mcf instanceof ValidatingManagedConnectionFactory)
+ {
+ try
+ {
+ ValidatingManagedConnectionFactory vcf = (ValidatingManagedConnectionFactory) mcf;
+ Set candidateSet = Collections.singleton(cl.getManagedConnection());
+ candidateSet = vcf.getInvalidConnections(candidateSet);
+
+ if (candidateSet == null || candidateSet.size() == 0)
+ {
+ kill = false;
+ }
+ }
+ catch (Throwable t)
+ {
+ log.trace("Exception during invalid flush", t);
+ }
+ }
+ }
+
+ if (kill)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ cl.getLastReturnedTime());
+
+ cl.setState(ConnectionState.DESTROY);
+ toDestroy.add(cl);
+ }
+ else
+ {
+ if (keep == null)
+ keep = new ArrayList(1);
+
+ keep.add(cl);
+ }
+ }
+
+ if (keep != null)
+ cls.addAll(keep);
+ }
+
+ // Trigger prefill
+ prefill();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeIdleConnections()
+ {
+ long now = System.currentTimeMillis();
+ long timeoutSetting = poolConfiguration.getIdleTimeoutMinutes() * 1000L * 60;
+
+ CapacityDecrementer decrementer = pool.getCapacity().getDecrementer();
+
+ if (decrementer == null)
+ decrementer = DefaultCapacity.DEFAULT_DECREMENTER;
+
+ if (TimedOutDecrementer.class.getName().equals(decrementer.getClass().getName()) ||
+ TimedOutFIFODecrementer.class.getName().equals(decrementer.getClass().getName()))
+ {
+ // Allow through each minute
+ if (now < (lastIdleCheck + 60000L))
+ return;
+ }
+ else
+ {
+ // Otherwise, strict check
+ if (now < (lastIdleCheck + timeoutSetting))
+ return;
+ }
+
+ lastIdleCheck = now;
+
+ ArrayList destroyConnections = new ArrayList();
+ long timeout = now - timeoutSetting;
+
+ boolean destroy = true;
+ int destroyed = 0;
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "removeIdleConnections(" + timeout + ")";
+ log.trace(ManagedConnectionPoolUtility.fullDetails(this, method,
+ mcf, cm, pool, poolConfiguration,
+ cls, checkedOut, pool.getInternalStatistics(),
+ defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "removeIdleConnections(" + timeout + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ while (destroy)
+ {
+ synchronized (cls)
+ {
+ // No free connection listeners
+ if (cls.size() == 0)
+ break;
+
+ // We always check the first connection listener, since it is the oldest
+ ConnectionListener cl = cls.get(0);
+
+ destroy = decrementer.shouldDestroy(cl, timeout,
+ cls.size() + checkedOut.size(),
+ poolConfiguration.getMinSize(),
+ destroyed);
+
+ if (destroy)
+ {
+ if (shouldRemove() || !isRunning())
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTimedOut();
+
+ log.tracef("Idle connection cl=%s", cl);
+
+ // We need to destroy this one
+ cls.remove(0);
+ destroyConnections.add(cl);
+ destroyed++;
+ }
+ else
+ {
+ destroy = false;
+ }
+ }
+ }
+ }
+
+ // We found some connections to destroy
+ if (destroyConnections.size() > 0 || isEmpty())
+ {
+ for (ConnectionListener cl : destroyConnections)
+ {
+ log.tracef("Destroying connection %s", cl);
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ cl.getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, true, false, false, false,
+ false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ cl = null;
+ }
+
+ if (isRunning())
+ {
+ // Let prefill and use-strict-min be the same
+ boolean emptyManagedConnectionPool = false;
+
+ if ((poolConfiguration.isPrefill() || poolConfiguration.isStrictMin()) && pool instanceof PrefillPool)
+ {
+ if (poolConfiguration.getMinSize() > 0)
+ {
+ prefill();
+ }
+ else
+ {
+ emptyManagedConnectionPool = true;
+ }
+ }
+ else
+ {
+ emptyManagedConnectionPool = true;
+ }
+
+ // Empty pool
+ if (emptyManagedConnectionPool && isEmpty())
+ pool.emptyManagedConnectionPool(this);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void shutdown()
+ {
+ final Collection toDestroy;
+ synchronized (this)
+ {
+ if (log.isTraceEnabled())
+ log.tracef("Shutdown - Pool: %s MCP: %s", pool.getName(), Integer.toHexString(System.identityHashCode(
+ this)));
+
+ IdleRemover.getInstance().unregisterPool(this);
+ ConnectionValidator.getInstance().unregisterPool(this);
+
+ if (checkedOut.size() > 0)
+ {
+ for (ConnectionListener cl : checkedOut)
+ {
+ log.destroyingActiveConnection(pool.getName(), cl.getManagedConnection());
+
+ if (Tracer.isEnabled())
+ Tracer.clearConnectionListener(pool.getName(), this, cl);
+ }
+ }
+
+ toDestroy = new ArrayList();
+ flush(FlushMode.ALL, toDestroy);
+ }
+ for (ConnectionListener cl : toDestroy)
+ {
+ cl.destroy();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void fillTo(int size)
+ {
+ if (size <= 0)
+ return;
+
+ if (!(poolConfiguration.isPrefill() || poolConfiguration.isStrictMin()))
+ return;
+
+ if (!(pool instanceof PrefillPool))
+ return;
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "fillTo(" + size + ")";
+ log.trace(ManagedConnectionPoolUtility.fullDetails(this, method,
+ mcf, cm, pool, poolConfiguration,
+ cls, checkedOut, pool.getInternalStatistics(),
+ defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "fillTo(" + size + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ while (!pool.isFull())
+ {
+ // Get a permit - avoids a race when the pool is nearly full
+ // Also avoids unnessary fill checking when all connections are checked out
+ try
+ {
+ long startWait = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalBlockingTime(System.currentTimeMillis() - startWait);
+ try
+ {
+ if (!isRunning())
+ {
+ return;
+ }
+
+ // We already have enough connections
+ if (isSize(size))
+ {
+ return;
+ }
+
+ // Create a connection to fill the pool
+ try
+ {
+ ConnectionListener cl = createConnectionEventListener(defaultSubject, defaultCri);
+
+ if (Tracer.isEnabled())
+ Tracer.createConnectionListener(pool.getName(), this, cl, cl.getManagedConnection(),
+ false, true, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ boolean added = false;
+ synchronized (cls)
+ {
+ if (!isSize(size))
+ {
+ log.tracef("Filling pool cl=%s", cl);
+
+ cls.add(cl);
+ added = true;
+ }
+ }
+
+ if (!added)
+ {
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, false, false,
+ false, true, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ return;
+ }
+ }
+ catch (ResourceException re)
+ {
+ log.unableFillPool(re, cm.getJndiName());
+ return;
+ }
+ }
+ finally
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+ catch (InterruptedException ignored)
+ {
+ Thread.interrupted();
+
+ log.trace("Interrupted while requesting permit in fillTo");
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void increaseCapacity(Subject subject, ConnectionRequestInfo cri)
+ {
+ // We have already created one connection when this method is scheduled
+ int created = 1;
+ boolean create = true;
+
+ while (create && !pool.isFull())
+ {
+ try
+ {
+ long startWait = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalBlockingTime(System.currentTimeMillis() - startWait);
+ try
+ {
+ if (!isRunning())
+ {
+ return;
+ }
+
+ int currentSize = 0;
+ synchronized (cls)
+ {
+ currentSize = cls.size() + checkedOut.size();
+ }
+
+ create = pool.getCapacity().getIncrementer().shouldCreate(currentSize,
+ poolConfiguration.getMaxSize(), created);
+
+ if (create)
+ {
+ try
+ {
+ ConnectionListener cl = createConnectionEventListener(subject, cri);
+
+ if (Tracer.isEnabled())
+ Tracer.createConnectionListener(pool.getName(), this, cl, cl.getManagedConnection(),
+ false, false, true,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ boolean added = false;
+ synchronized (cls)
+ {
+ if (!isSize(poolConfiguration.getMaxSize()))
+ {
+ log.tracef("Capacity fill: cl=%s", cl);
+
+ cls.add(cl);
+ created++;
+ added = true;
+ }
+ }
+
+ if (!added)
+ {
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, true, false,
+ false, false, true,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ return;
+ }
+ }
+ catch (ResourceException re)
+ {
+ log.unableFillPool(re, cm.getJndiName());
+ return;
+ }
+ }
+ }
+ finally
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+ catch (InterruptedException ignored)
+ {
+ Thread.interrupted();
+
+ log.trace("Interrupted while requesting permit in increaseCapacity");
+ }
+ }
+ }
+
+ /**
+ * Create a connection event listener
+ *
+ * @param subject the subject
+ * @param cri the connection request information
+ * @return the new listener
+ * @throws ResourceException for any error
+ */
+ private ConnectionListener createConnectionEventListener(Subject subject, ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ long start = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+
+ ManagedConnection mc = mcf.createManagedConnection(subject, cri);
+
+ if (pool.getInternalStatistics().isEnabled())
+ {
+ pool.getInternalStatistics().deltaTotalCreationTime(System.currentTimeMillis() - start);
+ pool.getInternalStatistics().deltaCreatedCount();
+ }
+ try
+ {
+ return cm.createConnectionListener(mc, this);
+ }
+ catch (ResourceException re)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaDestroyedCount();
+ mc.destroy();
+ throw re;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void connectionListenerDestroyed(ConnectionListener cl)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaDestroyedCount();
+ }
+
+ /**
+ * Should any connections be removed from the pool
+ * @return True if connections should be removed; otherwise false
+ */
+ private boolean shouldRemove()
+ {
+ boolean remove = true;
+
+ if (poolConfiguration.isStrictMin() && pool instanceof PrefillPool)
+ {
+ // Add 1 to min-pool-size since it is strict
+ remove = isSize(poolConfiguration.getMinSize() + 1);
+
+ log.tracef("StrictMin is active. Current connection will be removed is %b", remove);
+ }
+
+ return remove;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validateConnections() throws Exception
+ {
+
+ if (log.isTraceEnabled())
+ {
+ log.tracef("Attempting to validate connections for pool %s", this);
+ synchronized (cls)
+ {
+ String method = "validateConnections()";
+ log.trace(ManagedConnectionPoolUtility.fullDetails(this, method,
+ mcf, cm, pool, poolConfiguration,
+ cls, checkedOut, pool.getInternalStatistics(),
+ defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "validateConnections()";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ boolean anyDestroyed = false;
+
+ try
+ {
+ while (true)
+ {
+ ConnectionListener cl = null;
+ boolean destroyed = false;
+
+ synchronized (cls)
+ {
+ if (cls.size() == 0)
+ {
+ break;
+ }
+
+ cl = removeForFrequencyCheck();
+ }
+
+ if (cl == null)
+ {
+ break;
+ }
+
+ try
+ {
+ Set candidateSet = Collections.singleton(cl.getManagedConnection());
+
+ if (mcf instanceof ValidatingManagedConnectionFactory)
+ {
+ ValidatingManagedConnectionFactory vcf = (ValidatingManagedConnectionFactory) mcf;
+ candidateSet = vcf.getInvalidConnections(candidateSet);
+
+ if ((candidateSet != null && candidateSet.size() > 0) || !isRunning())
+ {
+ if (cl.getState() != ConnectionState.DESTROY)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ cl.getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, true,
+ false, false, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ cl = null;
+ destroyed = true;
+ anyDestroyed = true;
+ }
+ }
+ }
+ else
+ {
+ log.backgroundValidationNonCompliantManagedConnectionFactory();
+ }
+ }
+ catch (ResourceException re)
+ {
+ if (cl != null)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ cl.getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, false,
+ false, true, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ cl.destroy();
+ cl = null;
+ destroyed = true;
+ anyDestroyed = true;
+ }
+
+ log.connectionValidatorIgnoredUnexpectedError(re);
+ }
+ finally
+ {
+ if (!destroyed)
+ {
+ synchronized (cls)
+ {
+ returnForFrequencyCheck(cl);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ pool.getLock().release();
+
+ if (anyDestroyed)
+ prefill();
+ }
+ }
+ }
+
+ /**
+ * Get the pool name
+ * @return The value
+ */
+ String getPoolName()
+ {
+ if (pool == null)
+ return "";
+
+ return pool.getName();
+ }
+
+ /**
+ * Returns the connection listener that should be removed due to background validation
+ * @return The listener; otherwise null if none should be removed
+ */
+ private ConnectionListener removeForFrequencyCheck()
+ {
+ ConnectionListener cl = null;
+
+ for (Iterator iter = cls.iterator(); iter.hasNext();)
+ {
+ cl = iter.next();
+ long lastCheck = cl.getLastValidatedTime();
+
+ if ((System.currentTimeMillis() - lastCheck) >= poolConfiguration.getBackgroundValidationMillis())
+ {
+ cls.remove(cl);
+ break;
+ }
+ else
+ {
+ cl = null;
+ }
+ }
+
+ if (debug)
+ log.debugf("Checking for connection within frequency: %s", cl);
+
+ return cl;
+ }
+
+ /**
+ * Return a connection listener to the pool and update its validation timestamp
+ * @param cl The listener
+ */
+ private void returnForFrequencyCheck(ConnectionListener cl)
+ {
+ if (debug)
+ log.debugf("Returning for connection within frequency: %s", cl);
+
+ cl.setLastValidatedTime(System.currentTimeMillis());
+ cls.add(cl);
+ }
+
+ /**
+ * Check if the resource adapter supports lazy association
+ */
+ private void checkLazyAssociation()
+ {
+ synchronized (cls)
+ {
+ ConnectionListener cl = null;
+
+ if (checkedOut.size() > 0)
+ cl = checkedOut.get(0);
+
+ if (cl == null && cls.size() > 0)
+ cl = cls.get(0);
+
+ if (cl != null)
+ {
+ if (cl.supportsLazyAssociation())
+ {
+ if (debug)
+ log.debug("Enable lazy association support for: " + pool.getName());
+
+ supportsLazyAssociation = Boolean.TRUE;
+ }
+ else
+ {
+ if (debug)
+ log.debug("Disable lazy association support for: " + pool.getName());
+
+ supportsLazyAssociation = Boolean.FALSE;
+ }
+ }
+ }
+ }
+
+ /**
+ * Detach connection listener
+ * @return The outcome
+ */
+ private boolean detachConnectionListener()
+ {
+ synchronized (cls)
+ {
+ ConnectionListener cl = null;
+ try
+ {
+ Iterator it = checkedOut.iterator();
+ while (it.hasNext())
+ {
+ cl = it.next();
+ if (!cl.isEnlisted() && cl.getManagedConnection() instanceof DissociatableManagedConnection)
+ {
+ log.tracef("Detach: %s", cl);
+
+ DissociatableManagedConnection dmc = (DissociatableManagedConnection)cl.getManagedConnection();
+ dmc.dissociateConnections();
+
+ cl.unregisterConnections();
+
+ if (Tracer.isEnabled())
+ Tracer.returnConnectionListener(pool.getName(), this, cl, false, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ returnConnection(cl, false, false);
+
+ return true;
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ // Ok - didn't work; nuke it and disable
+ if (debug)
+ log.debug("Exception during detach for: " + pool.getName(), t);
+
+ supportsLazyAssociation = Boolean.FALSE;
+
+ if (cl != null)
+ {
+ if (Tracer.isEnabled())
+ Tracer.returnConnectionListener(pool.getName(), this, cl, true, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ returnConnection(cl, true, true);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * String representation
+ * @return The string
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("SemaphoreArrayListManagedConnectionPool@").append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append("[pool=").append(pool.getName());
+ sb.append("]");
+
+ return sb.toString();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SemaphoreConcurrentLinkedDequeManagedConnectionPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SemaphoreConcurrentLinkedDequeManagedConnectionPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/SemaphoreConcurrentLinkedDequeManagedConnectionPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,1788 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2015, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.mcp;
+
+import org.jboss.jca.core.CoreBundle;
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.FlushMode;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionState;
+import org.jboss.jca.core.connectionmanager.pool.api.CapacityDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.api.Pool;
+import org.jboss.jca.core.connectionmanager.pool.api.PrefillPool;
+import org.jboss.jca.core.connectionmanager.pool.capacity.DefaultCapacity;
+import org.jboss.jca.core.connectionmanager.pool.capacity.TimedOutDecrementer;
+import org.jboss.jca.core.connectionmanager.pool.capacity.TimedOutFIFODecrementer;
+import org.jboss.jca.core.connectionmanager.pool.idle.IdleRemover;
+import org.jboss.jca.core.connectionmanager.pool.validator.ConnectionValidator;
+import org.jboss.jca.core.tracer.Tracer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.DissociatableManagedConnection;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.RetryableException;
+import javax.resource.spi.ValidatingManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Messages;
+
+/**
+ * ManagedConnectionPool implementation based on a semaphore and ConcurrentLinkedDeque
+ *
+ * @author John O'Hara
+ * @author Jesper Pedersen
+ */
+public class SemaphoreConcurrentLinkedDequeManagedConnectionPool implements ManagedConnectionPool
+{
+ /** The log */
+ private CoreLogger log;
+
+ /** Whether debug is enabled */
+ private boolean debug;
+
+ /** The bundle */
+ private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
+
+ /** The managed connection factory */
+ private ManagedConnectionFactory mcf;
+
+ /** The connection manager */
+ private ConnectionManager cm;
+
+ /** The default subject */
+ private Subject defaultSubject;
+
+ /** The default connection request information */
+ private ConnectionRequestInfo defaultCri;
+
+ /** The pool configuration */
+ private PoolConfiguration poolConfiguration;
+
+ /** The pool */
+ private Pool pool;
+
+ /** FIFO / FILO */
+ private boolean fifo;
+
+ /**
+ * Copy of the maximum size from the pooling parameters. Dynamic changes to
+ * this value are not compatible with the semaphore which cannot change be
+ * dynamically changed.
+ */
+ private int maxSize;
+
+ /** The available connection event listeners */
+ private ConcurrentLinkedDeque clq;
+
+ /** all connection event listeners */
+ private Map cls;
+
+ /** Current pool size **/
+ private AtomicInteger poolSize = new AtomicInteger();
+
+ /** Current checked out connections **/
+ private AtomicInteger checkedOutSize = new AtomicInteger();
+
+ /** Supports lazy association */
+ private Boolean supportsLazyAssociation;
+
+ /** Last idle check */
+ private long lastIdleCheck;
+
+ /** Last used */
+ private long lastUsed;
+
+ /**
+ * Constructor
+ */
+ public SemaphoreConcurrentLinkedDequeManagedConnectionPool()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initialize(ManagedConnectionFactory mcf, ConnectionManager cm, Subject subject,
+ ConnectionRequestInfo cri, PoolConfiguration pc, Pool p)
+ {
+ if (mcf == null)
+ throw new IllegalArgumentException("ManagedConnectionFactory is null");
+
+ if (cm == null)
+ throw new IllegalArgumentException("ConnectionManager is null");
+
+ if (pc == null)
+ throw new IllegalArgumentException("PoolConfiguration is null");
+
+ if (p == null)
+ throw new IllegalArgumentException("Pool is null");
+
+ this.mcf = mcf;
+ this.cm = cm;
+ this.defaultSubject = subject;
+ this.defaultCri = cri;
+ this.poolConfiguration = pc;
+ this.maxSize = pc.getMaxSize();
+ this.pool = p;
+ this.fifo = p.isFIFO();
+ this.log = pool.getLogger();
+ this.debug = log.isDebugEnabled();
+ this.clq = new ConcurrentLinkedDeque();
+ this.cls = new ConcurrentHashMap();
+ this.poolSize.set(0);
+ this.checkedOutSize.set(0);
+ this.supportsLazyAssociation = null;
+ this.lastIdleCheck = System.currentTimeMillis();
+ this.lastUsed = Long.MAX_VALUE;
+
+ // Schedule managed connection pool for prefill
+ if ((pc.isPrefill() || pc.isStrictMin()) && p instanceof PrefillPool && pc.getInitialSize() > 0)
+ {
+ PoolFiller.fillPool(new FillRequest(this, pc.getInitialSize()));
+ }
+
+ if (poolConfiguration.getIdleTimeoutMinutes() > 0)
+ {
+ // Register removal support
+ IdleRemover.getInstance().registerPool(this,
+ poolConfiguration.getIdleTimeoutMinutes() * 1000L * 60);
+ }
+
+ if (poolConfiguration.isBackgroundValidation() && poolConfiguration.getBackgroundValidationMillis() > 0)
+ {
+ if (debug)
+ log.debug("Registering for background validation at interval " +
+ poolConfiguration.getBackgroundValidationMillis());
+
+ // Register validation
+ ConnectionValidator.getInstance().registerPool(this,
+ poolConfiguration.getBackgroundValidationMillis());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastUsed()
+ {
+ return lastUsed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRunning()
+ {
+ return !pool.isShutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty()
+ {
+ return poolSize.get() == 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isIdle()
+ {
+ return checkedOutSize.get() == 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getActive()
+ {
+ return poolSize.get();
+ }
+
+ /**
+ * Check if the pool has reached a certain size
+ *
+ * @param size The size
+ * @return True if reached; otherwise false
+ */
+ private boolean isSize(int size)
+ {
+ return poolSize.get() >= size;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void prefill()
+ {
+ if (isRunning() &&
+ (poolConfiguration.isPrefill() || poolConfiguration.isStrictMin()) &&
+ pool instanceof PrefillPool &&
+ poolConfiguration.getMinSize() > 0)
+ PoolFiller.fillPool(new FillRequest(this, poolConfiguration.getMinSize()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener getConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException
+ {
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "getConnection(" + subject + ", " + cri + ")";
+ SortedSet checkedOut = new TreeSet();
+ SortedSet available = new TreeSet();
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ checkedOut.add(entry.getKey());
+ else
+ available.add(entry.getKey());
+ }
+ log.trace(ManagedConnectionPoolUtility.fullDetails(this, method, mcf, cm, pool,
+ poolConfiguration, available, checkedOut,
+ pool.getInternalStatistics(), subject, cri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "getConnection(" + subject + ", " + cri + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ subject = (subject == null) ? defaultSubject : subject;
+ cri = (cri == null) ? defaultCri : cri;
+
+ if (pool.isFull())
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaWaitCount();
+
+ if (pool.isSharable() && (supportsLazyAssociation == null || supportsLazyAssociation.booleanValue()))
+ {
+ if (supportsLazyAssociation == null)
+ checkLazyAssociation();
+
+ if (supportsLazyAssociation != null && supportsLazyAssociation.booleanValue())
+ {
+ if (log.isTraceEnabled())
+ log.tracef("Trying to detach - Pool: %s MCP: %s", pool.getName(),
+ Integer.toHexString(System.identityHashCode(this)));
+
+ if (!detachConnectionListener())
+ {
+ if (log.isTraceEnabled())
+ log.tracef("Detaching didn't succeed - Pool: %s MCP: %s", pool.getName(),
+ Integer.toHexString(System.identityHashCode(this)));
+ }
+ }
+ }
+ }
+
+ long startWait = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+ try
+ {
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalBlockingTime(System.currentTimeMillis() - startWait);
+
+ // We have a permit to get a connection. Is there one in the pool already?
+ ConnectionListenerWrapper clw = null;
+ do
+ {
+ if (!isRunning())
+ {
+ pool.getLock().release();
+
+ throw new ResourceException(
+ bundle.thePoolHasBeenShutdown(pool.getName(),
+ Integer.toHexString(System.identityHashCode(this))));
+ }
+
+ if (fifo)
+ {
+ clw = clq.pollFirst();
+ }
+ else
+ {
+ clw = clq.pollLast();
+ }
+
+ if (clw != null)
+ {
+ clw.setCheckedOut(true);
+ checkedOutSize.incrementAndGet();
+
+ // Yes, we retrieved a ManagedConnection from the pool.
+ // Does it match?
+ try
+ {
+ Object matchedMC = mcf.matchManagedConnections(Collections.singleton(
+ clw.getConnectionListener().getManagedConnection()), subject, cri);
+
+ boolean valid = true;
+
+ if (matchedMC != null)
+ {
+ if (poolConfiguration.isValidateOnMatch())
+ {
+ if (mcf instanceof ValidatingManagedConnectionFactory)
+ {
+ try
+ {
+ ValidatingManagedConnectionFactory vcf = (ValidatingManagedConnectionFactory) mcf;
+ Set candidateSet =
+ Collections.singleton(clw.getConnectionListener().getManagedConnection());
+ candidateSet = vcf.getInvalidConnections(candidateSet);
+
+ if (candidateSet != null && candidateSet.size() > 0)
+ {
+ valid = false;
+ }
+ }
+ catch (Throwable t)
+ {
+ valid = false;
+ if (log.isTraceEnabled())
+ log.trace("Exception while ValidateOnMatch: " + t.getMessage(), t);
+ }
+ }
+ else
+ {
+ log.validateOnMatchNonCompliantManagedConnectionFactory(mcf.getClass().getName());
+ }
+ }
+
+ if (valid)
+ {
+ log.tracef("supplying ManagedConnection from pool: %s", clw.getConnectionListener());
+
+ lastUsed = System.currentTimeMillis();
+ clw.getConnectionListener().setLastCheckedOutTime(lastUsed);
+
+ if (pool.getInternalStatistics().isEnabled())
+ {
+ pool.getInternalStatistics().deltaTotalGetTime(lastUsed - startWait);
+ pool.getInternalStatistics().deltaTotalPoolTime(lastUsed -
+ clw.getConnectionListener().getLastReturnedTime());
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.getConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ true, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ clw.setHasPermit(true);
+
+ return clw.getConnectionListener();
+ }
+ }
+
+ // Match did not succeed but no exception was
+ // thrown.
+ // Either we have the matching strategy wrong or the
+ // connection died while being checked. We need to
+ // distinguish these cases, but for now we always
+ // destroy the connection.
+ if (valid)
+ {
+ log.destroyingConnectionNotSuccessfullyMatched(clw.getConnectionListener());
+ }
+ else
+ {
+ log.destroyingConnectionNotValidated(clw.getConnectionListener());
+ }
+
+ if (pool.getInternalStatistics().isEnabled())
+ {
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ clw.getConnectionListener().getLastReturnedTime());
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ false, false, true, false, false, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ clw = null;
+ }
+ catch (Throwable t)
+ {
+ log.throwableWhileTryingMatchManagedConnectionThenDestroyingConnection(
+ clw.getConnectionListener(), t);
+
+ if (pool.getInternalStatistics().isEnabled())
+ {
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ clw.getConnectionListener().getLastReturnedTime());
+ }
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ false, false, false, false, true, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ clw = null;
+ }
+
+ // We made it here, something went wrong and we should
+ // validate
+ // if we should continue attempting to acquire a
+ // connection
+ if (poolConfiguration.isUseFastFail())
+ {
+ if (log.isTraceEnabled())
+ log.trace("Fast failing for connection attempt. No more attempts will be made to "
+ + "acquire connection from pool and a new connection will be created immeadiately");
+ break;
+ }
+
+ }
+ }
+ while (clq.size() > 0);
+
+ // OK, we couldnt find a working connection from the pool. Make
+ // a new one.
+ try
+ {
+ // No, the pool was empty, so we have to make a new one.
+ clw = new ConnectionListenerWrapper(createConnectionEventListener(subject, cri), true, true);
+
+ if (Tracer.isEnabled())
+ Tracer.createConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ clw.getConnectionListener().getManagedConnection(),
+ true, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ clw.setCheckedOut(true);
+ checkedOutSize.incrementAndGet();
+
+ cls.put(clw.getConnectionListener(), clw);
+
+ log.tracef("supplying new ManagedConnection: %s", clw.getConnectionListener());
+
+ lastUsed = System.currentTimeMillis();
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalGetTime(lastUsed - startWait);
+
+ prefill();
+
+ // Trigger capacity increase
+ if (pool.getCapacity().getIncrementer() != null)
+ CapacityFiller.schedule(new CapacityRequest(this, subject, cri));
+
+ if (Tracer.isEnabled())
+ Tracer.getConnectionListener(pool.getName(), this, clw.getConnectionListener(), false,
+ pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ return clw.getConnectionListener();
+ }
+ catch (Throwable t)
+ {
+ if (clw != null || !(t instanceof RetryableException))
+ log.throwableWhileAttemptingGetNewGonnection(clw != null ? clw.getConnectionListener() : null, t);
+
+ // Return permit and rethrow
+ if (clw != null)
+ {
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ false, false, false, false, true, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ }
+
+ pool.getLock().release();
+
+ if (t instanceof ResourceException)
+ {
+ throw (ResourceException)t;
+ }
+ else
+ {
+ throw new ResourceException(
+ bundle.unexpectedThrowableWhileTryingCreateConnection(
+ clw != null ? clw.getConnectionListener() : null), t);
+ }
+ }
+ }
+ else
+ {
+ // We timed out
+ throw new ResourceException(
+ bundle.noMManagedConnectionsAvailableWithinConfiguredBlockingTimeout(
+ poolConfiguration.getBlockingTimeout()));
+ }
+
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.interrupted();
+
+ long end = pool.getInternalStatistics().isEnabled() ? (System.currentTimeMillis() - startWait) : 0L;
+ pool.getInternalStatistics().deltaTotalBlockingTime(end);
+ throw new ResourceException(bundle.interruptedWhileRequestingPermit(end));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc)
+ {
+ return findConnectionListener(mc, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener findConnectionListener(ManagedConnection mc, Object connection)
+ {
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut() && entry.getKey().controls(mc, connection))
+ return entry.getKey();
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill)
+ {
+ returnConnection(cl, kill, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void returnConnection(ConnectionListener cl, boolean kill, boolean cleanup)
+ {
+ if (pool.getInternalStatistics().isEnabled() && cl.getState() != ConnectionState.DESTROYED)
+ pool.getInternalStatistics().deltaTotalUsageTime(System.currentTimeMillis() - cl.getLastCheckedOutTime());
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "returnConnection(" + Integer.toHexString(System.identityHashCode(cl)) + ", " + kill + ")";
+ SortedSet checkedOut = new TreeSet();
+ SortedSet available = new TreeSet();
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ checkedOut.add(entry.getKey());
+ else
+ available.add(entry.getKey());
+ }
+ log.trace(ManagedConnectionPoolUtility.fullDetails(
+ this, method, mcf, cm, pool,
+ poolConfiguration, available, checkedOut, pool.getInternalStatistics(), defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "returnConnection(" + Integer.toHexString(System.identityHashCode(cl)) + ", " + kill + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method,
+ pool.getName(), pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ ConnectionListenerWrapper clw = cls.get(cl);
+ if (cl.getState() == ConnectionState.DESTROYED)
+ {
+ log.tracef("ManagedConnection is being returned after it was destroyed: %s", cl);
+
+ if (clw != null && clw.hasPermit())
+ {
+ clw.setHasPermit(false);
+ pool.getLock().release();
+ }
+
+ return;
+ }
+
+ if (cleanup)
+ {
+ try
+ {
+ cl.getManagedConnection().cleanup();
+ }
+ catch (ResourceException re)
+ {
+ log.resourceExceptionCleaningUpManagedConnection(cl, re);
+ kill = true;
+ }
+ }
+
+ // We need to destroy this one
+ if (clw == null || cl.getState() == ConnectionState.DESTROY || cl.getState() == ConnectionState.DESTROYED)
+ kill = true;
+
+ // This is really an error
+ if (!kill && isSize(poolConfiguration.getMaxSize() + 1))
+ {
+ log.destroyingReturnedConnectionMaximumPoolSizeExceeded(cl);
+ kill = true;
+ }
+
+ boolean releasePermit = false;
+ if (clw != null)
+ {
+ if (clw.hasPermit())
+ {
+ clw.setHasPermit(false);
+ releasePermit = true;
+ }
+ if (clw.isCheckedOut())
+ {
+ clw.setCheckedOut(false);
+ checkedOutSize.decrementAndGet();
+ }
+ }
+
+ // If we are destroying, check the connection is not in the pool
+ if (kill)
+ {
+ // Adrian Brock: A resource adapter can asynchronously notify us
+ // that a connection error occurred.
+ // This could happen while the connection is not checked out.
+ // e.g. JMS can do this via an ExceptionListener on the connection.
+ // I have twice had to reinstate this line of code, PLEASE DO NOT
+ // REMOVE IT!
+ cls.remove(cl);
+ }
+ // return to the pool
+ else
+ {
+ cl.toPool();
+ if (!clq.contains(clw))
+ {
+ clq.addLast(clw);
+ }
+ else
+ {
+ log.attemptReturnConnectionTwice(cl, new Throwable("STACKTRACE"));
+ }
+ }
+
+ if (kill)
+ {
+ log.tracef("Destroying returned connection %s", cl);
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl,
+ true, false, false, false, false, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ cl.destroy();
+ }
+
+ if (releasePermit)
+ {
+ pool.getLock().release();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void flush(FlushMode mode, Collection toDestroy)
+ {
+ ArrayList destroy = null;
+
+ synchronized (cls)
+ {
+ if (FlushMode.ALL == mode)
+ {
+ if (log.isTraceEnabled())
+ {
+ SortedSet checkedOut = new TreeSet();
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ checkedOut.add(entry.getKey());
+ }
+ log.tracef("Flushing pool checkedOut=%s inPool=%s", checkedOut , cls);
+ }
+
+ // Mark checked out connections as requiring destruction
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ {
+ log.tracef("Flush marking checked out connection for destruction %s", entry.getKey());
+
+ entry.getValue().setCheckedOut(false);
+ checkedOutSize.decrementAndGet();
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalUsageTime(System.currentTimeMillis() -
+ entry.getKey().getLastCheckedOutTime());
+
+ if (entry.getValue().hasPermit())
+ {
+ entry.getValue().setHasPermit(false);
+ pool.getLock().release();
+ }
+
+ entry.getKey().setState(ConnectionState.DESTROY);
+
+ if (destroy == null)
+ destroy = new ArrayList(1);
+
+ destroy.add(entry.getValue());
+
+ clq.remove(entry.getValue());
+ cls.remove(entry.getKey());
+ }
+ }
+ }
+ else if (FlushMode.GRACEFULLY == mode)
+ {
+ if (log.isTraceEnabled())
+ {
+ SortedSet checkedOut = new TreeSet();
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ checkedOut.add(entry.getKey());
+ }
+ log.tracef("Gracefully flushing pool checkedOut=%s inPool=%s", checkedOut , cls);
+ }
+
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ {
+ log.tracef("Graceful flush marking checked out connection for destruction %s", entry.getKey());
+
+ entry.getKey().setState(ConnectionState.DESTROY);
+ }
+ }
+
+ }
+
+ // Destroy connections in the pool
+ Iterator clqIter = clq.iterator();
+ while (clqIter.hasNext())
+ {
+ ConnectionListenerWrapper clw = clqIter.next();
+ boolean kill = true;
+
+ if (FlushMode.INVALID == mode && clw.getConnectionListener().getState().equals(ConnectionState.NORMAL))
+ {
+ if (mcf instanceof ValidatingManagedConnectionFactory)
+ {
+ try
+ {
+ ValidatingManagedConnectionFactory vcf = (ValidatingManagedConnectionFactory) mcf;
+ Set candidateSet = Collections.singleton(clw.getConnectionListener().getManagedConnection());
+ candidateSet = vcf.getInvalidConnections(candidateSet);
+
+ if (candidateSet == null || candidateSet.size() == 0)
+ {
+ kill = false;
+ }
+ }
+ catch (Throwable t)
+ {
+ log.trace("Exception during invalid flush", t);
+ }
+ }
+ }
+
+ if (kill)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ clw.getConnectionListener().getLastReturnedTime());
+
+ clq.remove(clw);
+ cls.remove(clw.getConnectionListener());
+
+ if (destroy == null)
+ destroy = new ArrayList(1);
+
+ clw.getConnectionListener().setState(ConnectionState.DESTROY);
+ destroy.add(clw);
+ }
+
+ }
+ }
+
+ // We need to destroy some connections
+ if (destroy != null)
+ {
+ for (ConnectionListenerWrapper clw : destroy)
+ {
+ removeConnectionListenerFromPool(clw);
+ toDestroy.add(clw.getConnectionListener());
+ clw = null;
+ }
+ }
+
+ // Trigger prefill
+ prefill();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeIdleConnections()
+ {
+ long now = System.currentTimeMillis();
+ long timeoutSetting = poolConfiguration.getIdleTimeoutMinutes() * 1000L * 60;
+
+ CapacityDecrementer decrementer = pool.getCapacity().getDecrementer();
+
+ if (decrementer == null)
+ decrementer = DefaultCapacity.DEFAULT_DECREMENTER;
+
+ if (TimedOutDecrementer.class.getName().equals(decrementer.getClass().getName()) ||
+ TimedOutFIFODecrementer.class.getName().equals(decrementer.getClass().getName()))
+ {
+ // Allow through each minute
+ if (now < (lastIdleCheck + 60000L))
+ return;
+ }
+ else
+ {
+ // Otherwise, strict check
+ if (now < (lastIdleCheck + timeoutSetting))
+ return;
+ }
+
+ lastIdleCheck = now;
+
+ ArrayList destroyConnections = new ArrayList();
+ long timeout = now - timeoutSetting;
+
+ boolean destroy = true;
+ int destroyed = 0;
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "removeIdleConnections(" + timeout + ")";
+ SortedSet checkedOut = new TreeSet();
+ SortedSet available = new TreeSet();
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ checkedOut.add(entry.getKey());
+ else
+ available.add(entry.getKey());
+ }
+ log.trace(ManagedConnectionPoolUtility.fullDetails(
+ this, method, mcf, cm, pool,
+ poolConfiguration, available, checkedOut, pool.getInternalStatistics(), defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "removeIdleConnections(" + timeout + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ Iterator clwIter = clq.iterator();
+ while (clwIter.hasNext() && destroy)
+ {
+ // Nothing left to destroy
+ if (clq.size() == 0)
+ break;
+
+ ConnectionListenerWrapper clw = clwIter.next();
+
+ destroy = decrementer.shouldDestroy(clw.getConnectionListener(),
+ timeout, poolSize.get() - destroyed,
+ poolConfiguration.getMinSize(), destroyed);
+
+ if (destroy)
+ {
+ if (shouldRemove() || !isRunning())
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTimedOut();
+
+ log.tracef("Idle connection cl=%s", clw.getConnectionListener());
+
+ // We need to destroy this one, so deregister now
+ if (cls.remove(clw.getConnectionListener()) == null)
+ log.tracef("Connection Pool did not contain: %s", clw.getConnectionListener());
+
+ if (!clq.remove(clw))
+ log.tracef("Available connection queue did not contain: %s", clw.getConnectionListener());
+
+ destroyConnections.add(clw);
+ destroyed++;
+ }
+ else
+ {
+ destroy = false;
+ }
+ }
+ }
+
+ // We found some connections to destroy
+ if (destroyConnections.size() > 0 || isEmpty())
+ {
+ for (ConnectionListenerWrapper clw : destroyConnections)
+ {
+ log.tracef("Destroying connection %s", clw.getConnectionListener());
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ clw.getConnectionListener().getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ false, true, false, false, false, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ clw = null;
+ }
+
+ if (isRunning())
+ {
+ // Let prefill and use-strict-min be the same
+ boolean emptyManagedConnectionPool = false;
+
+ if ((poolConfiguration.isPrefill() || poolConfiguration.isStrictMin()) && pool instanceof PrefillPool)
+ {
+ if (poolConfiguration.getMinSize() > 0)
+ {
+ prefill();
+ }
+ else
+ {
+ emptyManagedConnectionPool = true;
+ }
+ }
+ else
+ {
+ emptyManagedConnectionPool = true;
+ }
+
+ // Empty pool
+ if (emptyManagedConnectionPool && isEmpty())
+ pool.emptyManagedConnectionPool(this);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void shutdown()
+ {
+ if (log.isTraceEnabled())
+ log.tracef("Shutdown - Pool: %s MCP: %s", pool.getName(), Integer.toHexString(System.identityHashCode(this)));
+
+ IdleRemover.getInstance().unregisterPool(this);
+ ConnectionValidator.getInstance().unregisterPool(this);
+
+ if (checkedOutSize.get() > 0)
+ {
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ log.destroyingActiveConnection(pool.getName(), entry.getKey().getManagedConnection());
+
+ if (Tracer.isEnabled())
+ Tracer.clearConnectionListener(pool.getName(), this, entry.getKey());
+
+ }
+ }
+
+ final Collection toDestroy = new ArrayList();
+ flush(FlushMode.ALL, toDestroy);
+ for (ConnectionListener cl : toDestroy)
+ {
+ cl.destroy();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void fillTo(int size)
+ {
+ if (size <= 0)
+ return;
+
+ if (!(poolConfiguration.isPrefill() || poolConfiguration.isStrictMin()))
+ return;
+
+ if (!(pool instanceof PrefillPool))
+ return;
+
+ if (log.isTraceEnabled())
+ {
+ synchronized (cls)
+ {
+ String method = "fillTo(" + size + ")";
+ SortedSet checkedOut = new TreeSet();
+ SortedSet available = new TreeSet();
+ for (Entry entry : cls.entrySet())
+ {
+ if (entry.getValue().isCheckedOut())
+ checkedOut.add(entry.getKey());
+ else
+ available.add(entry.getKey());
+ }
+ log.trace(ManagedConnectionPoolUtility.fullDetails(
+ this, method, mcf, cm, pool,
+ poolConfiguration, available, checkedOut, pool.getInternalStatistics(), defaultSubject, defaultCri));
+ }
+ }
+ else if (debug)
+ {
+ String method = "fillTo(" + size + ")";
+ log.debug(ManagedConnectionPoolUtility.details(method, pool.getName(),
+ pool.getInternalStatistics().getInUseCount(), maxSize));
+ }
+
+ while (!pool.isFull())
+ {
+ // Get a permit - avoids a race when the pool is nearly full
+ // Also avoids unnessary fill checking when all connections are
+ // checked out
+ try
+ {
+ long startWait = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalBlockingTime(System.currentTimeMillis() - startWait);
+ try
+ {
+ if (!isRunning())
+ {
+ return;
+ }
+
+ // We already have enough connections
+ if (isSize(size))
+ {
+ return;
+ }
+
+ // Create a connection to fill the pool
+ try
+ {
+ ConnectionListener cl = createConnectionEventListener(defaultSubject, defaultCri);
+
+ if (Tracer.isEnabled())
+ Tracer.createConnectionListener(pool.getName(), this, cl, cl.getManagedConnection(),
+ false, true, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ boolean added = false;
+ // We have to add 1, since poolSize is already incremented
+ if (!isSize(size + 1))
+ {
+ log.tracef("Filling pool cl=%s", cl);
+
+ cls.put(cl, new ConnectionListenerWrapper(cl, false, false));
+ clq.addLast(cls.get(cl));
+ added = true;
+ }
+
+ if (!added)
+ {
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, false, false,
+ false, true, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ ConnectionListenerWrapper clw = new ConnectionListenerWrapper(cl, false, false);
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ return;
+ }
+ }
+ catch (ResourceException re)
+ {
+ log.unableFillPool(re, cm.getJndiName());
+ return;
+ }
+ }
+ finally
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+ catch (InterruptedException ignored)
+ {
+ Thread.interrupted();
+
+ log.trace("Interrupted while requesting permit in fillTo");
+ }
+ }
+ }
+
+ @Override
+ public void increaseCapacity(Subject subject, ConnectionRequestInfo cri)
+ {
+ // We have already created one connection when this method is scheduled
+ int created = 1;
+ boolean create = true;
+
+ while (create && !pool.isFull())
+ {
+ try
+ {
+ long startWait = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalBlockingTime(System.currentTimeMillis() - startWait);
+ try
+ {
+ if (!isRunning())
+ {
+ return;
+ }
+
+ create = pool.getCapacity().getIncrementer().shouldCreate(poolSize.get(),
+ poolConfiguration.getMaxSize(), created);
+
+ if (create)
+ {
+ try
+ {
+ ConnectionListener cl = createConnectionEventListener(subject, cri);
+
+ if (Tracer.isEnabled())
+ Tracer.createConnectionListener(pool.getName(), this, cl, cl.getManagedConnection(),
+ false, false, true,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ boolean added = false;
+ // We have to add 1, since poolSize is already incremented
+ if (!isSize(poolConfiguration.getMaxSize() + 1))
+ {
+ log.tracef("Capacity fill: cl=%s", cl);
+
+ cls.put(cl, new ConnectionListenerWrapper(cl, false, false));
+ clq.addLast(cls.get(cl));
+
+ created++;
+ added = true;
+ }
+
+ if (!added)
+ {
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, cl, false, false, true, false,
+ false, false, true,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ ConnectionListenerWrapper clw = new ConnectionListenerWrapper(cl, false, false);
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ return;
+ }
+ }
+ catch (ResourceException re)
+ {
+ log.unableFillPool(re, cm.getJndiName());
+ return;
+ }
+ }
+ }
+ finally
+ {
+ pool.getLock().release();
+ }
+ }
+ }
+ catch (InterruptedException ignored)
+ {
+ Thread.interrupted();
+
+ log.trace("Interrupted while requesting permit in increaseCapacity");
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addConnectionListener(ConnectionListener cl)
+ {
+ cls.put(cl, new ConnectionListenerWrapper(cl, false, false));
+ clq.addLast(cls.get(cl));
+ poolSize.incrementAndGet();
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaCreatedCount();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConnectionListener removeConnectionListener()
+ {
+ if (cls.size() > 0)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaDestroyedCount();
+ ConnectionListenerWrapper clw = clq.removeFirst();
+ if (cls.remove(clw.getConnectionListener()) != null)
+ poolSize.decrementAndGet();
+ return clw.getConnectionListener();
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a connection event listener
+ *
+ * @param subject
+ * the subject
+ * @param cri
+ * the connection request information
+ * @return the new listener
+ * @throws ResourceException
+ * for any error
+ */
+ private ConnectionListener createConnectionEventListener(Subject subject, ConnectionRequestInfo cri)
+ throws ResourceException
+ {
+ long start = pool.getInternalStatistics().isEnabled() ? System.currentTimeMillis() : 0L;
+
+ ManagedConnection mc = mcf.createManagedConnection(subject, cri);
+
+ if (pool.getInternalStatistics().isEnabled())
+ {
+ pool.getInternalStatistics().deltaTotalCreationTime(System.currentTimeMillis() - start);
+ pool.getInternalStatistics().deltaCreatedCount();
+ }
+ try
+ {
+ ConnectionListener cl = cm.createConnectionListener(mc, this);
+ poolSize.incrementAndGet();
+ return cl;
+ }
+ catch (ResourceException re)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaDestroyedCount();
+ mc.destroy();
+ throw re;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void connectionListenerDestroyed(ConnectionListener cl)
+ {
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaDestroyedCount();
+ }
+
+ /**
+ * Remove Connection Listener from pool and update counters and statistics
+ *
+ * Note, that the ConnectionListenerWrapper may already have been removed
+ * @param clw The wrapper
+ */
+ private void removeConnectionListenerFromPool(ConnectionListenerWrapper clw)
+ {
+ if (clw != null)
+ {
+ clq.remove(clw);
+ cls.remove(clw.getConnectionListener());
+
+ //update counter and statistics
+ if (clw.isCheckedOut())
+ {
+ clw.setCheckedOut(false);
+ checkedOutSize.decrementAndGet();
+ }
+ // update pool size
+ poolSize.decrementAndGet();
+ }
+ }
+
+ /**
+ * Should any connections be removed from the pool
+ *
+ * @return True if connections should be removed; otherwise false
+ */
+ private boolean shouldRemove()
+ {
+ boolean remove = true;
+
+ if (poolConfiguration.isStrictMin() && pool instanceof PrefillPool)
+ {
+ // Add 1 to min-pool-size since it is strict
+ remove = isSize(poolConfiguration.getMinSize() + 1);
+
+ log.tracef("StrictMin is active. Current connection will be removed is %b", remove);
+ }
+
+ return remove;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validateConnections() throws Exception
+ {
+
+ log.tracef("Attempting to validate connections for pool %s", this);
+
+ if (pool.getLock().tryAcquire(poolConfiguration.getBlockingTimeout(), TimeUnit.MILLISECONDS))
+ {
+ boolean anyDestroyed = false;
+
+ try
+ {
+ while (true)
+ {
+ ConnectionListener cl = null;
+ boolean destroyed = false;
+
+ synchronized (cls)
+ {
+ if (clq.size() == 0)
+ {
+ break;
+ }
+
+ cl = removeForFrequencyCheck();
+ }
+
+ if (cl == null)
+ {
+ break;
+ }
+
+ try
+ {
+ Set candidateSet = Collections.singleton(cl.getManagedConnection());
+
+ if (mcf instanceof ValidatingManagedConnectionFactory)
+ {
+ ValidatingManagedConnectionFactory vcf = (ValidatingManagedConnectionFactory) mcf;
+ candidateSet = vcf.getInvalidConnections(candidateSet);
+
+ if ((candidateSet != null && candidateSet.size() > 0) || !isRunning())
+ {
+ if (cl.getState() != ConnectionState.DESTROY)
+ {
+ ConnectionListenerWrapper clw = cls.remove(cl);
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ clw.getConnectionListener().getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ false, false, true, false, false, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ clw = null;
+ destroyed = true;
+ anyDestroyed = true;
+ }
+ }
+ }
+ else
+ {
+ log.backgroundValidationNonCompliantManagedConnectionFactory();
+ }
+ }
+ catch (ResourceException re)
+ {
+ if (cl != null)
+ {
+ ConnectionListenerWrapper clw = cls.remove(cl);
+
+ if (pool.getInternalStatistics().isEnabled())
+ pool.getInternalStatistics().deltaTotalPoolTime(System.currentTimeMillis() -
+ clw.getConnectionListener().getLastReturnedTime());
+
+ if (Tracer.isEnabled())
+ Tracer.destroyConnectionListener(pool.getName(), this, clw.getConnectionListener(),
+ false, false, false, false, true, false, false,
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ removeConnectionListenerFromPool(clw);
+ clw.getConnectionListener().destroy();
+ clw = null;
+ destroyed = true;
+ anyDestroyed = true;
+ }
+
+ log.connectionValidatorIgnoredUnexpectedError(re);
+ }
+ finally
+ {
+ if (!destroyed)
+ {
+ synchronized (cls)
+ {
+ returnForFrequencyCheck(cl);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ pool.getLock().release();
+
+ if (anyDestroyed)
+ prefill();
+ }
+ }
+ }
+
+ /**
+ * Get the pool name
+ * @return The value
+ */
+ String getPoolName()
+ {
+ if (pool == null)
+ return "";
+
+ return pool.getName();
+ }
+
+ /**
+ * Returns the connection listener that should be removed due to background
+ * validation
+ *
+ * @return The listener; otherwise null if none should be removed
+ */
+ private ConnectionListener removeForFrequencyCheck()
+ {
+ log.debug("Checking for connection within frequency");
+
+ ConnectionListenerWrapper clw = null;
+
+ for (Iterator iter = clq.iterator(); iter.hasNext();)
+ {
+ clw = iter.next();
+ long lastCheck = clw.getConnectionListener().getLastValidatedTime();
+
+ if ((System.currentTimeMillis() - lastCheck) >= poolConfiguration.getBackgroundValidationMillis())
+ {
+ clq.remove(clw);
+ break;
+ }
+ else
+ {
+ clw = null;
+ }
+ }
+
+ if (clw != null)
+ return clw.getConnectionListener();
+ else
+ return null;
+ }
+
+ /**
+ * Return a connection listener to the pool and update its validation
+ * timestamp
+ *
+ * @param cl
+ * The listener
+ */
+ private void returnForFrequencyCheck(ConnectionListener cl)
+ {
+ log.debug("Returning for connection within frequency");
+
+ cl.setLastValidatedTime(System.currentTimeMillis());
+ clq.addLast(cls.get(cl));
+ }
+
+ /**
+ * Check if the resource adapter supports lazy association
+ */
+ private void checkLazyAssociation()
+ {
+ ConnectionListener cl = null;
+
+ if (cls.size() > 0)
+ cl = cls.keySet().iterator().next();
+
+ if (cl != null)
+ {
+ if (cl.supportsLazyAssociation())
+ {
+ if (debug)
+ log.debug("Enable lazy association support for: " + pool.getName());
+
+ supportsLazyAssociation = Boolean.TRUE;
+ }
+ else
+ {
+ if (debug)
+ log.debug("Disable lazy association support for: " + pool.getName());
+
+ supportsLazyAssociation = Boolean.FALSE;
+ }
+ }
+ }
+
+ /**
+ * Detach connection listener
+ *
+ * @return The outcome
+ */
+ private boolean detachConnectionListener()
+ {
+ synchronized (cls)
+ {
+ ConnectionListener cl = null;
+ try
+ {
+ for (Entry entry : cls.entrySet())
+ {
+ cl = entry.getKey();
+
+ if (entry.getValue().isCheckedOut())
+ {
+ if (!cl.isEnlisted() && cl.getManagedConnection() instanceof DissociatableManagedConnection)
+ {
+ log.tracef("Detach: %s", cl);
+
+ DissociatableManagedConnection dmc = (DissociatableManagedConnection) cl.getManagedConnection();
+ dmc.dissociateConnections();
+
+ cl.unregisterConnections();
+
+ if (Tracer.isEnabled())
+ Tracer.returnConnectionListener(pool.getName(), this, cl, false, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ returnConnection(cl, false, false);
+
+ return true;
+ }
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ // Ok - didn't work; nuke it and disable
+ if (debug)
+ log.debug("Exception during detach for: " + pool.getName(),
+ t);
+
+ supportsLazyAssociation = Boolean.FALSE;
+
+ if (cl != null)
+ {
+ if (Tracer.isEnabled())
+ Tracer.returnConnectionListener(pool.getName(), this, cl, true, pool.isInterleaving(),
+ Tracer.isRecordCallstacks() ?
+ new Throwable("CALLSTACK") : null);
+
+ returnConnection(cl, true, true);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * String representation
+ *
+ * @return The string
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("SemaphoreConcurrentLinkedQueueManagedConnectionPool@");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append("[pool=").append(pool.getName());
+ sb.append("]");
+
+ return sb.toString();
+ }
+
+ /**
+ * Connection Listener wrapper to retain connection listener pool state
+ *
+ * @author John O'Hara
+ * @author Jesper Pedersen
+ */
+ static class ConnectionListenerWrapper
+ {
+ private volatile ConnectionListener cl;
+ private volatile boolean checkedOut;
+ private volatile boolean hasPermit;
+
+ /**
+ * Constructor
+ *
+ * @param connectionListener wrapped Connection Listener
+ */
+ public ConnectionListenerWrapper(ConnectionListener connectionListener)
+ {
+ this(connectionListener, false, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param connectionListener wrapped Connection Listener
+ * @param checkedOut is connection listener checked out
+ */
+ public ConnectionListenerWrapper(ConnectionListener connectionListener, boolean checkedOut)
+ {
+ this(connectionListener, checkedOut, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param connectionListener wrapped Connection Listener
+ * @param checkedOut is connection listener checked out
+ * @param hasPermit does connection listener have a permit
+ */
+ public ConnectionListenerWrapper(ConnectionListener connectionListener, boolean checkedOut, boolean hasPermit)
+ {
+ this.cl = connectionListener;
+ this.checkedOut = checkedOut;
+ this.hasPermit = hasPermit;
+ }
+
+ /**
+ * Get wrapped Connection Listener
+ *
+ * @return Wrapped Connection Listener
+ */
+ public ConnectionListener getConnectionListener()
+ {
+ return cl;
+ }
+
+ /**
+ * Is Connection Listener checked out
+ *
+ * @return Connection Listener is checked out
+ */
+ public boolean isCheckedOut()
+ {
+ return checkedOut;
+ }
+
+ /**
+ * Set whether Connection Listener is checkout out
+ *
+ * @param checkedOut is connection listener checked out
+ */
+ public void setCheckedOut(boolean checkedOut)
+ {
+ this.checkedOut = checkedOut;
+ }
+
+ /**
+ * Does Connection Listener have a permit
+ *
+ * @return Connection Listener has a permit
+ */
+ public boolean hasPermit()
+ {
+ return hasPermit;
+ }
+
+ /**
+ * Set whether Connection Listener has permit
+ *
+ * @param hasPermit does connection listener have a permit
+ */
+ public void setHasPermit(boolean hasPermit)
+ {
+ this.hasPermit = hasPermit;
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/mcp/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,4 @@
+
+This package contains the managed connection pool implementations and the
+factory to create one with.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the connection pool implementation.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/CriKey.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/CriKey.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/CriKey.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,86 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import javax.resource.spi.ConnectionRequestInfo;
+
+/**
+ * Pool by {@link ConnectionRequestInfo} key.
+ *
+ * @author Gurkan Erdogdu
+ * @version $Rev: $
+ */
+class CriKey
+{
+ /** Identifies no connection request information */
+ private static final Object NOCRI = new Object();
+
+ /** The connection request information */
+ private final Object cri;
+
+ /** Separate no tx */
+ private boolean separateNoTx;
+
+ /** The cached hashCode */
+ private int hashCode = Integer.MAX_VALUE;
+
+ /**
+ * Creates a new instance.
+ * @param cri connection request info
+ * @param separateNoTx separateNoTx
+ */
+ CriKey(ConnectionRequestInfo cri, boolean separateNoTx)
+ {
+ this.cri = (cri == null) ? NOCRI : cri;
+ this.separateNoTx = separateNoTx;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode()
+ {
+ if (hashCode == Integer.MAX_VALUE)
+ hashCode = cri.hashCode();
+
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+
+ if (obj == null || !(obj instanceof CriKey))
+ return false;
+
+ CriKey other = (CriKey) obj;
+
+ return cri.equals(other.cri) && separateNoTx == other.separateNoTx;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/OnePool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/OnePool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/OnePool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,111 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.pool.AbstractPrefillPool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Single pool implementation.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class OnePool extends AbstractPrefillPool
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, OnePool.class.getName());
+
+ /**
+ * Creates a new instance.
+ *
+ * @param mcf managed connection factory
+ * @param pc pool configuration
+ * @param noTxSeparatePools notx seperate pool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ public OnePool(final ManagedConnectionFactory mcf, final PoolConfiguration pc,
+ final boolean noTxSeparatePools, final boolean sharable,
+ final String mcp)
+ {
+ super(mcf, pc, noTxSeparatePools, sharable, mcp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object getKey(final Subject subject, final ConnectionRequestInfo cri, boolean separateNoTx)
+ {
+ if (separateNoTx)
+ {
+ return Boolean.TRUE;
+ }
+ else
+ {
+ return Boolean.FALSE;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void emptyManagedConnectionPool(ManagedConnectionPool pool)
+ {
+ // No-operation
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection()
+ {
+ return internalTestConnection(null, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection(ConnectionRequestInfo cri, Subject subject)
+ {
+ return internalTestConnection(null, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CoreLogger getLogger()
+ {
+ return log;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolByCri.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolByCri.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolByCri.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,94 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.pool.AbstractPool;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Pool implementation that uses subject.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class PoolByCri extends AbstractPool
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, PoolByCri.class.getName());
+
+ /**
+ * Creates a new instance.
+ * @param mcf managed connection factory
+ * @param pc pool configuration
+ * @param noTxSeparatePools notx seperate pool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ public PoolByCri(final ManagedConnectionFactory mcf, final PoolConfiguration pc,
+ final boolean noTxSeparatePools, final boolean sharable,
+ final String mcp)
+ {
+ super(mcf, pc, noTxSeparatePools, sharable, mcp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object getKey(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx) throws ResourceException
+ {
+ return new CriKey(cri, separateNoTx);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection(ConnectionRequestInfo cri, Subject subject)
+ {
+ return internalTestConnection(cri, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CoreLogger getLogger()
+ {
+ return log;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolBySubject.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolBySubject.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolBySubject.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,164 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.ConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.AbstractPrefillPool;
+import org.jboss.jca.core.spi.security.SubjectFactory;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Set;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.security.PasswordCredential;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Pool implementation that uses subject.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class PoolBySubject extends AbstractPrefillPool
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, PoolBySubject.class.getName());
+
+ /**
+ * Creates a new instance.
+ * @param mcf managed connection factory
+ * @param pc pool configuration
+ * @param noTxSeparatePools notx seperate pool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ public PoolBySubject(final ManagedConnectionFactory mcf, final PoolConfiguration pc,
+ final boolean noTxSeparatePools, final boolean sharable,
+ final String mcp)
+ {
+ super(mcf, pc, noTxSeparatePools, sharable, mcp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object getKey(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx) throws ResourceException
+ {
+ return new SubjectKey(subject, separateNoTx);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection()
+ {
+ try
+ {
+ ConnectionManager cm = getConnectionManager();
+ ManagedConnectionFactory mcf = getManagedConnectionFactory();
+
+ Subject subject = createSubject(cm.getSubjectFactory(), cm.getSecurityDomain(), mcf, cm.getJndiName());
+
+ if (subject != null)
+ return internalTestConnection(null, subject);
+ }
+ catch (Throwable t)
+ {
+ log.debugf(t, "Error during testConnection: %s", t.getMessage());
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection(ConnectionRequestInfo cri, Subject subject)
+ {
+ return internalTestConnection(null, subject);
+ }
+
+ /**
+ * Create a subject
+ * @param subjectFactory The subject factory
+ * @param securityDomain The security domain
+ * @param mcf The managed connection factory
+ * @param jndiName The jndi-name
+ * @return The subject; null
in case of an error
+ */
+ protected Subject createSubject(final SubjectFactory subjectFactory,
+ final String securityDomain,
+ final ManagedConnectionFactory mcf,
+ final String jndiName)
+ {
+ if (subjectFactory == null)
+ throw new IllegalArgumentException("SubjectFactory is null");
+
+ if (securityDomain == null)
+ throw new IllegalArgumentException("SecurityDomain is null");
+
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Subject run()
+ {
+ try
+ {
+ Subject subject = subjectFactory.createSubject(securityDomain);
+
+ Set pcs = subject.getPrivateCredentials(PasswordCredential.class);
+ if (pcs.size() > 0)
+ {
+ for (PasswordCredential pc : pcs)
+ {
+ pc.setManagedConnectionFactory(mcf);
+ }
+ }
+
+ return subject;
+ }
+ catch (Throwable t)
+ {
+ log.exceptionDuringCreateSubject(jndiName, t.getMessage(), t);
+ }
+
+ return null;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CoreLogger getLogger()
+ {
+ return log;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolBySubjectAndCri.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolBySubjectAndCri.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/PoolBySubjectAndCri.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,95 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.pool.AbstractPool;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Pool implementation that uses subject and connection
+ * request info for its pool partition.
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class PoolBySubjectAndCri extends AbstractPool
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, PoolBySubjectAndCri.class.getName());
+
+ /**
+ * Creates a new instance.
+ * @param mcf managed connection factory
+ * @param pc pool configuration
+ * @param noTxSeparatePools notx seperate pool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ public PoolBySubjectAndCri(final ManagedConnectionFactory mcf, final PoolConfiguration pc,
+ final boolean noTxSeparatePools, final boolean sharable,
+ final String mcp)
+ {
+ super(mcf, pc, noTxSeparatePools, sharable, mcp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object getKey(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx) throws ResourceException
+ {
+ return new SubjectCriKey(subject, cri, separateNoTx);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection(ConnectionRequestInfo cri, Subject subject)
+ {
+ return internalTestConnection(cri, subject);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CoreLogger getLogger()
+ {
+ return log;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/ReauthKey.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/ReauthKey.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/ReauthKey.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,76 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.security.auth.Subject;
+
+/**
+ * Simple reauth pool with same properties as an OnePool
+ * @author Jesper Pedersen
+ */
+class ReauthKey
+{
+ /** The cached hashCode */
+ private int hashCode = Integer.MAX_VALUE;
+
+ /**
+ * Constructor
+ * @param subject subject instance
+ * @param cri connection request info
+ * @param separateNoTx seperateNoTx
+ */
+ ReauthKey(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx)
+ {
+ this.hashCode = separateNoTx ? Boolean.TRUE.hashCode() : Boolean.FALSE.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof ReauthKey))
+ {
+ return false;
+ }
+
+ ReauthKey other = (ReauthKey)obj;
+ return hashCode == other.hashCode;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/ReauthPool.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/ReauthPool.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/ReauthPool.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,110 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.api.connectionmanager.pool.PoolConfiguration;
+import org.jboss.jca.core.connectionmanager.pool.AbstractPool;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Pool implementation that supports reauthentication
+ *
+ * @author Jesper Pedersen
+ */
+public class ReauthPool extends AbstractPool
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, ReauthPool.class.getName());
+
+ /**
+ * Creates a new instance.
+ * @param mcf managed connection factory
+ * @param pc pool configuration
+ * @param noTxSeparatePools notx seperate pool
+ * @param sharable Are the connections sharable
+ * @param mcp mcp
+ */
+ public ReauthPool(final ManagedConnectionFactory mcf,
+ final PoolConfiguration pc,
+ final boolean noTxSeparatePools,
+ final boolean sharable,
+ final String mcp)
+ {
+ super(mcf, pc, noTxSeparatePools, sharable, mcp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected synchronized Object getKey(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx)
+ throws ResourceException
+ {
+ return new ReauthKey(subject, cri, separateNoTx);
+ }
+
+ /**
+ * There is no reason to empty the managed connection pool for reauth enabled
+ * resource adapters, since all managed connections can change
+ * its credentials
+ *
+ * @param pool the managed connection pool
+ */
+ @Override
+ public void emptyManagedConnectionPool(ManagedConnectionPool pool)
+ {
+ // No-operation
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean testConnection(ConnectionRequestInfo cri, Subject subject)
+ {
+ return internalTestConnection(cri, subject);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CoreLogger getLogger()
+ {
+ return log;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,85 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2010, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+/**
+ * Privileged Blocks
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Constructor
+ */
+ private SecurityActions()
+ {
+ }
+
+ /**
+ * Get the hash code for a Subject
+ * @param subject The Subject
+ * @return The hash code
+ */
+ static int hashCode(final Subject subject)
+ {
+ if (System.getSecurityManager() == null)
+ return subject.hashCode();
+
+ Integer hashCode = AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Integer run()
+ {
+ return subject.hashCode();
+ }
+ });
+
+ return hashCode.intValue();
+ }
+
+ /**
+ * Verify if two Subject's are equal
+ * @param s1 The first Subject
+ * @param s2 The second Subject
+ * @return True if equal; otherwise false
+ */
+ static boolean equals(final Subject s1, final Subject s2)
+ {
+ if (System.getSecurityManager() == null)
+ return s1 != null ? s1.equals(s2) : s2 == null;
+
+ Boolean equals = AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Boolean run()
+ {
+ return s1 != null ? s1.equals(s2) : s2 == null;
+ }
+ });
+
+ return equals.booleanValue();
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SubjectCriKey.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SubjectCriKey.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SubjectCriKey.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,108 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.security.auth.Subject;
+
+/**
+ * Pool key based on {@link Subject} and {@link ConnectionRequestInfo}.
+ *
+ * @author Gurkan Erdogdu
+ * @author David Jencks
+ * @author Adrian Brock
+ * @author Weston Price
+ * @author Jesper Pedersen
+ * @version $Rev: $
+ */
+class SubjectCriKey
+{
+ /** Identifies no subject */
+ private static final Subject NOSUBJECT = new Subject();
+
+ /** Identifies no connection request information */
+ private static final Object NOCRI = new Object();
+
+ /** The subject */
+ private final Subject subject;
+
+ /** The connection request information */
+ private final Object cri;
+
+ /** The cached hashCode */
+ private int hashCode = Integer.MAX_VALUE;
+
+ /** Separate no tx */
+ private boolean separateNoTx;
+
+ /**
+ *
+ * @param subject subject instance
+ * @param cri connection request info
+ * @param separateNoTx seperateNoTx
+ */
+ SubjectCriKey(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx)
+ {
+ this.subject = (subject == null) ? NOSUBJECT : subject;
+ this.cri = (cri == null) ? NOCRI : cri;
+ this.separateNoTx = separateNoTx;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode()
+ {
+ if (hashCode == Integer.MAX_VALUE)
+ {
+ hashCode = SecurityActions.hashCode(subject) ^ cri.hashCode();
+ }
+
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof SubjectCriKey))
+ {
+ return false;
+ }
+
+ SubjectCriKey other = (SubjectCriKey) obj;
+
+ return SecurityActions.equals(subject, other.subject)
+ && cri.equals(other.cri)
+ && separateNoTx == other.separateNoTx;
+ }
+
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SubjectKey.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SubjectKey.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/SubjectKey.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,90 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2009, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.strategy;
+
+import javax.security.auth.Subject;
+
+/**
+ * Pool by {@link Subject} key.
+ *
+ * @author Gurkan Erdogdu
+ * @version $Rev: $
+ */
+class SubjectKey
+{
+ /** Identifies no subject */
+ private static final Subject NOSUBJECT = new Subject();
+
+ /** The subject */
+ private final Subject subject;
+
+ /** Separate no tx */
+ private boolean separateNoTx;
+
+ /** The cached hashCode */
+ private int hashCode = Integer.MAX_VALUE;
+
+ /**
+ * Creates a new instance.
+ * @param subject subject
+ * @param separateNoTx separateNoTx
+ */
+ SubjectKey(Subject subject, boolean separateNoTx)
+ {
+ this.subject = (subject == null) ? NOSUBJECT : subject;
+ this.separateNoTx = separateNoTx;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode()
+ {
+ if (hashCode == Integer.MAX_VALUE)
+ hashCode = SecurityActions.hashCode(subject);
+
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null || !(obj instanceof SubjectKey))
+ {
+ return false;
+ }
+ SubjectKey other = (SubjectKey) obj;
+
+ return SecurityActions.equals(subject, other.subject)
+ && separateNoTx == other.separateNoTx;
+ }
+
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/strategy/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the connection pool strategies.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/ConnectionValidator.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/ConnectionValidator.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/ConnectionValidator.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,308 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008-2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.validator;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.connectionmanager.pool.mcp.ManagedConnectionPool;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Connection validator
+ *
+ * @author Gurkan Erdogdu
+ * @author Jesper Pedersen
+ */
+public class ConnectionValidator
+{
+ /** Logger instance */
+ private static CoreLogger logger = Logger.getMessageLogger(CoreLogger.class, ConnectionValidator.class.getName());
+
+ /** Thread name */
+ private static final String THREAD_NAME = "ConnectionValidator";
+
+ /** Singleton instance */
+ private static ConnectionValidator instance = new ConnectionValidator();
+
+ /** Registered pool instances */
+ private CopyOnWriteArrayList registeredPools =
+ new CopyOnWriteArrayList();
+
+ /** Executor service */
+ private ExecutorService executorService;
+
+ /** Is the executor external */
+ private boolean isExternal;
+
+ /** The interval */
+ private long interval;
+
+ /** The next scan */
+ private long next;
+
+ /** Shutdown */
+ private AtomicBoolean shutdown;
+
+ /** Lock */
+ private Lock lock;
+
+ /** Condition */
+ private Condition condition;
+
+ /**
+ * Private constructor.
+ */
+ private ConnectionValidator()
+ {
+ this.executorService = null;
+ this.isExternal = false;
+ this.interval = Long.MAX_VALUE;
+ this.next = Long.MAX_VALUE;
+ this.shutdown = new AtomicBoolean(false);
+ this.lock = new ReentrantLock(true);
+ this.condition = lock.newCondition();
+ }
+
+ /**
+ * Get the instance
+ * @return The value
+ */
+ public static ConnectionValidator getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Set the executor service
+ * @param v The value
+ */
+ public void setExecutorService(ExecutorService v)
+ {
+ if (v != null)
+ {
+ this.executorService = v;
+ this.isExternal = true;
+ }
+ else
+ {
+ this.executorService = null;
+ this.isExternal = false;
+ }
+ }
+
+ /**
+ * Start
+ * @exception Throwable Thrown if an error occurs
+ */
+ public void start() throws Throwable
+ {
+ if (!isExternal)
+ {
+ this.executorService = Executors.newSingleThreadExecutor(new ValidatorThreadFactory());
+ }
+
+ this.shutdown.set(false);
+ this.interval = Long.MAX_VALUE;
+ this.next = Long.MAX_VALUE;
+
+ this.executorService.execute(new ConnectionValidatorRunner());
+ }
+
+ /**
+ * Stop
+ * @exception Throwable Thrown if an error occurs
+ */
+ public void stop() throws Throwable
+ {
+ instance.shutdown.set(true);
+
+ if (!isExternal)
+ {
+ instance.executorService.shutdownNow();
+ instance.executorService = null;
+ }
+
+ instance.registeredPools.clear();
+ }
+
+ /**
+ * Register pool for connection validation.
+ * @param mcp managed connection pool
+ * @param interval validation interval
+ */
+ public void registerPool(ManagedConnectionPool mcp, long interval)
+ {
+ logger.debugf("Register pool: %s (interval=%s)", mcp, interval);
+
+ instance.internalRegisterPool(mcp, interval);
+ }
+
+ /**
+ * Unregister pool instance for connection validation.
+ * @param mcp pool instance
+ */
+ public void unregisterPool(ManagedConnectionPool mcp)
+ {
+ logger.debugf("Unregister pool: %s", mcp);
+
+ instance.internalUnregisterPool(mcp);
+ }
+
+ private void internalRegisterPool(ManagedConnectionPool mcp, long interval)
+ {
+ try
+ {
+ this.lock.lock();
+
+ this.registeredPools.addIfAbsent(mcp);
+
+ if (interval > 1 && interval / 2 < this.interval)
+ {
+ this.interval = interval / 2;
+ long maybeNext = System.currentTimeMillis() + this.interval;
+ if (next > maybeNext && maybeNext > 0)
+ {
+ next = maybeNext;
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("About to notify thread: old next: " + next + ", new next: " + maybeNext);
+ }
+
+ this.condition.signal();
+ }
+ }
+ }
+ finally
+ {
+ this.lock.unlock();
+ }
+ }
+
+ private void internalUnregisterPool(ManagedConnectionPool mcp)
+ {
+ this.registeredPools.remove(mcp);
+
+ if (this.registeredPools.size() == 0)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Setting interval to Long.MAX_VALUE");
+ }
+
+ interval = Long.MAX_VALUE;
+ }
+ }
+
+ /**
+ * Thread factory.
+ */
+ private static class ValidatorThreadFactory implements ThreadFactory
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public Thread newThread(Runnable r)
+ {
+ Thread thread = new Thread(r, ConnectionValidator.THREAD_NAME);
+ thread.setDaemon(true);
+
+ return thread;
+ }
+ }
+
+ /**
+ * ConnectionValidatorRunner.
+ *
+ */
+ private class ConnectionValidatorRunner implements Runnable
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public void run()
+ {
+ final ClassLoader oldTccl = SecurityActions.getThreadContextClassLoader();
+ SecurityActions.setThreadContextClassLoader(ConnectionValidator.class.getClassLoader());
+
+ try
+ {
+ lock.lock();
+
+ while (!shutdown.get())
+ {
+ boolean result = instance.condition.await(instance.interval, TimeUnit.MILLISECONDS);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("Result of await: " + result);
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Notifying pools, interval: " + interval);
+ }
+
+ for (ManagedConnectionPool mcp : registeredPools)
+ {
+ mcp.validateConnections();
+ }
+
+ next = System.currentTimeMillis() + interval;
+
+ if (next < 0)
+ {
+ next = Long.MAX_VALUE;
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ if (!shutdown.get())
+ logger.returningConnectionValidatorInterrupted();
+ }
+ catch (RuntimeException e)
+ {
+ logger.connectionValidatorIgnoredUnexpectedRuntimeException(e);
+ }
+ catch (Exception e)
+ {
+ logger.connectionValidatorIgnoredUnexpectedError(e);
+ }
+ finally
+ {
+ lock.unlock();
+ SecurityActions.setThreadContextClassLoader(oldTccl);
+ }
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/SecurityActions.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/SecurityActions.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/SecurityActions.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,83 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2008, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.core.connectionmanager.pool.validator;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Jesper Pedersen
+ */
+class SecurityActions
+{
+ /**
+ * Get the context classloader.
+ * @return The classloader
+ */
+ public static ClassLoader getThreadContextClassLoader()
+ {
+ if (System.getSecurityManager() == null)
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ else
+ {
+ return AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public ClassLoader run()
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+ }
+
+ /**
+ * Set the context classloader.
+ * @param cl classloader
+ */
+ public static void setThreadContextClassLoader(final ClassLoader cl)
+ {
+ if (cl == null)
+ return;
+
+ if (System.getSecurityManager() == null)
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ else
+ {
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+
+ return null;
+ }
+ });
+ }
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/package.html
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/package.html (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/pool/validator/package.html (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,3 @@
+
+This package contains the connection validator logic.
+
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/transaction/LockKey.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/transaction/LockKey.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/transaction/LockKey.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,65 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2011, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.transaction;
+
+/**
+ * Defines the lock key
+ *
+ * @author Jesper Pedersen
+ */
+public class LockKey
+{
+ /** Instance */
+ public static final LockKey INSTANCE = new LockKey();
+
+ /**
+ * Constructor
+ */
+ private LockKey()
+ {
+ }
+
+ /**
+ * Equals
+ * @param other The other object
+ * @return True if equal; otherwise false
+ */
+ public boolean equals(Object other)
+ {
+ if (this == other)
+ return true;
+
+ if (other == null || !(other instanceof LockKey))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Hash code
+ * @return The value
+ */
+ public int hashCode()
+ {
+ return 42;
+ }
+}
Index: 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java
===================================================================
diff -u
--- 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java (revision 0)
+++ 3rdParty_sources/ironjacamar/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java (revision 8b7897a917497532f0074f6a38c6ded6fd94cdb9)
@@ -0,0 +1,501 @@
+/*
+ * IronJacamar, a Java EE Connector Architecture implementation
+ * Copyright 2006, Red Hat Inc, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jca.core.connectionmanager.transaction;
+
+import org.jboss.jca.core.CoreLogger;
+import org.jboss.jca.core.spi.transaction.TransactionIntegration;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Organizes transaction synchronization done by JCA.
+ *
+ *
+ * This class exists to make sure all Tx synchronizations
+ * are invoked before the cached connection manager closes any
+ * closed connections.
+ *
+ * @author Adrian Brock
+ * @author gurkanerdogdu
+ * @version $Rev$
+ */
+public class TransactionSynchronizer implements Synchronization
+{
+ /** The logger */
+ private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, TransactionSynchronizer.class.getName());
+
+ /** The records */
+ private static ConcurrentMap records =
+ new ConcurrentHashMap(512, 0.75f, 512);
+
+ /** The transaction */
+ private Transaction tx;
+
+ /** The identifier */
+ private Object identifier;
+
+ /** The enlisting thread */
+ private Thread enlistingThread;
+
+ /** Unenlisted */
+ private List unenlisted;
+
+ /** Enlisted */
+ private List enlisted;
+
+ /** The cached connection manager synchronization */
+ private Synchronization ccmSynch;
+
+ /**
+ * Create a new transaction synchronizer
+ *
+ * @param tx the transaction to synchronize with
+ * @param id the identifier for the transaction
+ */
+ private TransactionSynchronizer(Transaction tx, Object id)
+ {
+ this.tx = tx;
+ this.identifier = id;
+ this.enlistingThread = null;
+ this.unenlisted = new ArrayList(1);
+ this.enlisted = new ArrayList(1);
+ }
+
+ /**
+ * Add a new Tx synchronization that has not been enlisted
+ *
+ * @param synch the synchronization
+ */
+ public synchronized void addUnenlisted(Synchronization synch)
+ {
+ if (unenlisted == null)
+ unenlisted = new ArrayList