libproxool-java-0.9.1.orig/0000755000175000017500000000000011053761073015531 5ustar twernertwernerlibproxool-java-0.9.1.orig/doc/0000755000175000017500000000000011054125603016270 5ustar twernertwernerlibproxool-java-0.9.1.orig/lib/0000755000175000017500000000000011054125603016271 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/0000755000175000017500000000000011053761073016320 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/0000755000175000017500000000000011054125603017233 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/0000755000175000017500000000000011053761073020030 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/0000755000175000017500000000000011053761073023007 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/0000755000175000017500000000000011054125603025163 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/BoundedChannel.java0000644000175000017500000000214310730503124030675 0ustar twernertwerner/* File: BoundedChannel.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * A channel that is known to have a capacity, signifying * that put operations may block when the * capacity is reached. Various implementations may have * intrinsically hard-wired capacities, capacities that are fixed upon * construction, or dynamically adjustable capacities. * @see DefaultChannelCapacity *

[ Introduction to this package. ]

**/ public interface BoundedChannel extends Channel { /** * Return the maximum number of elements that can be held. * @return the capacity of this channel. **/ public int capacity(); } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/Callable.java0000644000175000017500000000223710730503124027527 0ustar twernertwerner/* File: Callable.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 30Jun1998 dl Create public version 5Jan1999 dl Change Exception to Throwable in call signature 27Jan1999 dl Undo last change */ package org.logicalcobwebs.concurrent; /** * Interface for runnable actions that bear results and/or throw Exceptions. * This interface is designed to provide a common protocol for * result-bearing actions that can be run independently in threads, * in which case * they are ordinarily used as the bases of Runnables that set * FutureResults *

*

[ Introduction to this package. ] * @see FutureResult **/ public interface Callable { /** Perform some action that returns a result or throws an exception **/ Object call() throws Exception; } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/Channel.java0000644000175000017500000002553410730503124027405 0ustar twernertwerner/* File: Channel.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version 25aug1998 dl added peek */ package org.logicalcobwebs.concurrent; /** * Main interface for buffers, queues, pipes, conduits, etc. *

* A Channel represents anything that you can put items * into and take them out of. As with the Sync * interface, both * blocking (put(x), take), * and timeouts (offer(x, msecs), poll(msecs)) policies * are provided. Using a * zero timeout for offer and poll results in a pure balking policy. *

* To aid in efforts to use Channels in a more typesafe manner, * this interface extends Puttable and Takable. You can restrict * arguments of instance variables to this type as a way of * guaranteeing that producers never try to take, or consumers put. * for example: *

 * class Producer implements Runnable {
 *   final Puttable chan;
 *   Producer(Puttable channel) { chan = channel; }
 *   public void run() {
 *     try {
 *       for(;;) { chan.put(produce()); }
 *     }
 *     catch (InterruptedException ex) {}
 *   }
 *   Object produce() { ... }
 * }
 *
 *
 * class Consumer implements Runnable {
 *   final Takable chan;
 *   Consumer(Takable channel) { chan = channel; }
 *   public void run() {
 *     try {
 *       for(;;) { consume(chan.take()); }
 *     }
 *     catch (InterruptedException ex) {}
 *   }
 *   void consume(Object x) { ... }
 * }
 *
 * class Setup {
 *   void main() {
 *     Channel chan = new SomeChannelImplementation();
 *     Producer p = new Producer(chan);
 *     Consumer c = new Consumer(chan);
 *     new Thread(p).start();
 *     new Thread(c).start();
 *   }
 * }
 * 
*

* A given channel implementation might or might not have bounded * capacity or other insertion constraints, so in general, you cannot tell if * a given put will block. However, * Channels that are designed to * have an element capacity (and so always block when full) * should implement the * BoundedChannel * subinterface. *

* Channels may hold any kind of item. However, * insertion of null is not in general supported. Implementations * may (all currently do) throw IllegalArgumentExceptions upon attempts to * insert null. *

* By design, the Channel interface does not support any methods to determine * the current number of elements being held in the channel. * This decision reflects the fact that in * concurrent programming, such methods are so rarely useful * that including them invites misuse; at best they could * provide a snapshot of current * state, that could change immediately after being reported. * It is better practice to instead use poll and offer to try * to take and put elements without blocking. For example, * to empty out the current contents of a channel, you could write: *

 *  try {
 *    for (;;) {
 *       Object item = channel.poll(0);
 *       if (item != null)
 *         process(item);
 *       else
 *         break;
 *    }
 *  }
 *  catch(InterruptedException ex) { ... }
 * 
*

* However, it is possible to determine whether an item * exists in a Channel via peek, which returns * but does NOT remove the next item that can be taken (or null * if there is no such item). The peek operation has a limited * range of applicability, and must be used with care. Unless it * is known that a given thread is the only possible consumer * of a channel, and that no time-out-based offer operations * are ever invoked, there is no guarantee that the item returned * by peek will be available for a subsequent take. *

* When appropriate, you can define an isEmpty method to * return whether peek returns null. *

* Also, as a compromise, even though it does not appear in interface, * implementation classes that can readily compute the number * of elements support a size() method. This allows careful * use, for example in queue length monitors, appropriate to the * particular implementation constraints and properties. *

* All channels allow multiple producers and/or consumers. * They do not support any kind of close method * to shut down operation or indicate completion of particular * producer or consumer threads. * If you need to signal completion, one way to do it is to * create a class such as *

 * class EndOfStream {
 *    // Application-dependent field/methods
 * }
 * 
* And to have producers put an instance of this class into * the channel when they are done. The consumer side can then * check this via *
 *   Object x = aChannel.take();
 *   if (x instanceof EndOfStream)
 *     // special actions; perhaps terminate
 *   else
 *     // process normally
 * 
*

* In time-out based methods (poll(msecs) and offer(x, msecs), * time bounds are interpreted in * a coarse-grained, best-effort fashion. Since there is no * way in Java to escape out of a wait for a synchronized * method/block, time bounds can sometimes be exceeded when * there is a lot contention for the channel. Additionally, * some Channel semantics entail a ``point of * no return'' where, once some parts of the operation have completed, * others must follow, regardless of time bound. *

* Interruptions are in general handled as early as possible * in all methods. Normally, InterruptionExceptions are thrown * in put/take and offer(msec)/poll(msec) if interruption * is detected upon entry to the method, as well as in any * later context surrounding waits. *

* If a put returns normally, an offer * returns true, or a put or poll returns non-null, the operation * completed successfully. * In all other cases, the operation fails cleanly -- the * element is not put or taken. *

* As with Sync classes, spinloops are not directly supported, * are not particularly recommended for routine use, but are not hard * to construct. For example, here is an exponential backoff version: *

 * Object backOffTake(Channel q) throws InterruptedException {
 *   long waitTime = 0;
 *   for (;;) {
 *      Object x = q.poll(0);
 *      if (x != null)
 *        return x;
 *      else {
 *        Thread.sleep(waitTime);
 *        waitTime = 3 * waitTime / 2 + 1;
 *      }
 *    }
 * 
*

* Sample Usage. Here is a producer/consumer design * where the channel is used to hold Runnable commands representing * background tasks. *

 * class Service {
 *   private final Channel channel = ... some Channel implementation;
 *
 *   private void backgroundTask(int taskParam) { ... }
 *
 *   public void action(final int arg) {
 *     Runnable command =
 *       new Runnable() {
 *         public void run() { backgroundTask(arg); }
 *       };
 *     try { channel.put(command) }
 *     catch (InterruptedException ex) {
 *       Thread.currentThread().interrupt(); // ignore but propagate
 *     }
 *   }
 *
 *   public Service() {
 *     Runnable backgroundLoop =
 *       new Runnable() {
 *         public void run() {
 *           for (;;) {
 *             try {
 *               Runnable task = (Runnable)(channel.take());
 *               task.run();
 *             }
 *             catch (InterruptedException ex) { return; }
 *           }
 *         }
 *       };
 *     new Thread(backgroundLoop).start();
 *   }
 * }
 *
 * 
*

[ Introduction to this package. ] * @see Sync * @see BoundedChannel **/ public interface Channel extends Puttable, Takable { /** * Place item in the channel, possibly waiting indefinitely until * it can be accepted. Channels implementing the BoundedChannel * subinterface are generally guaranteed to block on puts upon * reaching capacity, but other implementations may or may not block. * @param item the element to be inserted. Should be non-null. * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case the element is guaranteed not * to be inserted. Otherwise, on normal return, the element is guaranteed * to have been inserted. **/ public void put(Object item) throws InterruptedException; /** * Place item in channel only if it can be accepted within * msecs milliseconds. The time bound is interpreted in * a coarse-grained, best-effort fashion. * @param item the element to be inserted. Should be non-null. * @param msecs the number of milliseconds to wait. If less than * or equal to zero, the method does not perform any timed waits, * but might still require * access to a synchronization lock, which can impose unbounded * delay if there is a lot of contention for the channel. * @return true if accepted, else false * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case the element is guaranteed not * to be inserted (i.e., is equivalent to a false return). **/ public boolean offer(Object item, long msecs) throws InterruptedException; /** * Return and remove an item from channel, * possibly waiting indefinitely until * such an item exists. * @return some item from the channel. Different implementations * may guarantee various properties (such as FIFO) about that item * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case state of the channel is unchanged. * **/ public Object take() throws InterruptedException; /** * Return and remove an item from channel only if one is available within * msecs milliseconds. The time bound is interpreted in a coarse * grained, best-effort fashion. * @param msecs the number of milliseconds to wait. If less than * or equal to zero, the operation does not perform any timed waits, * but might still require * access to a synchronization lock, which can impose unbounded * delay if there is a lot of contention for the channel. * @return some item, or null if the channel is empty. * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case state of the channel is unchanged * (i.e., equivalent to a null return). **/ public Object poll(long msecs) throws InterruptedException; /** * Return, but do not remove object at head of Channel, * or null if it is empty. **/ public Object peek(); } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/DefaultChannelCapacity.java0000644000175000017500000000343310730503124032362 0ustar twernertwerner/* File: DefaultChannelCapacity.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * A utility class to set the default capacity of * BoundedChannel * implementations that otherwise require a capacity argument * @see BoundedChannel * [ Introduction to this package. ]

**/ public class DefaultChannelCapacity { /** The initial value of the default capacity is 1024 **/ public static final int INITIAL_DEFAULT_CAPACITY = 1024; /** the current default capacity **/ private static final SynchronizedInt defaultCapacity_ = new SynchronizedInt(INITIAL_DEFAULT_CAPACITY); /** * Set the default capacity used in * default (no-argument) constructor for BoundedChannels * that otherwise require a capacity argument. * @exception IllegalArgumentException if capacity less or equal to zero */ public static void set(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); defaultCapacity_.set(capacity); } /** * Get the default capacity used in * default (no-argument) constructor for BoundedChannels * that otherwise require a capacity argument. * Initial value is INITIAL_DEFAULT_CAPACITY * @see #INITIAL_DEFAULT_CAPACITY */ public static int get() { return defaultCapacity_.get(); } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/Executor.java0000644000175000017500000000512110730503124027621 0ustar twernertwerner/* File: Executor.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 19Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * Interface for objects that execute Runnables, * as well as various objects that can be wrapped * as Runnables. * The main reason to use Executor throughout a program or * subsystem is to provide flexibility: You can easily * change from using thread-per-task to using pools or * queuing, without needing to change most of your code that * generates tasks. *

* The general intent is that execution be asynchronous, * or at least independent of the caller. For example, * one of the simplest implementations of execute * (as performed in ThreadedExecutor) * is new Thread(command).start();. * However, this interface allows implementations that instead * employ queueing or pooling, or perform additional * bookkeeping. *

* *

[ Introduction to this package. ] **/ public interface Executor { /** * Execute the given command. This method is guaranteed * only to arrange for execution, that may actually * occur sometime later; for example in a new * thread. However, in fully generic use, callers * should be prepared for execution to occur in * any fashion at all, including immediate direct * execution. *

* The method is defined not to throw * any checked exceptions during execution of the command. Generally, * any problems encountered will be asynchronous and * so must be dealt with via callbacks or error handler * objects. If necessary, any context-dependent * catastrophic errors encountered during * actions that arrange for execution could be accompanied * by throwing context-dependent unchecked exceptions. *

* However, the method does throw InterruptedException: * It will fail to arrange for execution * if the current thread is currently interrupted. * Further, the general contract of the method is to avoid, * suppress, or abort execution if interruption is detected * in any controllable context surrounding execution. **/ public void execute(Runnable command) throws InterruptedException; } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/FJTask.java0000644000175000017500000004613310730503124027155 0ustar twernertwerner/* File: Task.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 7Jan1999 dl first release 14jan1999 dl simplify start() semantics; improve documentation 18Jan1999 dl Eliminate useless time-based waits. 7Mar1999 dl Add reset method, add array-based composite operations 27Apr1999 dl Rename */ package org.logicalcobwebs.concurrent; /** * Abstract base class for Fork/Join Tasks. * *

* FJTasks are lightweight, stripped-down analogs of Threads. * Many FJTasks share the same pool of Java threads. This is * supported by the FJTaskRunnerGroup and FJTaskRunner classes, that * mainly contain * methods called only internally by FJTasks. * FJTasks support versions of the most common methods found in class Thread, * including start(), yield() and join(). However, they * don't support priorities, ThreadGroups or other bookkeeping * or control methods of class Thread. *

* FJTasks should normally be defined by subclassing and adding a run() method. * Alternatively, static inner class Wrap(Runnable r) * can be used to * wrap an existing Runnable object in a FJTask. *

* FJTaskRunnerGroup.execute(FJTask) can be used to * initiate a FJTask from a non-FJTask thread. * And FJTaskRunnerGroup.invoke(FJTask) can be used to initiate * a FJTask and then wait for it to complete before returning. * These are the only entry-points from normal threads to FJTasks. * Most FJTask methods themselves may only be called from within running FJTasks. * They throw ClassCastExceptions if they are not, * reflecting the fact that these methods * can only be executed using FJTaskRunner threads, not generic * java.lang.Threads. *

* There are three different ways to run a FJTask, * with different scheduling semantics: *

*

* The main economies of FJTasks stem from the fact that * FJTasks do not support blocking operations of any kind. * FJTasks should just run to completion without * issuing waits or performing blocking IO. * There are several styles for creating the run methods that * execute as tasks, including * event-style methods, and pure computational methods. * Generally, the best kinds of FJTasks are those that in turn * generate other FJTasks. *

* There is nothing actually * preventing you from blocking within a FJTask, and very short waits/blocks are * completely well behaved. But FJTasks are not designed * to support arbitrary synchronization * since there is no way to suspend and resume individual tasks * once they have begun executing. FJTasks should also be finite * in duration -- they should not contain infinite loops. * FJTasks that might need to perform a blocking * action, or hold locks for extended periods, or * loop forever can instead create normal * java Thread objects that will do so. FJTasks are just not * designed to support these things. * FJTasks may however yield() control to allow their FJTaskRunner threads * to run other tasks, * and may wait for other dependent tasks via join(). These * are the only coordination mechanisms supported by FJTasks. *

* FJTasks, and the FJTaskRunners that execute them are not * intrinsically robust with respect to exceptions. * A FJTask that aborts via an exception does not automatically * have its completion flag (isDone) set. * As with ordinary Threads, an uncaught exception will normally cause * its FJTaskRunner thread to die, which in turn may sometimes * cause other computations being performed to hang or abort. * You can of course * do better by trapping exceptions inside the run methods of FJTasks. *

* The overhead differences between FJTasks and Threads are substantial, * especially when using fork() or coInvoke(). * FJTasks can be two or three orders of magnitude faster than Threads, * at least when run on JVMs with high-performance garbage collection * (every FJTask quickly becomes garbage) and good native thread support. *

* Given these overhead savings, you might be tempted to use FJTasks for * everything you would use a normal Thread to do. Don't. Java Threads * remain better for general purpose thread-based programming. Remember * that FJTasks cannot be used for designs involving arbitrary blocking * synchronization or I/O. Extending FJTasks to support such capabilities * would amount to re-inventing the Thread class, and would make them * less optimal in the contexts that they were designed for. *

[ Introduction to this package. ] *

* @see FJTaskRunner * @see FJTaskRunnerGroup **/ public abstract class FJTask implements Runnable { /** * The only status information associated with FJTasks is whether * the they are considered to have completed. * It is set true automatically within * FJTaskRunner methods upon completion * of the run method, or manually via cancel. **/ private volatile boolean done; // = false; /** * Return the FJTaskRunner thread running the current FJTask. * Most FJTask methods are just relays to their current * FJTaskRunners, that perform the indicated actions. * @exception ClassCastException if caller thread is not a * running FJTask. **/ public static FJTaskRunner getFJTaskRunner() { return (FJTaskRunner) (Thread.currentThread()); } /** * Return the FJTaskRunnerGroup of the thread running the current FJTask. * @exception ClassCastException if caller thread is not a * running FJTask. **/ public static FJTaskRunnerGroup getFJTaskRunnerGroup() { return getFJTaskRunner().getGroup(); } /** * Return true if current task has terminated or been cancelled. * The method is a simple analog of the Thread.isAlive() * method. However, it reports true only when the task has terminated * or has been cancelled. It does not distinguish these two cases. * And there is no way to determine whether a FJTask has been started * or is currently executing. **/ public final boolean isDone() { return done; } /** * Indicate termination. Intended only to be called by FJTaskRunner. * FJTasks themselves should use (non-final) method * cancel() to suppress execution. **/ protected final void setDone() { done = true; } /** * Set the termination status of this task. This simple-minded * analog of Thread.interrupt * causes the task not to execute if it has not already been started. * Cancelling a running FJTask * has no effect unless the run method itself uses isDone() * to probe cancellation and take appropriate action. * Individual run() methods may sense status and * act accordingly, normally by returning early. **/ public void cancel() { setDone(); } /** * Clear the termination status of this task. * This method is intended to be used * only as a means to allow task objects to be recycled. It should * be called only when you are sure that the previous * execution of this task has terminated and, if applicable, has * been joined by all other waiting tasks. Usage in any other * context is a very bad idea. **/ public void reset() { done = false; } /** * Execute this task. This method merely places the task in a * group-wide scheduling queue. * It will be run * the next time any TaskRunner thread is otherwise idle. * This scheduling maintains FIFO ordering of started tasks * with respect to * the group of worker threads. * @exception ClassCastException if caller thread is not * running in a FJTaskRunner thread. **/ public void start() { getFJTaskRunnerGroup().executeTask(this); } /** * Arrange for execution of a strictly dependent task. * The task that will be executed in * procedure-call-like LIFO order if executed by the * same worker thread, but is FIFO with respect to other tasks * forked by this thread when taken by other worker threads. * That is, earlier-forked * tasks are preferred to later-forked tasks by other idle workers. *

* Fork() is noticeably * faster than start(). However, it may only * be used for strictly dependent tasks -- generally, those that * could logically be issued as straight method calls without * changing the logic of the program. * The method is optimized for use in parallel fork/join designs * in which the thread that issues one or more forks * cannot continue until at least some of the forked * threads terminate and are joined. * @exception ClassCastException if caller thread is not * running in a FJTaskRunner thread. **/ public void fork() { getFJTaskRunner().push(this); } /** * Allow the current underlying FJTaskRunner thread to process other tasks. *

* Spinloops based on yield() are well behaved so long * as the event or condition being waited for is produced via another * FJTask. Additionally, you must never hold a lock * while performing a yield or join. (This is because * multiple FJTasks can be run by the same Thread during * a yield. Since java locks are held per-thread, the lock would not * maintain the conceptual exclusion you have in mind.) *

* Otherwise, spinloops using * yield are the main construction of choice when a task must wait * for a condition that it is sure will eventually occur because it * is being produced by some other FJTask. The most common * such condition is built-in: join() repeatedly yields until a task * has terminated after producing some needed results. You can also * use yield to wait for callbacks from other FJTasks, to wait for * status flags to be set, and so on. However, in all these cases, * you should be confident that the condition being waited for will * occur, essentially always because it is produced by * a FJTask generated by the current task, or one of its subtasks. * * @exception ClassCastException if caller thread is not * running in a FJTaskRunner thread. **/ public static void yield() { getFJTaskRunner().taskYield(); } /** * Yield until this task isDone. * Equivalent to while(!isDone()) yield(); * @exception ClassCastException if caller thread is not * running in a FJTaskRunner thread. **/ public void join() { getFJTaskRunner().taskJoin(this); } /** * Immediately execute task t by calling its run method. Has no * effect if t has already been run or has been cancelled. * It is equivalent to calling t.run except that it * deals with completion status, so should always be used * instead of directly calling run. * The method can be useful * when a computation has been packaged as a FJTask, but you just need to * directly execute its body from within some other task. **/ public static void invoke(FJTask t) { if (!t.isDone()) { t.run(); t.setDone(); } } /** * Fork both tasks and then wait for their completion. It behaves as: *

     * task1.fork(); task2.fork(); task2.join(); task1.join();
     * 
* As a simple classic example, here is * a class that computes the Fibonacci function: *
     * public class Fib extends FJTask {
     *
     *  // Computes fibonacci(n) = fibonacci(n-1) + fibonacci(n-2);  for n> 1
     *  //          fibonacci(0) = 0;
     *  //          fibonacci(1) = 1.
     *
     *  // Value to compute fibonacci function for.
     *  // It is replaced with the answer when computed.
     *  private volatile int number;
     *
     *  public Fib(int n) { number = n; }
     *
     *  public int getAnswer() {
     *    if (!isDone()) throw new Error("Not yet computed");
     *    return number;
     *  }
     *
     *  public void run() {
     *    int n = number;
     *    if (n > 1) {
     *      Fib f1 = new Fib(n - 1);
     *      Fib f2 = new Fib(n - 2);
     *
     *      coInvoke(f1, f2); // run these in parallel
     *
     *      // we know f1 and f2 are computed, so just directly access numbers
     *      number = f1.number + f2.number;
     *    }
     *  }
     *
     *  public static void main(String[] args) { // sample driver
     *    try {
     *      int groupSize = 2;    // 2 worker threads
     *      int num = 35;         // compute fib(35)
     *      FJTaskRunnerGroup group = new FJTaskRunnerGroup(groupSize);
     *      Fib f = new Fib(num);
     *      group.invoke(f);
     *      int result = f.getAnswer();
     *      System.out.println(" Answer: " + result);
     *    }
     *    catch (InterruptedException ex) {
     *      System.out.println("Interrupted");
     *    }
     *  }
     * }
     * 
* * @exception ClassCastException if caller thread is not * running in a FJTaskRunner thread. **/ public static void coInvoke(FJTask task1, FJTask task2) { getFJTaskRunner().coInvoke(task1, task2); } /** * Fork all tasks in array, and await their completion. * Behaviorally equivalent to: *
     * for (int i = 0; i < tasks.length; ++i) tasks[i].fork();
     * for (int i = 0; i < tasks.length; ++i) tasks[i].join();
     * 
**/ public static void coInvoke(FJTask[] tasks) { getFJTaskRunner().coInvoke(tasks); } /** * A FJTask that holds a Runnable r, and calls r.run when executed. * The class is a simple utilty to allow arbitrary Runnables * to be used as FJTasks. **/ public static class Wrap extends FJTask { protected final Runnable runnable; public Wrap(Runnable r) { runnable = r; } public void run() { runnable.run(); } } /** * A new Seq, when executed, * invokes each task provided in the constructor, in order. * The class is a simple utility * that makes it easier to create composite FJTasks. **/ public static class Seq extends FJTask { protected final FJTask[] tasks; /** * Construct a Seq that, when executed, will process each of the * tasks in the tasks array in order **/ public Seq(FJTask[] tasks) { this.tasks = tasks; } /** * Two-task constructor, for compatibility with previous release. **/ public Seq(FJTask task1, FJTask task2) { this.tasks = new FJTask[]{task1, task2}; } public void run() { for (int i = 0; i < tasks.length; ++i) FJTask.invoke(tasks[i]); } } /** * Construct and return a FJTask object that, when executed, will * invoke the tasks in the tasks array in array order **/ public static FJTask seq(FJTask[] tasks) { return new Seq(tasks); } /** * A new Par, when executed, * runs the tasks provided in the constructor in parallel using * coInvoke(tasks). * The class is a simple utility * that makes it easier to create composite FJTasks. **/ public static class Par extends FJTask { protected final FJTask[] tasks; /** * Construct a Seq that, when executed, will process each of the * tasks in the tasks array in parallel **/ public Par(FJTask[] tasks) { this.tasks = tasks; } /** * Two-task constructor, for compatibility with previous release. **/ public Par(FJTask task1, FJTask task2) { this.tasks = new FJTask[]{task1, task2}; } public void run() { FJTask.coInvoke(tasks); } } /** * Construct and return a FJTask object that, when executed, will * invoke the tasks in the tasks array in parallel using coInvoke **/ public static FJTask par(FJTask[] tasks) { return new Par(tasks); } /** * A new Seq2(task1, task2), when executed, * invokes task1 and then task2, in order. * The class is a simple utility * that makes it easier to create composite Tasks. **/ public static class Seq2 extends FJTask { protected final FJTask fst; protected final FJTask snd; public Seq2(FJTask task1, FJTask task2) { fst = task1; snd = task2; } public void run() { FJTask.invoke(fst); FJTask.invoke(snd); } } /** * Construct and return a FJTask object that, when executed, will * invoke task1 and task2, in order **/ public static FJTask seq(FJTask task1, FJTask task2) { return new Seq2(task1, task2); } /** * A new Par(task1, task2), when executed, * runs task1 and task2 in parallel using coInvoke(task1, task2). * The class is a simple utility * that makes it easier to create composite Tasks. **/ public static class Par2 extends FJTask { protected final FJTask fst; protected final FJTask snd; public Par2(FJTask task1, FJTask task2) { fst = task1; snd = task2; } public void run() { FJTask.coInvoke(fst, snd); } } /** * Construct and return a FJTask object that, when executed, will * invoke task1 and task2, in parallel **/ public static FJTask par(FJTask task1, FJTask task2) { return new Par2(task1, task2); } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/FJTaskRunner.java0000644000175000017500000007542410730503124030354 0ustar twernertwerner/* File: FJTaskRunner.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 7Jan1999 dl First public release 13Jan1999 dl correct a stat counter update; ensure inactive status on run termination; misc minor cleaup 14Jan1999 dl Use random starting point in scan; variable renamings. 18Jan1999 dl Runloop allowed to die on task exception; remove useless timed join 22Jan1999 dl Rework scan to allow use of priorities. 6Feb1999 dl Documentation updates. 7Mar1999 dl Add array-based coInvoke 31Mar1999 dl Revise scan to remove need for NullTasks 27Apr1999 dl Renamed 23oct1999 dl Earlier detect of interrupt in scanWhileIdling 24nov1999 dl Now works on JVMs that do not properly implement read-after-write of 2 volatiles. */ package org.logicalcobwebs.concurrent; import java.util.Random; /** * Specialized Thread subclass for running FJTasks. *

* Each FJTaskRunner keeps FJTasks in a double-ended queue (DEQ). * Double-ended queues support stack-based operations * push and pop, as well as queue-based operations put and take. * Normally, threads run their own tasks. But they * may also steal tasks from each others DEQs. *

* The algorithms are minor variants of those used * in Cilk and * Hood, and * to a lesser extent * Filaments, * but are adapted to work in Java. *

* The two most important capabilities are: *

* The push, pop, and put are designed to only ever called by the * current thread, and take (steal) is only ever called by * other threads. * All other operations are composites and variants of these, * plus a few miscellaneous bookkeeping methods. *

* Implementations of the underlying representations and operations * are geared for use on JVMs operating on multiple CPUs (although * they should of course work fine on single CPUs as well). *

* A possible snapshot of a FJTaskRunner's DEQ is: *

 *     0     1     2     3     4     5     6    ...
 *  +-----+-----+-----+-----+-----+-----+-----+--
 *  |     |  t  |  t  |  t  |  t  |     |     | ...  deq array
 *  +-----+-----+-----+-----+-----+-----+-----+--
 *           ^                       ^
 *          base                    top
 *   (incremented                     (incremented
 *       on take,                         on push
 *    decremented                     decremented
 *       on put)                          on pop)
 * 
*

* FJTasks are held in elements of the DEQ. * They are maintained in a bounded array that * works similarly to a circular bounded buffer. To ensure * visibility of stolen FJTasks across threads, the array elements * must be volatile. * Using volatile rather than synchronizing suffices here since * each task accessed by a thread is either one that it * created or one that has never seen before. Thus we cannot * encounter any staleness problems executing run methods, * although FJTask programmers must be still sure to either synch or use * volatile for shared data within their run methods. *

* However, since there is no way * to declare an array of volatiles in Java, the DEQ elements actually * hold VolatileTaskRef objects, each of which in turn holds a * volatile reference to a FJTask. * Even with the double-indirection overhead of * volatile refs, using an array for the DEQ works out * better than linking them since fewer shared * memory locations need to be * touched or modified by the threads while using the DEQ. * Further, the double indirection may alleviate cache-line * sharing effects (which cannot otherwise be directly dealt with in Java). *

* The indices for the base and top of the DEQ * are declared as volatile. The main contention point with * multiple FJTaskRunner threads occurs when one thread is trying * to pop its own stack while another is trying to steal from it. * This is handled via a specialization of Dekker's algorithm, * in which the popping thread pre-decrements top, * and then checks it against base. * To be conservative in the face of JVMs that only partially * honor the specification for volatile, the pop proceeds * without synchronization only if there are apparently enough * items for both a simultaneous pop and take to succeed. * It otherwise enters a * synchronized lock to check if the DEQ is actually empty, * if so failing. The stealing thread * does almost the opposite, but is set up to be less likely * to win in cases of contention: Steals always run under synchronized * locks in order to avoid conflicts with other ongoing steals. * They pre-increment base, and then check against * top. They back out (resetting the base index * and failing to steal) if the * DEQ is empty or is about to become empty by an ongoing pop. *

* A push operation can normally run concurrently with a steal. * A push enters a synch lock only if the DEQ appears full so must * either be resized or have indices adjusted due to wrap-around * of the bounded DEQ. The put operation always requires synchronization. *

* When a FJTaskRunner thread has no tasks of its own to run, * it tries to be a good citizen. * Threads run at lower priority while scanning for work. *

* If the task is currently waiting * via yield, the thread alternates scans (starting at a randomly * chosen victim) with Thread.yields. This is * well-behaved so long as the JVM handles Thread.yield in a * sensible fashion. (It need not. Thread.yield is so underspecified * that it is legal for a JVM to treat it as a no-op.) This also * keeps things well-behaved even if we are running on a uniprocessor * JVM using a simple cooperative threading model. *

* If a thread needing work is * is otherwise idle (which occurs only in the main runloop), and * there are no available tasks to steal or poll, it * instead enters into a sleep-based (actually timed wait(msec)) * phase in which it progressively sleeps for longer durations * (up to a maximum of FJTaskRunnerGroup.MAX_SLEEP_TIME, * currently 100ms) between scans. * If all threads in the group * are idling, they further progress to a hard wait phase, suspending * until a new task is entered into the FJTaskRunnerGroup entry queue. * A sleeping FJTaskRunner thread may be awakened by a new * task being put into the group entry queue or by another FJTaskRunner * becoming active, but not merely by some DEQ becoming non-empty. * Thus the MAX_SLEEP_TIME provides a bound for sleep durations * in cases where all but one worker thread start sleeping * even though there will eventually be work produced * by a thread that is taking a long time to place tasks in DEQ. * These sleep mechanics are handled in the FJTaskRunnerGroup class. *

* Composite operations such as taskJoin include heavy * manual inlining of the most time-critical operations * (mainly FJTask.invoke). * This opens up a few opportunities for further hand-optimizations. * Until Java compilers get a lot smarter, these tweaks * improve performance significantly enough for task-intensive * programs to be worth the poorer maintainability and code duplication. *

* Because they are so fragile and performance-sensitive, nearly * all methods are declared as final. However, nearly all fields * and methods are also declared as protected, so it is possible, * with much care, to extend functionality in subclasses. (Normally * you would also need to subclass FJTaskRunnerGroup.) *

* None of the normal java.lang.Thread class methods should ever be called * on FJTaskRunners. For this reason, it might have been nicer to * declare FJTaskRunner as a Runnable to run within a Thread. However, * this would have complicated many minor logistics. And since * no FJTaskRunner methods should normally be called from outside the * FJTask and FJTaskRunnerGroup classes either, this decision doesn't impact * usage. *

* You might think that layering this kind of framework on top of * Java threads, which are already several levels removed from raw CPU * scheduling on most systems, would lead to very poor performance. * But on the platforms * tested, the performance is quite good. *

[ Introduction to this package. ] * @see FJTask * @see FJTaskRunnerGroup **/ public class FJTaskRunner extends Thread { /** The group of which this FJTaskRunner is a member **/ protected final FJTaskRunnerGroup group; /** * Constructor called only during FJTaskRunnerGroup initialization **/ protected FJTaskRunner(FJTaskRunnerGroup g) { group = g; victimRNG = new Random(System.identityHashCode(this)); runPriority = getPriority(); setDaemon(true); } /** * Return the FJTaskRunnerGroup of which this thread is a member **/ protected final FJTaskRunnerGroup getGroup() { return group; } /* ------------ DEQ Representation ------------------- */ /** * FJTasks are held in an array-based DEQ with INITIAL_CAPACITY * elements. The DEQ is grown if necessary, but default value is * normally much more than sufficient unless there are * user programming errors or questionable operations generating * large numbers of Tasks without running them. * Capacities must be a power of two. **/ protected static final int INITIAL_CAPACITY = 4096; /** * The maximum supported DEQ capacity. * When exceeded, FJTaskRunner operations throw Errors **/ protected static final int MAX_CAPACITY = 1 << 30; /** * An object holding a single volatile reference to a FJTask. **/ protected final static class VolatileTaskRef { /** The reference **/ protected volatile FJTask ref; /** Set the reference **/ protected final void put(FJTask r) { ref = r; } /** Return the reference **/ protected final FJTask get() { return ref; } /** Return the reference and clear it **/ protected final FJTask take() { FJTask r = ref; ref = null; return r; } /** * Initialization utility for constructing arrays. * Make an array of given capacity and fill it with * VolatileTaskRefs. **/ protected static VolatileTaskRef[] newArray(int cap) { VolatileTaskRef[] a = new VolatileTaskRef[cap]; for (int k = 0; k < cap; k++) a[k] = new VolatileTaskRef(); return a; } } /** * The DEQ array. **/ protected VolatileTaskRef[] deq = VolatileTaskRef.newArray(INITIAL_CAPACITY); /** Current size of the task DEQ **/ protected int deqSize() { return deq.length; } /** * Current top of DEQ. Generally acts just like a stack pointer in an * array-based stack, except that it circularly wraps around the * array, as in an array-based queue. The value is NOT * always kept within 0 ... deq.length though. * The current top element is always at top & (deq.length-1). * To avoid integer overflow, top is reset down * within bounds whenever it is noticed to be out out bounds; * at worst when it is at 2 * deq.length. **/ protected volatile int top = 0; /** * Current base of DEQ. Acts like a take-pointer in an * array-based bounded queue. Same bounds and usage as top. **/ protected volatile int base = 0; /** * An extra object to synchronize on in order to * achieve a memory barrier. **/ protected final Object barrier = new Object(); /* ------------ Other BookKeeping ------------------- */ /** * Record whether current thread may be processing a task * (i.e., has been started and is not in an idle wait). * Accessed, under synch, ONLY by FJTaskRunnerGroup, but the field is * stored here for simplicity. **/ protected boolean active = false; /** Random starting point generator for scan() **/ protected final Random victimRNG; /** Priority to use while scanning for work **/ protected int scanPriority = FJTaskRunnerGroup.DEFAULT_SCAN_PRIORITY; /** Priority to use while running tasks **/ protected int runPriority; /** * Set the priority to use while scanning. * We do not bother synchronizing access, since * by the time the value is needed, both this FJTaskRunner * and its FJTaskRunnerGroup will * necessarily have performed enough synchronization * to avoid staleness problems of any consequence. **/ protected void setScanPriority(int pri) { scanPriority = pri; } /** * Set the priority to use while running tasks. * Same usage and rationale as setScanPriority. **/ protected void setRunPriority(int pri) { runPriority = pri; } /** * Compile-time constant for statistics gathering. * Even when set, reported values may not be accurate * since all are read and written without synchronization. **/ static final boolean COLLECT_STATS = true; // static final boolean COLLECT_STATS = false; // for stat collection /** Total number of tasks run **/ protected int runs = 0; /** Total number of queues scanned for work **/ protected int scans = 0; /** Total number of tasks obtained via scan **/ protected int steals = 0; /* ------------ DEQ operations ------------------- */ /** * Push a task onto DEQ. * Called ONLY by current thread. **/ protected final void push(final FJTask r) { int t = top; /* This test catches both overflows and index wraps. It doesn't really matter if base value is in the midst of changing in take. As long as deq length is < 2^30, we are guaranteed to catch wrap in time since base can only be incremented at most length times between pushes (or puts). */ if (t < (base & (deq.length - 1)) + deq.length) { deq[t & (deq.length - 1)].put(r); top = t + 1; } else // isolate slow case to increase chances push is inlined slowPush(r); // check overflow and retry } /** * Handle slow case for push **/ protected synchronized void slowPush(final FJTask r) { checkOverflow(); push(r); // just recurse -- this one is sure to succeed. } /** * Enqueue task at base of DEQ. * Called ONLY by current thread. * This method is currently not called from class FJTask. It could be used * as a faster way to do FJTask.start, but most users would * find the semantics too confusing and unpredictable. **/ protected final synchronized void put(final FJTask r) { for (; ;) { int b = base - 1; if (top < b + deq.length) { int newBase = b & (deq.length - 1); deq[newBase].put(r); base = newBase; if (b != newBase) { // Adjust for index underflow int newTop = top & (deq.length - 1); if (newTop < newBase) newTop += deq.length; top = newTop; } return; } else { checkOverflow(); // ... and retry } } } /** * Return a popped task, or null if DEQ is empty. * Called ONLY by current thread. *

* This is not usually called directly but is * instead inlined in callers. This version differs from the * cilk algorithm in that pop does not fully back down and * retry in the case of potential conflict with take. It simply * rechecks under synch lock. This gives a preference * for threads to run their own tasks, which seems to * reduce flailing a bit when there are few tasks to run. **/ protected final FJTask pop() { /* Decrement top, to force a contending take to back down. */ int t = --top; /* To avoid problems with JVMs that do not properly implement read-after-write of a pair of volatiles, we conservatively grab without lock only if the DEQ appears to have at least two elements, thus guaranteeing that both a pop and take will succeed, even if the pre-increment in take is not seen by current thread. Otherwise we recheck under synch. */ if (base + 1 < t) return deq[t & (deq.length - 1)].take(); else return confirmPop(t); } /** * Check under synch lock if DEQ is really empty when doing pop. * Return task if not empty, else null. **/ protected final synchronized FJTask confirmPop(int provisionalTop) { if (base <= provisionalTop) return deq[provisionalTop & (deq.length - 1)].take(); else { // was empty /* Reset DEQ indices to zero whenever it is empty. This both avoids unnecessary calls to checkOverflow in push, and helps keep the DEQ from accumulating garbage */ top = base = 0; return null; } } /** * Take a task from the base of the DEQ. * Always called by other threads via scan() **/ protected final synchronized FJTask take() { /* Increment base in order to suppress a contending pop */ int b = base++; if (b < top) return confirmTake(b); else { // back out base = b; return null; } } /** * double-check a potential take **/ protected FJTask confirmTake(int oldBase) { /* Use a second (guaranteed uncontended) synch to serve as a barrier in case JVM does not properly process read-after-write of 2 volatiles */ synchronized (barrier) { if (oldBase < top) { /* We cannot call deq[oldBase].take here because of possible races when nulling out versus concurrent push operations. Resulting accumulated garbage is swept out periodically in checkOverflow, or more typically, just by keeping indices zero-based when found to be empty in pop, which keeps active region small and constantly overwritten. */ return deq[oldBase & (deq.length - 1)].get(); } else { base = oldBase; return null; } } } /** * Adjust top and base, and grow DEQ if necessary. * Called only while DEQ synch lock being held. * We don't expect this to be called very often. In most * programs using FJTasks, it is never called. **/ protected void checkOverflow() { int t = top; int b = base; if (t - b < deq.length - 1) { // check if just need an index reset int newBase = b & (deq.length - 1); int newTop = top & (deq.length - 1); if (newTop < newBase) newTop += deq.length; top = newTop; base = newBase; /* Null out refs to stolen tasks. This is the only time we can safely do it. */ int i = newBase; while (i != newTop && deq[i].ref != null) { deq[i].ref = null; i = (i - 1) & (deq.length - 1); } } else { // grow by doubling array int newTop = t - b; int oldcap = deq.length; int newcap = oldcap * 2; if (newcap >= MAX_CAPACITY) throw new Error("FJTask queue maximum capacity exceeded"); VolatileTaskRef[] newdeq = new VolatileTaskRef[newcap]; // copy in bottom half of new deq with refs from old deq for (int j = 0; j < oldcap; ++j) newdeq[j] = deq[b++ & (oldcap - 1)]; // fill top half of new deq with new refs for (int j = oldcap; j < newcap; ++j) newdeq[j] = new VolatileTaskRef(); deq = newdeq; base = 0; top = newTop; } } /* ------------ Scheduling ------------------- */ /** * Do all but the pop() part of yield or join, by * traversing all DEQs in our group looking for a task to * steal. If none, it checks the entry queue. *

* Since there are no good, portable alternatives, * we rely here on a mixture of Thread.yield and priorities * to reduce wasted spinning, even though these are * not well defined. We are hoping here that the JVM * does something sensible. * @param waitingFor if non-null, the current task being joined **/ protected void scan(final FJTask waitingFor) { FJTask task = null; // to delay lowering priority until first failure to steal boolean lowered = false; /* Circularly traverse from a random start index. This differs slightly from cilk version that uses a random index for each attempted steal. Exhaustive scanning might impede analytic tractablity of the scheduling policy, but makes it much easier to deal with startup and shutdown. */ FJTaskRunner[] ts = group.getArray(); int idx = victimRNG.nextInt(ts.length); for (int i = 0; i < ts.length; ++i) { FJTaskRunner t = ts[idx]; if (++idx >= ts.length) idx = 0; // circularly traverse if (t != null && t != this) { if (waitingFor != null && waitingFor.isDone()) { break; } else { if (COLLECT_STATS) ++scans; task = t.take(); if (task != null) { if (COLLECT_STATS) ++steals; break; } else if (isInterrupted()) { break; } else if (!lowered) { // if this is first fail, lower priority lowered = true; setPriority(scanPriority); } else { // otherwise we are at low priority; just yield yield(); } } } } if (task == null) { if (COLLECT_STATS) ++scans; task = group.pollEntryQueue(); if (COLLECT_STATS) if (task != null) ++steals; } if (lowered) setPriority(runPriority); if (task != null && !task.isDone()) { if (COLLECT_STATS) ++runs; task.run(); task.setDone(); } } /** * Same as scan, but called when current thread is idling. * It repeatedly scans other threads for tasks, * sleeping while none are available. *

* This differs from scan mainly in that * since there is no reason to return to recheck any * condition, we iterate until a task is found, backing * off via sleeps if necessary. **/ protected void scanWhileIdling() { FJTask task = null; boolean lowered = false; long iters = 0; FJTaskRunner[] ts = group.getArray(); int idx = victimRNG.nextInt(ts.length); do { for (int i = 0; i < ts.length; ++i) { FJTaskRunner t = ts[idx]; if (++idx >= ts.length) idx = 0; // circularly traverse if (t != null && t != this) { if (COLLECT_STATS) ++scans; task = t.take(); if (task != null) { if (COLLECT_STATS) ++steals; if (lowered) setPriority(runPriority); group.setActive(this); break; } } } if (task == null) { if (isInterrupted()) return; if (COLLECT_STATS) ++scans; task = group.pollEntryQueue(); if (task != null) { if (COLLECT_STATS) ++steals; if (lowered) setPriority(runPriority); group.setActive(this); } else { ++iters; // Check here for yield vs sleep to avoid entering group synch lock if (iters >= group.SCANS_PER_SLEEP) { group.checkActive(this, iters); if (isInterrupted()) return; } else if (!lowered) { lowered = true; setPriority(scanPriority); } else { yield(); } } } } while (task == null); if (!task.isDone()) { if (COLLECT_STATS) ++runs; task.run(); task.setDone(); } } /* ------------ composite operations ------------------- */ /** * Main runloop **/ public void run() { try { while (!interrupted()) { FJTask task = pop(); if (task != null) { if (!task.isDone()) { // inline FJTask.invoke if (COLLECT_STATS) ++runs; task.run(); task.setDone(); } } else scanWhileIdling(); } } finally { group.setInactive(this); } } /** * Execute a task in this thread. Generally called when current task * cannot otherwise continue. **/ protected final void taskYield() { FJTask task = pop(); if (task != null) { if (!task.isDone()) { if (COLLECT_STATS) ++runs; task.run(); task.setDone(); } } else scan(null); } /** * Process tasks until w is done. * Equivalent to while(!w.isDone()) taskYield(); **/ protected final void taskJoin(final FJTask w) { while (!w.isDone()) { FJTask task = pop(); if (task != null) { if (!task.isDone()) { if (COLLECT_STATS) ++runs; task.run(); task.setDone(); if (task == w) return; // fast exit if we just ran w } } else scan(w); } } /** * A specialized expansion of * w.fork(); invoke(v); w.join(); **/ protected final void coInvoke(final FJTask w, final FJTask v) { // inline push int t = top; if (t < (base & (deq.length - 1)) + deq.length) { deq[t & (deq.length - 1)].put(w); top = t + 1; // inline invoke if (!v.isDone()) { if (COLLECT_STATS) ++runs; v.run(); v.setDone(); } // inline taskJoin while (!w.isDone()) { FJTask task = pop(); if (task != null) { if (!task.isDone()) { if (COLLECT_STATS) ++runs; task.run(); task.setDone(); if (task == w) return; // fast exit if we just ran w } } else scan(w); } } else // handle non-inlinable cases slowCoInvoke(w, v); } /** * Backup to handle noninlinable cases of coInvoke **/ protected void slowCoInvoke(final FJTask w, final FJTask v) { push(w); // let push deal with overflow FJTask.invoke(v); taskJoin(w); } /** * Array-based version of coInvoke **/ protected final void coInvoke(FJTask[] tasks) { int nforks = tasks.length - 1; // inline bulk push of all but one task int t = top; if (nforks >= 0 && t + nforks < (base & (deq.length - 1)) + deq.length) { for (int i = 0; i < nforks; ++i) { deq[t++ & (deq.length - 1)].put(tasks[i]); top = t; } // inline invoke of one task FJTask v = tasks[nforks]; if (!v.isDone()) { if (COLLECT_STATS) ++runs; v.run(); v.setDone(); } // inline taskJoins for (int i = 0; i < nforks; ++i) { FJTask w = tasks[i]; while (!w.isDone()) { FJTask task = pop(); if (task != null) { if (!task.isDone()) { if (COLLECT_STATS) ++runs; task.run(); task.setDone(); } } else scan(w); } } } else // handle non-inlinable cases slowCoInvoke(tasks); } /** * Backup to handle atypical or noninlinable cases of coInvoke **/ protected void slowCoInvoke(FJTask[] tasks) { for (int i = 0; i < tasks.length; ++i) push(tasks[i]); for (int i = 0; i < tasks.length; ++i) taskJoin(tasks[i]); } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/FJTaskRunnerGroup.java0000644000175000017500000005214010730503124031357 0ustar twernertwerner/* File: FJTaskRunnerGroup.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 7Jan1999 dl First public release 12Jan1999 dl made getActiveCount public; misc minor cleanup. 14Jan1999 dl Added executeTask 20Jan1999 dl Allow use of priorities; reformat stats 6Feb1999 dl Lazy thread starts 27Apr1999 dl Renamed */ package org.logicalcobwebs.concurrent; /** * A stripped down analog of a ThreadGroup used for * establishing and managing FJTaskRunner threads. * ThreadRunnerGroups serve as the control boundary separating * the general world of normal threads from the specialized world * of FJTasks. *

* By intent, this class does not subclass java.lang.ThreadGroup, and * does not support most methods found in ThreadGroups, since they * would make no sense for FJTaskRunner threads. In fact, the class * does not deal with ThreadGroups at all. If you want to restrict * a FJTaskRunnerGroup to a particular ThreadGroup, you can create * it from within that ThreadGroup. *

* The main contextual parameter for a FJTaskRunnerGroup is * the group size, established in the constructor. * Groups must be of a fixed size. * There is no way to dynamically increase or decrease the number * of threads in an existing group. *

* In general, the group size should be equal to the number * of CPUs on the system. (Unfortunately, there is no portable * means of automatically detecting the number of CPUs on a JVM, so there is * no good way to automate defaults.) In principle, when * FJTasks are used for computation-intensive tasks, having only * as many threads as CPUs should minimize bookkeeping overhead * and contention, and so maximize throughput. However, because * FJTaskRunners lie atop Java threads, and in turn operating system * thread support and scheduling policies, * it is very possible that using more threads * than CPUs will improve overall throughput even though it adds * to overhead. This will always be so if FJTasks are I/O bound. * So it may pay to experiment a bit when tuning on particular platforms. * You can also use setRunPriorities to either * increase or decrease the priorities of active threads, which * may interact with group size choice. *

* In any case, overestimating group sizes never * seriously degrades performance (at least within reasonable bounds). * You can also use a value * less than the number of CPUs in order to reserve processing * for unrelated threads. *

* There are two general styles for using a FJTaskRunnerGroup. * You can create one group per entire program execution, for example * as a static singleton, and use it for all parallel tasks: *

 * class Tasks {
 *   static FJTaskRunnerGroup group;
 *   public void initialize(int groupsize) {
 *      group = new FJTaskRunnerGroup(groupSize);
 *   }
 *   // ...
 * }
 * 
* Alternatively, you can make new groups on the fly and use them only for * particular task sets. This is more flexible,, * and leads to more controllable and deterministic execution patterns, * but it encounters greater overhead on startup. Also, to reclaim * system resources, you should * call FJTaskRunnerGroup.interruptAll when you are done * using one-shot groups. Otherwise, because FJTaskRunners set * Thread.isDaemon * status, they will not normally be reclaimed until program termination. *

* The main supported methods are execute, * which starts a task processed by FJTaskRunner threads, * and invoke, which starts one and waits for completion. * For example, you might extend the above FJTasks * class to support a task-based computation, say, the * Fib class from the FJTask documentation: *

 * class Tasks { // continued
 *   // ...
 *   static int fib(int n) {
 *     try {
 *       Fib f = new Fib(n);
 *       group.invoke(f);
 *       return f.getAnswer();
 *     }
 *     catch (InterruptedException ex) {
 *       throw new Error("Interrupted during computation");
 *     }
 *   }
 * }
 * 
*

* Method stats() can be used to monitor performance. * Both FJTaskRunnerGroup and FJTaskRunner may be compiled with * the compile-time constant COLLECT_STATS set to false. In this * case, various simple counts reported in stats() are not collected. * On platforms tested, * this leads to such a tiny performance improvement that there is * very little motivation to bother. * *

[ Introduction to this package. ] *

* @see FJTask * @see FJTaskRunner **/ public class FJTaskRunnerGroup implements Executor { /** The threads in this group **/ protected final FJTaskRunner[] threads; /** Group-wide queue for tasks entered via execute() **/ protected final LinkedQueue entryQueue = new LinkedQueue(); /** Number of threads that are not waiting for work **/ protected int activeCount = 0; /** Number of threads that have been started. Used to avoid unecessary contention during startup of task sets. **/ protected int nstarted = 0; /** * Compile-time constant. If true, various counts of * runs, waits, etc., are maintained. These are NOT * updated with synchronization, so statistics reports * might not be accurate. **/ static final boolean COLLECT_STATS = true; // static final boolean COLLECT_STATS = false; // for stats /** The time at which this ThreadRunnerGroup was constructed **/ long initTime = 0; /** Total number of executes or invokes **/ int entries = 0; static final int DEFAULT_SCAN_PRIORITY = Thread.MIN_PRIORITY + 1; /** * Create a FJTaskRunnerGroup with the indicated number * of FJTaskRunner threads. Normally, the best size to use is * the number of CPUs on the system. *

* The threads in a FJTaskRunnerGroup are created with their * isDaemon status set, so do not normally need to be * shut down manually upon program termination. **/ public FJTaskRunnerGroup(int groupSize) { threads = new FJTaskRunner[groupSize]; initializeThreads(); initTime = System.currentTimeMillis(); } /** * Arrange for execution of the given task * by placing it in a work queue. If the argument * is not of type FJTask, it is embedded in a FJTask via * FJTask.Wrap. * @exception InterruptedException if current Thread is * currently interrupted **/ public void execute(Runnable r) throws InterruptedException { if (r instanceof FJTask) { entryQueue.put((FJTask) r); } else { entryQueue.put(new FJTask.Wrap(r)); } signalNewTask(); } /** * Specialized form of execute called only from within FJTasks **/ public void executeTask(FJTask t) { try { entryQueue.put(t); signalNewTask(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } /** * Start a task and wait it out. Returns when the task completes. * @exception InterruptedException if current Thread is * interrupted before completion of the task. **/ public void invoke(Runnable r) throws InterruptedException { InvokableFJTask w = new InvokableFJTask(r); entryQueue.put(w); signalNewTask(); w.awaitTermination(); } /** * Try to shut down all FJTaskRunner threads in this group * by interrupting them all. This method is designed * to be used during cleanup when it is somehow known * that all threads are idle. * FJTaskRunners only * check for interruption when they are not otherwise * processing a task (and its generated subtasks, * if any), so if any threads are active, shutdown may * take a while, and may lead to unpredictable * task processing. **/ public void interruptAll() { // paranoically interrupt current thread last if in group. Thread current = Thread.currentThread(); boolean stopCurrent = false; for (int i = 0; i < threads.length; ++i) { Thread t = threads[i]; if (t == current) stopCurrent = true; else t.interrupt(); } if (stopCurrent) current.interrupt(); } /** * Set the priority to use while a FJTaskRunner is * polling for new tasks to perform. Default * is currently Thread.MIN_PRIORITY+1. The value * set may not go into effect immediately, but * will be used at least the next time a thread scans for work. **/ public synchronized void setScanPriorities(int pri) { for (int i = 0; i < threads.length; ++i) { FJTaskRunner t = threads[i]; t.setScanPriority(pri); if (!t.active) t.setPriority(pri); } } /** * Set the priority to use while a FJTaskRunner is * actively running tasks. Default * is the priority that was in effect by the thread that * constructed this FJTaskRunnerGroup. Setting this value * while threads are running may momentarily result in * them running at this priority even when idly waiting for work. **/ public synchronized void setRunPriorities(int pri) { for (int i = 0; i < threads.length; ++i) { FJTaskRunner t = threads[i]; t.setRunPriority(pri); if (t.active) t.setPriority(pri); } } /** Return the number of FJTaskRunner threads in this group **/ public int size() { return threads.length; } /** * Return the number of threads that are not idly waiting for work. * Beware that even active threads might not be doing any useful * work, but just spinning waiting for other dependent tasks. * Also, since this is just a snapshot value, some tasks * may be in the process of becoming idle. **/ public synchronized int getActiveCount() { return activeCount; } /** * Prints various snapshot statistics to System.out. *

*

* Cautions: Some statistics are updated and gathered * without synchronization, * so may not be accurate. However, reported counts may be considered * as lower bounds of actual values. * Some values may be zero if classes are compiled * with COLLECT_STATS set to false. (FJTaskRunner and FJTaskRunnerGroup * classes can be independently compiled with different values of * COLLECT_STATS.) Also, the counts are maintained as ints so could * overflow in exceptionally long-lived applications. *

* These statistics can be useful when tuning algorithms or diagnosing * problems. For example: *

**/ public void stats() { long time = System.currentTimeMillis() - initTime; double secs = ((double) time) / 1000.0; long totalRuns = 0; long totalScans = 0; long totalSteals = 0; System.out.print("Thread" + "\tQ Cap" + "\tScans" + "\tNew" + "\tRuns" + "\n"); for (int i = 0; i < threads.length; ++i) { FJTaskRunner t = threads[i]; int truns = t.runs; totalRuns += truns; int tscans = t.scans; totalScans += tscans; int tsteals = t.steals; totalSteals += tsteals; String star = (getActive(t)) ? "*" : " "; System.out.print("T" + i + star + "\t" + t.deqSize() + "\t" + tscans + "\t" + tsteals + "\t" + truns + "\n"); } System.out.print("Total" + "\t " + "\t" + totalScans + "\t" + totalSteals + "\t" + totalRuns + "\n"); System.out.print("Execute: " + entries); System.out.print("\tTime: " + secs); long rps = 0; if (secs != 0) rps = Math.round((double) (totalRuns) / secs); System.out.println("\tRate: " + rps); } /* ------------ Methods called only by FJTaskRunners ------------- */ /** * Return the array of threads in this group. * Called only by FJTaskRunner.scan(). **/ protected FJTaskRunner[] getArray() { return threads; } /** * Return a task from entry queue, or null if empty. * Called only by FJTaskRunner.scan(). **/ protected FJTask pollEntryQueue() { try { FJTask t = (FJTask) (entryQueue.poll(0)); return t; } catch (InterruptedException ex) { // ignore interrupts Thread.currentThread().interrupt(); return null; } } /** * Return active status of t. * Per-thread active status can only be accessed and * modified via synchronized method here in the group class. **/ protected synchronized boolean getActive(FJTaskRunner t) { return t.active; } /** * Set active status of thread t to true, and notify others * that might be waiting for work. **/ protected synchronized void setActive(FJTaskRunner t) { if (!t.active) { t.active = true; ++activeCount; if (nstarted < threads.length) threads[nstarted++].start(); else notifyAll(); } } /** * Set active status of thread t to false. **/ protected synchronized void setInactive(FJTaskRunner t) { if (t.active) { t.active = false; --activeCount; } } /** * The number of times to scan other threads for tasks * before transitioning to a mode where scans are * interleaved with sleeps (actually timed waits). * Upon transition, sleeps are for duration of * scans / SCANS_PER_SLEEP milliseconds. *

* This is not treated as a user-tunable parameter because * good values do not appear to vary much across JVMs or * applications. Its main role is to help avoid some * useless spinning and contention during task startup. **/ static final long SCANS_PER_SLEEP = 15; /** * The maximum time (in msecs) to sleep when a thread is idle, * yet others are not, so may eventually generate work that * the current thread can steal. This value reflects the maximum time * that a thread may sleep when it possibly should not, because there * are other active threads that might generate work. In practice, * designs in which some threads become stalled because others * are running yet not generating tasks are not likely to work * well in this framework anyway, so the exact value does not matter * too much. However, keeping it in the sub-second range does * help smooth out startup and shutdown effects. **/ static final long MAX_SLEEP_TIME = 100; /** * Set active status of thread t to false, and * then wait until: (a) there is a task in the entry * queue, or (b) other threads are active, or (c) the current * thread is interrupted. Upon return, it * is not certain that there will be work available. * The thread must itself check. *

* The main underlying reason * for these mechanics is that threads do not * signal each other when they add elements to their queues. * (This would add to task overhead, reduce locality. * and increase contention.) * So we must rely on a tamed form of polling. However, tasks * inserted into the entry queue do result in signals, so * tasks can wait on these if all of them are otherwise idle. **/ protected synchronized void checkActive(FJTaskRunner t, long scans) { setInactive(t); try { // if nothing available, do a hard wait if (activeCount == 0 && entryQueue.peek() == null) { wait(); } else { // If there is possibly some work, // sleep for a while before rechecking long msecs = scans / SCANS_PER_SLEEP; if (msecs > MAX_SLEEP_TIME) msecs = MAX_SLEEP_TIME; int nsecs = (msecs == 0) ? 1 : 0; // forces shortest possible sleep wait(msecs, nsecs); } } catch (InterruptedException ex) { notify(); // avoid lost notifies on interrupts Thread.currentThread().interrupt(); } } /* ------------ Utility methods ------------- */ /** * Start or wake up any threads waiting for work **/ protected synchronized void signalNewTask() { if (COLLECT_STATS) ++entries; if (nstarted < threads.length) threads[nstarted++].start(); else notify(); } /** * Create all FJTaskRunner threads in this group. **/ protected void initializeThreads() { for (int i = 0; i < threads.length; ++i) threads[i] = new FJTaskRunner(this); } /** * Wrap wait/notify mechanics around a task so that * invoke() can wait it out **/ protected static final class InvokableFJTask extends FJTask { protected final Runnable wrapped; protected boolean terminated = false; protected InvokableFJTask(Runnable r) { wrapped = r; } public void run() { try { if (wrapped instanceof FJTask) FJTask.invoke((FJTask) (wrapped)); else wrapped.run(); } finally { setTerminated(); } } protected synchronized void setTerminated() { terminated = true; notifyAll(); } protected synchronized void awaitTermination() throws InterruptedException { while (!terminated) wait(); } } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/FutureResult.java0000644000175000017500000001436710730503124030510 0ustar twernertwerner/* File: FutureResult.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 30Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; import java.lang.reflect.InvocationTargetException; /** * A class maintaining a single reference variable serving as the result * of an operation. The result cannot be accessed until it has been set. *

* Sample Usage

*

 * class ImageRenderer { Image render(byte[] raw); }
 * class App {
 *   Executor executor = ...
 *   ImageRenderer renderer = ...
 *   void display(byte[] rawimage) {
 *     try {
 *       FutureResult futureImage = new FutureResult();
 *       Runnable command = futureImage.setter(new Callable() {
 *          public Object call() { return renderer.render(rawImage); }
 *       });
 *       executor.execute(command);
 *       drawBorders();             // do other things while executing
 *       drawCaption();
 *       drawImage((Image)(futureImage.get())); // use future
 *     }
 *     catch (InterruptedException ex) { return; }
 *     catch (InvocationTargetException ex) { cleanup(); return; }
 *   }
 * }
 * 
*

[ Introduction to this package. ] * @see Executor **/ public class FutureResult { /** The result of the operation **/ protected Object value_ = null; /** Status -- true after first set **/ protected boolean ready_ = false; /** the exception encountered by operation producing result **/ protected InvocationTargetException exception_ = null; /** * Create an initially unset FutureResult **/ public FutureResult() { } /** * Return a Runnable object that, when run, will set the result value. * @param function - a Callable object whose result will be * held by this FutureResult. * @return A Runnable object that, when run, will call the * function and (eventually) set the result. **/ public Runnable setter(final Callable function) { return new Runnable() { public void run() { try { set(function.call()); } catch (Throwable ex) { setException(ex); } } }; } /** internal utility: either get the value or throw the exception **/ protected Object doGet() throws InvocationTargetException { if (exception_ != null) throw exception_; else return value_; } /** * Access the reference, waiting if necessary until it is ready. * @return current value * @exception InterruptedException if current thread has been interrupted * @exception InvocationTargetException if the operation * producing the value encountered an exception. **/ public synchronized Object get() throws InterruptedException, InvocationTargetException { while (!ready_) wait(); return doGet(); } /** * Wait at most msecs to access the reference. * @return current value * @exception TimeoutException if not ready after msecs * @exception InterruptedException if current thread has been interrupted * @exception InvocationTargetException if the operation * producing the value encountered an exception. **/ public synchronized Object timedGet(long msecs) throws TimeoutException, InterruptedException, InvocationTargetException { long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis(); long waitTime = msecs; if (ready_) return doGet(); else if (waitTime <= 0) throw new TimeoutException(msecs); else { for (; ;) { wait(waitTime); if (ready_) return doGet(); else { waitTime = msecs - (System.currentTimeMillis() - startTime); if (waitTime <= 0) throw new TimeoutException(msecs); } } } } /** * Set the reference, and signal that it is ready. It is not * considered an error to set the value more than once, * but it is not something you would normally want to do. * @param newValue The value that will be returned by a subsequent get(); **/ public synchronized void set(Object newValue) { value_ = newValue; ready_ = true; notifyAll(); } /** * Set the exception field, also setting ready status. * @param ex The exception. It will be reported out wrapped * within an InvocationTargetException **/ public synchronized void setException(Throwable ex) { exception_ = new InvocationTargetException(ex); ready_ = true; notifyAll(); } /** * Get the exception, or null if there isn't one (yet). * This does not wait until the future is ready, so should * ordinarily only be called if you know it is. * @return the exception encountered by the operation * setting the future, wrapped in an InvocationTargetException **/ public synchronized InvocationTargetException getException() { return exception_; } /** * Return whether the reference or exception have been set. * @return true if has been set. else false **/ public synchronized boolean isReady() { return ready_; } /** * Access the reference, even if not ready * @return current value **/ public synchronized Object peek() { return value_; } /** * Clear the value and exception and set to not-ready, * allowing this FutureResult to be reused. This is not * particularly recommended and must be done only * when you know that no other object is depending on the * properties of this FutureResult. **/ public synchronized void clear() { value_ = null; exception_ = null; ready_ = false; } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/LinkedNode.java0000644000175000017500000000161210730503124030040 0ustar twernertwerner/* File: LinkedNode.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version 25may2000 dl Change class access to public 26nov2001 dl Added no-arg constructor, all public access. */ package org.logicalcobwebs.concurrent; /** A standard linked list node used in various queue classes **/ public class LinkedNode { public Object value; public LinkedNode next; public LinkedNode() { } public LinkedNode(Object x) { value = x; } public LinkedNode(Object x, LinkedNode n) { value = x; next = n; } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/LinkedQueue.java0000644000175000017500000001300710730503124030240 0ustar twernertwerner/* File: LinkedQueue.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version 25aug1998 dl added peek 10dec1998 dl added isEmpty 10oct1999 dl lock on node object to ensure visibility */ package org.logicalcobwebs.concurrent; /** * A linked list based channel implementation. * The algorithm avoids contention between puts * and takes when the queue is not empty. * Normally a put and a take can proceed simultaneously. * (Although it does not allow multiple concurrent puts or takes.) * This class tends to perform more efficently than * other Channel implementations in producer/consumer * applications. *

[ Introduction to this package. ] **/ public class LinkedQueue implements Channel { /** * Dummy header node of list. The first actual node, if it exists, is always * at head_.next. After each take, the old first node becomes the head. **/ protected LinkedNode head_; /** * Helper monitor for managing access to last node. **/ protected final Object putLock_ = new Object(); /** * The last node of list. Put() appends to list, so modifies last_ **/ protected LinkedNode last_; /** * The number of threads waiting for a take. * Notifications are provided in put only if greater than zero. * The bookkeeping is worth it here since in reasonably balanced * usages, the notifications will hardly ever be necessary, so * the call overhead to notify can be eliminated. **/ protected int waitingForTake_ = 0; public LinkedQueue() { head_ = new LinkedNode(null); last_ = head_; } /** Main mechanics for put/offer **/ protected void insert(Object x) { synchronized (putLock_) { LinkedNode p = new LinkedNode(x); synchronized (last_) { last_.next = p; last_ = p; } if (waitingForTake_ > 0) putLock_.notify(); } } /** Main mechanics for take/poll **/ protected synchronized Object extract() { synchronized (head_) { Object x = null; LinkedNode first = head_.next; if (first != null) { x = first.value; first.value = null; head_ = first; } return x; } } public void put(Object x) throws InterruptedException { if (x == null) throw new IllegalArgumentException(); if (Thread.interrupted()) throw new InterruptedException(); insert(x); } public boolean offer(Object x, long msecs) throws InterruptedException { if (x == null) throw new IllegalArgumentException(); if (Thread.interrupted()) throw new InterruptedException(); insert(x); return true; } public Object take() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); // try to extract. If fail, then enter wait-based retry loop Object x = extract(); if (x != null) return x; else { synchronized (putLock_) { try { ++waitingForTake_; for (; ;) { x = extract(); if (x != null) { --waitingForTake_; return x; } else { putLock_.wait(); } } } catch (InterruptedException ex) { --waitingForTake_; putLock_.notify(); throw ex; } } } } public Object peek() { synchronized (head_) { LinkedNode first = head_.next; if (first != null) return first.value; else return null; } } public boolean isEmpty() { synchronized (head_) { return head_.next == null; } } public Object poll(long msecs) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Object x = extract(); if (x != null) return x; else { synchronized (putLock_) { try { long waitTime = msecs; long start = (msecs <= 0) ? 0 : System.currentTimeMillis(); ++waitingForTake_; for (; ;) { x = extract(); if (x != null || waitTime <= 0) { --waitingForTake_; return x; } else { putLock_.wait(waitTime); waitTime = msecs - (System.currentTimeMillis() - start); } } } catch (InterruptedException ex) { --waitingForTake_; putLock_.notify(); throw ex; } } } } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/Puttable.java0000644000175000017500000000507610730503124027614 0ustar twernertwerner/* File: Puttable.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * This interface exists to enable stricter type checking * for channels. A method argument or instance variable * in a producer object can be declared as only a Puttable * rather than a Channel, in which case a Java compiler * will disallow take operations. *

* Full method descriptions appear in the Channel interface. *

[ Introduction to this package. ] * @see Channel * @see Takable **/ public interface Puttable { /** * Place item in the channel, possibly waiting indefinitely until * it can be accepted. Channels implementing the BoundedChannel * subinterface are generally guaranteed to block on puts upon * reaching capacity, but other implementations may or may not block. * @param item the element to be inserted. Should be non-null. * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case the element is guaranteed not * to be inserted. Otherwise, on normal return, the element is guaranteed * to have been inserted. **/ public void put(Object item) throws InterruptedException; /** * Place item in channel only if it can be accepted within * msecs milliseconds. The time bound is interpreted in * a coarse-grained, best-effort fashion. * @param item the element to be inserted. Should be non-null. * @param msecs the number of milliseconds to wait. If less than * or equal to zero, the method does not perform any timed waits, * but might still require * access to a synchronization lock, which can impose unbounded * delay if there is a lot of contention for the channel. * @return true if accepted, else false * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case the element is guaranteed not * to be inserted (i.e., is equivalent to a false return). **/ public boolean offer(Object item, long msecs) throws InterruptedException; } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/ReadWriteLock.java0000644000175000017500000000454410730503124030532 0ustar twernertwerner/* File: ReadWriteLock.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * ReadWriteLocks maintain a pair of associated locks. * The readLock may be held simultanously by multiple * reader threads, so long as there are no writers. The writeLock * is exclusive. ReadWrite locks are generally preferable to * plain Sync locks or synchronized methods in cases where: *

* Different implementation classes differ in policies surrounding * which threads to prefer when there is * contention. By far, the most commonly useful policy is * WriterPreferenceReadWriteLock. The other implementations * are targeted for less common, niche applications. *

* Standard usage: *

 * class X {
 *   ReadWriteLock rw;
 *   // ...
 *
 *   public void read() throws InterruptedException {
 *     rw.readLock().acquire();
 *     try {
 *       // ... do the read
 *     }
 *     finally {
 *       rw.readlock().release()
 *     }
 *   }
 *
 *
 *   public void write() throws InterruptedException {
 *     rw.writeLock().acquire();
 *     try {
 *       // ... do the write
 *     }
 *     finally {
 *       rw.writelock().release()
 *     }
 *   }
 * }
 * 
* @see Sync *

[ Introduction to this package. ] **/ public interface ReadWriteLock { /** get the readLock **/ Sync readLock(); /** get the writeLock **/ Sync writeLock(); } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/ReaderPreferenceReadWriteLock.javalibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/ReaderPreferenceReadWriteLock.java0000644000175000017500000000200110730503124033636 0ustar twernertwerner/* File: ReaderPreferenceReadWriteLock.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * A ReadWriteLock that prefers waiting readers over * waiting writers when there is contention. The range of applicability * of this class is very limited. In the majority of situations, * writer preference locks provide more reasonable semantics. * *

[ Introduction to this package. ] **/ public class ReaderPreferenceReadWriteLock extends WriterPreferenceReadWriteLock { protected boolean allowReader() { return activeWriter_ == null; } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/Sync.java0000644000175000017500000002557410730503124026755 0ustar twernertwerner/* File: Sync.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version 5Aug1998 dl Added some convenient time constants */ package org.logicalcobwebs.concurrent; /** * Main interface for locks, gates, and conditions. *

* Sync objects isolate waiting and notification for particular * logical states, resource availability, events, and the like that are * shared across multiple threads. Use of Syncs sometimes * (but by no means always) adds flexibility and efficiency * compared to the use of plain java monitor methods * and locking, and are sometimes (but by no means always) * simpler to program with. *

* * Most Syncs are intended to be used primarily (although * not exclusively) in before/after constructions such as: *

 * class X {
 *   Sync gate;
 *   // ...
 *
 *   public void m() {
 *     try {
 *       gate.acquire();  // block until condition holds
 *       try {
 *         // ... method body
 *       }
 *       finally {
 *         gate.release()
 *       }
 *     }
 *     catch (InterruptedException ex) {
 *       // ... evasive action
 *     }
 *   }
 *
 *   public void m2(Sync cond) { // use supplied condition
 *     try {
 *       if (cond.attempt(10)) {         // try the condition for 10 ms
 *         try {
 *           // ... method body
 *         }
 *         finally {
 *           cond.release()
 *         }
 *       }
 *     }
 *     catch (InterruptedException ex) {
 *       // ... evasive action
 *     }
 *   }
 * }
 * 
* Syncs may be used in somewhat tedious but more flexible replacements * for built-in Java synchronized blocks. For example: *
 * class HandSynched {
 *   private double state_ = 0.0;
 *   private final Sync lock;  // use lock type supplied in constructor
 *   public HandSynched(Sync l) { lock = l; }
 *
 *   public void changeState(double d) {
 *     try {
 *       lock.acquire();
 *       try     { state_ = updateFunction(d); }
 *       finally { lock.release(); }
 *     }
 *     catch(InterruptedException ex) { }
 *   }
 *
 *   public double getState() {
 *     double d = 0.0;
 *     try {
 *       lock.acquire();
 *       try     { d = accessFunction(state_); }
 *       finally { lock.release(); }
 *     }
 *     catch(InterruptedException ex){}
 *     return d;
 *   }
 *   private double updateFunction(double d) { ... }
 *   private double accessFunction(double d) { ... }
 * }
 * 
* If you have a lot of such methods, and they take a common * form, you can standardize this using wrappers. Some of these * wrappers are standardized in LockedExecutor, but you can make others. * For example: *
 * class HandSynchedV2 {
 *   private double state_ = 0.0;
 *   private final Sync lock;  // use lock type supplied in constructor
 *   public HandSynchedV2(Sync l) { lock = l; }
 *
 *   protected void runSafely(Runnable r) {
 *     try {
 *       lock.acquire();
 *       try { r.run(); }
 *       finally { lock.release(); }
 *     }
 *     catch (InterruptedException ex) { // propagate without throwing
 *       Thread.currentThread().interrupt();
 *     }
 *   }
 *
 *   public void changeState(double d) {
 *     runSafely(new Runnable() {
 *       public void run() { state_ = updateFunction(d); }
 *     });
 *   }
 *   // ...
 * }
 * 
*

* One reason to bother with such constructions is to use deadlock- * avoiding back-offs when dealing with locks involving multiple objects. * For example, here is a Cell class that uses attempt to back-off * and retry if two Cells are trying to swap values with each other * at the same time. *

 * class Cell {
 *   long value;
 *   Sync lock = ... // some sync implementation class
 *   void swapValue(Cell other) {
 *     for (;;) {
 *       try {
 *         lock.acquire();
 *         try {
 *           if (other.lock.attempt(100)) {
 *             try {
 *               long t = value;
 *               value = other.value;
 *               other.value = t;
 *               return;
 *             }
 *             finally { other.lock.release(); }
 *           }
 *         }
 *         finally { lock.release(); }
 *       }
 *       catch (InterruptedException ex) { return; }
 *     }
 *   }
 * }
 *
*

* Here is an even fancier version, that uses lock re-ordering * upon conflict: *

 * class Cell {
 *   long value;
 *   Sync lock = ...;
 *   private static boolean trySwap(Cell a, Cell b) {
 *     a.lock.acquire();
 *     try {
 *       if (!b.lock.attempt(0))
 *         return false;
 *       try {
 *         long t = a.value;
 *         a.value = b.value;
 *         b.value = t;
 *         return true;
 *       }
 *       finally { other.lock.release(); }
 *     }
 *     finally { lock.release(); }
 *     return false;
 *   }
 *
 *  void swapValue(Cell other) {
 *    try {
 *      while (!trySwap(this, other) &&
 *            !tryswap(other, this))
 *        Thread.sleep(1);
 *    }
 *    catch (InterruptedException ex) { return; }
 *  }
 *}
 *
*

* Interruptions are in general handled as early as possible. * Normally, InterruptionExceptions are thrown * in acquire and attempt(msec) if interruption * is detected upon entry to the method, as well as in any * later context surrounding waits. * However, interruption status is ignored in release(); *

* Timed versions of attempt report failure via return value. * If so desired, you can transform such constructions to use exception * throws via *

 *   if (!c.attempt(timeval)) throw new TimeoutException(timeval);
 * 
*

* The TimoutSync wrapper class can be used to automate such usages. *

* All time values are expressed in milliseconds as longs, which have a maximum * value of Long.MAX_VALUE, or almost 300,000 centuries. It is not * known whether JVMs actually deal correctly with such extreme values. * For convenience, some useful time values are defined as static constants. *

* All implementations of the three Sync methods guarantee to * somehow employ Java synchronized methods or blocks, * and so entail the memory operations described in JLS * chapter 17 which ensure that variables are loaded and flushed * within before/after constructions. *

* Syncs may also be used in spinlock constructions. Although * it is normally best to just use acquire(), various forms * of busy waits can be implemented. For a simple example * (but one that would probably never be preferable to using acquire()): *

 * class X {
 *   Sync lock = ...
 *   void spinUntilAcquired() throws InterruptedException {
 *     // Two phase.
 *     // First spin without pausing.
 *     int purespins = 10;
 *     for (int i = 0; i < purespins; ++i) {
 *       if (lock.attempt(0))
 *         return true;
 *     }
 *     // Second phase - use timed waits
 *     long waitTime = 1; // 1 millisecond
 *     for (;;) {
 *       if (lock.attempt(waitTime))
 *         return true;
 *       else
 *         waitTime = waitTime * 3 / 2 + 1; // increase 50%
 *     }
 *   }
 * }
 * 
*

* In addition pure synchronization control, Syncs * may be useful in any context requiring before/after methods. * For example, you can use an ObservableSync * (perhaps as part of a LayeredSync) in order to obtain callbacks * before and after each method invocation for a given class. *

*

[ Introduction to this package. ] **/ public interface Sync { /** * Wait (possibly forever) until successful passage. * Fail only upon interuption. Interruptions always result in * `clean' failures. On failure, you can be sure that it has not * been acquired, and that no * corresponding release should be performed. Conversely, * a normal return guarantees that the acquire was successful. **/ public void acquire() throws InterruptedException; /** * Wait at most msecs to pass; report whether passed. *

* The method has best-effort semantics: * The msecs bound cannot * be guaranteed to be a precise upper bound on wait time in Java. * Implementations generally can only attempt to return as soon as possible * after the specified bound. Also, timers in Java do not stop during garbage * collection, so timeouts can occur just because a GC intervened. * So, msecs arguments should be used in * a coarse-grained manner. Further, * implementations cannot always guarantee that this method * will return at all without blocking indefinitely when used in * unintended ways. For example, deadlocks may be encountered * when called in an unintended context. *

* @param msecs the number of milleseconds to wait. * An argument less than or equal to zero means not to wait at all. * However, this may still require * access to a synchronization lock, which can impose unbounded * delay if there is a lot of contention among threads. * @return true if acquired **/ public boolean attempt(long msecs) throws InterruptedException; /** * Potentially enable others to pass. *

* Because release does not raise exceptions, * it can be used in `finally' clauses without requiring extra * embedded try/catch blocks. But keep in mind that * as with any java method, implementations may * still throw unchecked exceptions such as Error or NullPointerException * when faced with uncontinuable errors. However, these should normally * only be caught by higher-level error handlers. **/ public void release(); /** One second, in milliseconds; convenient as a time-out value **/ public static final long ONE_SECOND = 1000; /** One minute, in milliseconds; convenient as a time-out value **/ public static final long ONE_MINUTE = 60 * ONE_SECOND; /** One hour, in milliseconds; convenient as a time-out value **/ public static final long ONE_HOUR = 60 * ONE_MINUTE; /** One day, in milliseconds; convenient as a time-out value **/ public static final long ONE_DAY = 24 * ONE_HOUR; /** One week, in milliseconds; convenient as a time-out value **/ public static final long ONE_WEEK = 7 * ONE_DAY; /** One year in milliseconds; convenient as a time-out value **/ // Not that it matters, but there is some variation across // standard sources about value at msec precision. // The value used is the same as in java.util.GregorianCalendar public static final long ONE_YEAR = (long) (365.2425 * ONE_DAY); /** One century in milliseconds; convenient as a time-out value **/ public static final long ONE_CENTURY = 100 * ONE_YEAR; } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/SynchronizedInt.java0000644000175000017500000001347610730503124031171 0ustar twernertwerner/* File: SynchronizedInt.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 19Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * A class useful for offloading synch for int instance variables. * *

[ Introduction to this package. ] **/ public class SynchronizedInt extends SynchronizedVariable implements Comparable, Cloneable { protected int value_; /** * Make a new SynchronizedInt with the given initial value, * and using its own internal lock. **/ public SynchronizedInt(int initialValue) { super(); value_ = initialValue; } /** * Make a new SynchronizedInt with the given initial value, * and using the supplied lock. **/ public SynchronizedInt(int initialValue, Object lock) { super(lock); value_ = initialValue; } /** * Return the current value **/ public final int get() { synchronized (lock_) { return value_; } } /** * Set to newValue. * @return the old value **/ public int set(int newValue) { synchronized (lock_) { int old = value_; value_ = newValue; return old; } } /** * Set value to newValue only if it is currently assumedValue. * @return true if successful **/ public boolean commit(int assumedValue, int newValue) { synchronized (lock_) { boolean success = (assumedValue == value_); if (success) value_ = newValue; return success; } } /** * Atomically swap values with another SynchronizedInt. * Uses identityHashCode to avoid deadlock when * two SynchronizedInts attempt to simultaneously swap with each other. * (Note: Ordering via identyHashCode is not strictly guaranteed * by the language specification to return unique, orderable * values, but in practice JVMs rely on them being unique.) * @return the new value **/ public int swap(SynchronizedInt other) { if (other == this) return get(); SynchronizedInt fst = this; SynchronizedInt snd = other; if (System.identityHashCode(fst) > System.identityHashCode(snd)) { fst = other; snd = this; } synchronized (fst.lock_) { synchronized (snd.lock_) { fst.set(snd.set(fst.get())); return get(); } } } /** * Increment the value. * @return the new value **/ public int increment() { synchronized (lock_) { return ++value_; } } /** * Decrement the value. * @return the new value **/ public int decrement() { synchronized (lock_) { return --value_; } } /** * Add amount to value (i.e., set value += amount) * @return the new value **/ public int add(int amount) { synchronized (lock_) { return value_ += amount; } } /** * Subtract amount from value (i.e., set value -= amount) * @return the new value **/ public int subtract(int amount) { synchronized (lock_) { return value_ -= amount; } } /** * Multiply value by factor (i.e., set value *= factor) * @return the new value **/ public synchronized int multiply(int factor) { synchronized (lock_) { return value_ *= factor; } } /** * Divide value by factor (i.e., set value /= factor) * @return the new value **/ public int divide(int factor) { synchronized (lock_) { return value_ /= factor; } } /** * Set the value to the negative of its old value * @return the new value **/ public int negate() { synchronized (lock_) { value_ = -value_; return value_; } } /** * Set the value to its complement * @return the new value **/ public int complement() { synchronized (lock_) { value_ = ~value_; return value_; } } /** * Set value to value & b. * @return the new value **/ public int and(int b) { synchronized (lock_) { value_ = value_ & b; return value_; } } /** * Set value to value | b. * @return the new value **/ public int or(int b) { synchronized (lock_) { value_ = value_ | b; return value_; } } /** * Set value to value ^ b. * @return the new value **/ public int xor(int b) { synchronized (lock_) { value_ = value_ ^ b; return value_; } } public int compareTo(int other) { int val = get(); return (val < other) ? -1 : (val == other) ? 0 : 1; } public int compareTo(SynchronizedInt other) { return compareTo(other.get()); } public int compareTo(Object other) { return compareTo((SynchronizedInt) other); } public boolean equals(Object other) { if (other != null && other instanceof SynchronizedInt) return get() == ((SynchronizedInt) other).get(); else return false; } public int hashCode() { return get(); } public String toString() { return String.valueOf(get()); } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/SynchronizedVariable.java0000644000175000017500000001751210730503124032157 0ustar twernertwerner/* File: SynchronizedVariable.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 30Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * Base class for simple, small classes * maintaining single values that are always accessed * and updated under synchronization. Since defining them for only * some types seemed too arbitrary, they exist for all basic types, * although it is hard to imagine uses for some. *

* These classes mainly exist so that you do not have to go to the * trouble of writing your own miscellaneous classes and methods * in situations including: *

*

* While they cannot, by nature, share much code, * all of these classes work in the same way. *

* Construction
* Synchronized variables are always constructed holding an * initial value of the associated type. Constructors also * establish the lock to use for all methods: *

*

* Update methods
* Each class supports several kinds of update methods: *

*

* Guarded methods
* All Waitable subclasses provide notifications on * every value update, and support guarded methods of the form * whenpredicate, that wait until the * predicate hold, then optionally run any Runnable action * within the lock, and then return. All types support: *

* (If the action argument is null, these return immediately * after the predicate holds.) * Numerical types also support * * The Waitable classes are not always spectacularly efficient since they * provide notifications on all value changes. They are * designed for use in contexts where either performance is not an * overriding issue, or where nearly every update releases guarded * waits anyway. *

* Other methods
* This class implements Executor, and provides an execute * method that runs the runnable within the lock. *

* All classes except SynchronizedRef and WaitableRef implement * Cloneable and Comparable. * Implementations of the corresponding * methods either use default mechanics, or use methods that closely * correspond to their java.lang analogs. SynchronizedRef does not * implement any of these standard interfaces because there are * many cases where it would not make sense. However, you can * easily make simple subclasses that add the appropriate declarations. * *

* * * *

[ Introduction to this package. ] **/ public class SynchronizedVariable implements Executor { protected final Object lock_; /** Create a SynchronizedVariable using the supplied lock **/ public SynchronizedVariable(Object lock) { lock_ = lock; } /** Create a SynchronizedVariable using itself as the lock **/ public SynchronizedVariable() { lock_ = this; } /** * Return the lock used for all synchronization for this object **/ public Object getLock() { return lock_; } /** * If current thread is not interrupted, execute the given command * within this object's lock **/ public void execute(Runnable command) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); synchronized (lock_) { command.run(); } } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/Takable.java0000644000175000017500000000450010730503124027366 0ustar twernertwerner/* File: Takable.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version */ package org.logicalcobwebs.concurrent; /** * This interface exists to enable stricter type checking * for channels. A method argument or instance variable * in a consumer object can be declared as only a Takable * rather than a Channel, in which case a Java compiler * will disallow put operations. *

* Full method descriptions appear in the Channel interface. *

[ Introduction to this package. ] * @see Channel * @see Puttable **/ public interface Takable { /** * Return and remove an item from channel, * possibly waiting indefinitely until * such an item exists. * @return some item from the channel. Different implementations * may guarantee various properties (such as FIFO) about that item * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case state of the channel is unchanged. * **/ public Object take() throws InterruptedException; /** * Return and remove an item from channel only if one is available within * msecs milliseconds. The time bound is interpreted in a coarse * grained, best-effort fashion. * @param msecs the number of milliseconds to wait. If less than * or equal to zero, the operation does not perform any timed waits, * but might still require * access to a synchronization lock, which can impose unbounded * delay if there is a lot of contention for the channel. * @return some item, or null if the channel is empty. * @exception InterruptedException if the current thread has * been interrupted at a point at which interruption * is detected, in which case state of the channel is unchanged * (i.e., equivalent to a false return). **/ public Object poll(long msecs) throws InterruptedException; } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/TimeoutException.java0000644000175000017500000000260210730503124031331 0ustar twernertwerner/* File: TimeoutException.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 29Jun1998 dl Create public version 4Aug1998 dl Change to extend InterruptedException */ package org.logicalcobwebs.concurrent; /** * Thrown by synchronization classes that report * timeouts via exceptions. The exception is treated * as a form (subclass) of InterruptedException. This both * simplifies handling, and conceptually reflects the fact that * timed-out operations are artificially interrupted by timers. **/ public class TimeoutException extends InterruptedException { /** * The approximate time that the operation lasted before * this timeout exception was thrown. **/ public final long duration; /** * Constructs a TimeoutException with given duration value. **/ public TimeoutException(long time) { duration = time; } /** * Constructs a TimeoutException with the * specified duration value and detail message. */ public TimeoutException(long time, String message) { super(message); duration = time; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/WriterPreferenceReadWriteLock.javalibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/WriterPreferenceReadWriteLock.java0000644000175000017500000002524410730503124033726 0ustar twernertwerner/* File: WriterPreferenceReadWriteLock.java Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code. History: Date Who What 11Jun1998 dl Create public version 5Aug1998 dl replaced int counters with longs 25aug1998 dl record writer thread 3May1999 dl add notifications on interrupt/timeout */ package org.logicalcobwebs.concurrent; /** * A ReadWriteLock that prefers waiting writers over * waiting readers when there is contention. This class * is adapted from the versions described in CPJ, improving * on the ones there a bit by segregating reader and writer * wait queues, which is typically more efficient. *

* The locks are NOT reentrant. In particular, * even though it may appear to usually work OK, * a thread holding a read lock should not attempt to * re-acquire it. Doing so risks lockouts when there are * also waiting writers. *

[ Introduction to this package. ] **/ public class WriterPreferenceReadWriteLock implements ReadWriteLock { protected long activeReaders_ = 0; protected Thread activeWriter_ = null; protected long waitingReaders_ = 0; protected long waitingWriters_ = 0; protected final ReaderLock readerLock_ = new ReaderLock(); protected final WriterLock writerLock_ = new WriterLock(); public Sync writeLock() { return writerLock_; } public Sync readLock() { return readerLock_; } /* A bunch of small synchronized methods are needed to allow communication from the Lock objects back to this object, that serves as controller */ protected synchronized void cancelledWaitingReader() { --waitingReaders_; } protected synchronized void cancelledWaitingWriter() { --waitingWriters_; } /** Override this method to change to reader preference **/ protected boolean allowReader() { return activeWriter_ == null && waitingWriters_ == 0; } protected synchronized boolean startRead() { boolean allowRead = allowReader(); if (allowRead) ++activeReaders_; return allowRead; } protected synchronized boolean startWrite() { // The allowWrite expression cannot be modified without // also changing startWrite, so is hard-wired boolean allowWrite = (activeWriter_ == null && activeReaders_ == 0); if (allowWrite) activeWriter_ = Thread.currentThread(); return allowWrite; } /* Each of these variants is needed to maintain atomicity of wait counts during wait loops. They could be made faster by manually inlining each other. We hope that compilers do this for us though. */ protected synchronized boolean startReadFromNewReader() { boolean pass = startRead(); if (!pass) ++waitingReaders_; return pass; } protected synchronized boolean startWriteFromNewWriter() { boolean pass = startWrite(); if (!pass) ++waitingWriters_; return pass; } protected synchronized boolean startReadFromWaitingReader() { boolean pass = startRead(); if (pass) --waitingReaders_; return pass; } protected synchronized boolean startWriteFromWaitingWriter() { boolean pass = startWrite(); if (pass) --waitingWriters_; return pass; } /** * Called upon termination of a read. * Returns the object to signal to wake up a waiter, or null if no such **/ protected synchronized Signaller endRead() { if (--activeReaders_ == 0 && waitingWriters_ > 0) return writerLock_; else return null; } /** * Called upon termination of a write. * Returns the object to signal to wake up a waiter, or null if no such **/ protected synchronized Signaller endWrite() { activeWriter_ = null; if (waitingReaders_ > 0 && allowReader()) return readerLock_; else if (waitingWriters_ > 0) return writerLock_; else return null; } /** * Reader and Writer requests are maintained in two different * wait sets, by two different objects. These objects do not * know whether the wait sets need notification since they * don't know preference rules. So, each supports a * method that can be selected by main controlling object * to perform the notifications. This base class simplifies mechanics. **/ protected abstract class Signaller { // base for ReaderLock and WriterLock abstract void signalWaiters(); } protected class ReaderLock extends Signaller implements Sync { public void acquire() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); InterruptedException ie = null; synchronized (this) { if (!startReadFromNewReader()) { for (; ;) { try { ReaderLock.this.wait(); if (startReadFromWaitingReader()) return; } catch (InterruptedException ex) { cancelledWaitingReader(); ie = ex; break; } } } } if (ie != null) { // fall through outside synch on interrupt. // This notification is not really needed here, // but may be in plausible subclasses writerLock_.signalWaiters(); throw ie; } } public void release() { Signaller s = endRead(); if (s != null) s.signalWaiters(); } synchronized void signalWaiters() { ReaderLock.this.notifyAll(); } public boolean attempt(long msecs) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); InterruptedException ie = null; synchronized (this) { if (msecs <= 0) return startRead(); else if (startReadFromNewReader()) return true; else { long waitTime = msecs; long start = System.currentTimeMillis(); for (; ;) { try { ReaderLock.this.wait(waitTime); } catch (InterruptedException ex) { cancelledWaitingReader(); ie = ex; break; } if (startReadFromWaitingReader()) return true; else { waitTime = msecs - (System.currentTimeMillis() - start); if (waitTime <= 0) { cancelledWaitingReader(); break; } } } } } // safeguard on interrupt or timeout: writerLock_.signalWaiters(); if (ie != null) throw ie; else return false; // timed out } } protected class WriterLock extends Signaller implements Sync { public void acquire() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); InterruptedException ie = null; synchronized (this) { if (!startWriteFromNewWriter()) { for (; ;) { try { WriterLock.this.wait(); if (startWriteFromWaitingWriter()) return; } catch (InterruptedException ex) { cancelledWaitingWriter(); WriterLock.this.notify(); ie = ex; break; } } } } if (ie != null) { // Fall through outside synch on interrupt. // On exception, we may need to signal readers. // It is not worth checking here whether it is strictly necessary. readerLock_.signalWaiters(); throw ie; } } public void release() { Signaller s = endWrite(); if (s != null) s.signalWaiters(); } synchronized void signalWaiters() { WriterLock.this.notify(); } public boolean attempt(long msecs) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); InterruptedException ie = null; synchronized (this) { if (msecs <= 0) return startWrite(); else if (startWriteFromNewWriter()) return true; else { long waitTime = msecs; long start = System.currentTimeMillis(); for (; ;) { try { WriterLock.this.wait(waitTime); } catch (InterruptedException ex) { cancelledWaitingWriter(); WriterLock.this.notify(); ie = ex; break; } if (startWriteFromWaitingWriter()) return true; else { waitTime = msecs - (System.currentTimeMillis() - start); if (waitTime <= 0) { cancelledWaitingWriter(); WriterLock.this.notify(); break; } } } } } readerLock_.signalWaiters(); if (ie != null) throw ie; else return false; // timed out } } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/concurrent/package.html0000644000175000017500000000055410730503124027446 0ustar twernertwerner

Concurrency utilities.

Originally written by Doug Lea and released into the public domain. This may be used for any purposes whatsoever without acknowledgment. Thanks for the assistance and support of Sun Microsystems Labs, and everyone contributing, testing, and using this code.

libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/0000755000175000017500000000000011054125603024503 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/0000755000175000017500000000000011054125603025573 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jmx/0000755000175000017500000000000011054125603026371 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jmx/ConnectionPoolMBean.java0000644000175000017500000011460610730503124033076 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.jmx; import org.logicalcobwebs.proxool.resources.ResourceNamesIF; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolListenerIF; import org.logicalcobwebs.proxool.ConfigurationListenerIF; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanAttributeInfo; import javax.management.MBeanNotificationInfo; import javax.management.DynamicMBean; import javax.management.AttributeNotFoundException; import javax.management.MBeanException; import javax.management.ReflectionException; import javax.management.RuntimeOperationsException; import javax.management.Attribute; import javax.management.InvalidAttributeValueException; import javax.management.AttributeList; import javax.management.MBeanParameterInfo; import javax.management.NotificationBroadcaster; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationListener; import javax.management.NotificationFilter; import javax.management.ListenerNotFoundException; import javax.management.Notification; import javax.management.MBeanRegistration; import javax.management.ObjectName; import javax.management.MBeanServer; import java.util.Iterator; import java.util.ResourceBundle; import java.util.Properties; import java.util.StringTokenizer; import java.text.MessageFormat; /** * JMX DynamicMBean adapter for a Proxool connection pool.
* See the configuration documentation to learn * how to activate a pool for JMX. No programming is necessary to do this. *

* Attributes *

*

*

* Operations *

*

*

* Notifications *

*

* @version $Revision: 1.16 $, $Date: 2007/06/19 11:33:36 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ConnectionPoolMBean implements DynamicMBean, MBeanRegistration, NotificationBroadcaster, ProxoolListenerIF, ConfigurationListenerIF { /** * Notification type emitted when the pool definition is updated. */ public static final String NOTIFICATION_TYPE_DEFINITION_UPDATED = "proxool.definitionUpdated"; private static final Log LOG = LogFactory.getLog(ConnectionPoolMBean.class); private static final String CLASS_NAME = ConnectionPoolMBean.class.getName(); private static final String RECOURCE_NAME_MBEAN_POOL_DESCRIPTION = "mbean.pool.description"; private static final String RECOURCE_NAME_MBEAN_NOTIFICATION_DESCRIPTION = "mbean.notification.description"; private static final String RECOURCE_NAME_MBEAN_NOTIFICATION_DEF_UPDATED = "mbean.notification.defUpdated"; private static final String OPERATION_NAME_SHUTDOWN = "shutdown"; private static final ResourceBundle ATTRIBUTE_DESCRIPTIONS_RESOURCE = createAttributeDescriptionsResource(); private static final ResourceBundle JMX_RESOURCE = createJMXResource(); private static final MBeanNotificationInfo[] NOTIFICATION_INFOS = getNotificationInfos(); private MBeanInfo mBeanInfo; private ConnectionPoolDefinitionIF poolDefinition; private Properties poolProperties; private long definitionUpdatedSequence; private NotificationBroadcasterSupport notificationHelper = new NotificationBroadcasterSupport(); private boolean active; public ConnectionPoolMBean(String alias, Properties poolProperties) throws ProxoolException { this.poolDefinition = ProxoolFacade .getConnectionPoolDefinition(alias); this.poolProperties = poolProperties; this.mBeanInfo = getDynamicMBeanInfo(this.poolDefinition.getAlias()); ProxoolFacade.addProxoolListener(this); ProxoolFacade.addConfigurationListener(alias, this); } /** * @see javax.management.DynamicMBean#getAttribute(java.lang.String) */ public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { if (attributeName == null) { final String message = "Cannot invoke a getter of " + CLASS_NAME + " with null attribute name"; LOG.error(message); throw new RuntimeOperationsException(new IllegalArgumentException("Attribute name cannot be null"), message); } if (LOG.isDebugEnabled()) { LOG.debug("Getting attribute " + attributeName + "."); } return ((Attribute) getAttributes(new String[]{attributeName}).get(0)).getValue(); } /** * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute) */ public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { if (attribute == null) { final String message = "Cannot invoke a setter of " + CLASS_NAME + " with null attribute"; LOG.error(message); throw new RuntimeOperationsException(new IllegalArgumentException("Attribute cannot be null"), message); } if (LOG.isDebugEnabled()) { LOG.debug("Setting attribute " + attribute.getName() + "."); } final AttributeList attributeList = new AttributeList(); attributeList.add(attribute); setAttributes(attributeList); } /** * @see javax.management.DynamicMBean#getAttributes(java.lang.String[]) */ public AttributeList getAttributes(String[] attributeNames) { if (attributeNames == null) { final String message = "Cannot invoke a null getter of " + CLASS_NAME; LOG.error(message); throw new RuntimeOperationsException(new IllegalArgumentException("attributeNames[] cannot be null"), message); } AttributeList resultList = new AttributeList(); // if attributeNames is empty, return an empty result list if (attributeNames.length == 0) { return resultList; } // build the result attribute list for (int i = 0; i < attributeNames.length; i++) { try { if (equalsProperty(attributeNames[i], ProxoolConstants.ALIAS)) { resultList.add(new Attribute(attributeNames[i], this.poolDefinition.getAlias())); } else if (equalsProperty(attributeNames[i], ProxoolConstants.DRIVER_PROPERTIES)) { resultList.add(new Attribute(attributeNames[i], getDelegatePropertiesAsString(this.poolProperties))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.DRIVER_URL)) { resultList.add(new Attribute(attributeNames[i], this.poolDefinition.getUrl())); } else if (equalsProperty(attributeNames[i], ProxoolConstants.FATAL_SQL_EXCEPTION)) { resultList.add(new Attribute(attributeNames[i], getValueOrEmpty(this.poolProperties.getProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY)))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME)) { resultList.add(new Attribute(attributeNames[i], new Long(this.poolDefinition.getHouseKeepingSleepTime()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.HOUSE_KEEPING_TEST_SQL)) { resultList.add(new Attribute(attributeNames[i], getValueOrEmpty(poolDefinition.getHouseKeepingTestSql()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.TEST_BEFORE_USE)) { resultList.add(new Attribute(attributeNames[i], new Boolean(this.poolDefinition.isTestBeforeUse()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.TEST_AFTER_USE)) { resultList.add(new Attribute(attributeNames[i], new Boolean(this.poolDefinition.isTestAfterUse()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.MAXIMUM_ACTIVE_TIME)) { resultList.add(new Attribute(attributeNames[i], new Long(this.poolDefinition.getMaximumActiveTime()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.MAXIMUM_CONNECTION_COUNT)) { resultList.add(new Attribute(attributeNames[i], new Integer(this.poolDefinition.getMaximumConnectionCount()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME)) { resultList.add(new Attribute(attributeNames[i], new Long(this.poolDefinition.getMaximumConnectionLifetime()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.MAXIMUM_NEW_CONNECTIONS)) { resultList.add(new Attribute(attributeNames[i], new Integer(this.poolDefinition.getMaximumNewConnections()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE)) { resultList.add(new Attribute(attributeNames[i], new Integer(this.poolDefinition.getSimultaneousBuildThrottle()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.MINIMUM_CONNECTION_COUNT)) { resultList.add(new Attribute(attributeNames[i], new Integer(this.poolDefinition.getMinimumConnectionCount()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME)) { resultList.add(new Attribute(attributeNames[i], new Long(this.poolDefinition.getOverloadWithoutRefusalLifetime()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.PROTOTYPE_COUNT)) { resultList.add(new Attribute(attributeNames[i], new Integer(this.poolDefinition.getPrototypeCount()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.RECENTLY_STARTED_THRESHOLD)) { resultList.add(new Attribute(attributeNames[i], new Long(this.poolDefinition.getRecentlyStartedThreshold()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.STATISTICS)) { resultList.add(new Attribute(attributeNames[i], getValueOrEmpty(this.poolDefinition.getStatistics()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.STATISTICS_LOG_LEVEL)) { resultList.add(new Attribute(attributeNames[i], getValueOrEmpty(this.poolDefinition.getStatisticsLogLevel()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.TRACE)) { resultList.add(new Attribute(attributeNames[i], new Boolean(this.poolDefinition.isTrace()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.VERBOSE)) { resultList.add(new Attribute(attributeNames[i], new Boolean(this.poolDefinition.isVerbose()))); } else if (equalsProperty(attributeNames[i], ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS)) { resultList.add(new Attribute(attributeNames[i], getValueOrEmpty(this.poolDefinition.getFatalSqlExceptionWrapper()))); } else { final String message = "Unknown attribute: " + attributeNames[i]; LOG.error(message); throw new AttributeNotFoundException(message); } } catch (AttributeNotFoundException e) { throw new RuntimeOperationsException(new IllegalArgumentException(e.getMessage())); } } return resultList; } /** * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList) */ public AttributeList setAttributes(AttributeList attributes) { if (attributes == null) { final String message = "AttributeList attributes cannot be null"; LOG.error(message); throw new RuntimeOperationsException(new IllegalArgumentException(message), "Cannot invoke a setter of " + CLASS_NAME); } AttributeList resultList = new AttributeList(); if (attributes.isEmpty()) { return resultList; } String name = null; Object value = null; final Properties newProperties = new Properties(); Attribute attribute = null; for (Iterator i = attributes.iterator(); i.hasNext();) { attribute = (Attribute) i.next(); try { name = attribute.getName(); value = attribute.getValue(); if (equalsProperty(name, ProxoolConstants.DRIVER_PROPERTIES)) { if (!isEqualProperties(value.toString(), getDelegatePropertiesAsString(this.poolProperties))) { checkAssignable(name, String.class, value); setDelegateProperties(newProperties, value.toString()); resultList.add(new Attribute(name, value)); } } else if (equalsProperty(name, ProxoolConstants.DRIVER_URL)) { checkAssignable(name, String.class, value); if (notEmpty(value)) { newProperties.setProperty(ProxoolConstants.DRIVER_URL_PROPERTY, value.toString()); } else { newProperties.setProperty(ProxoolConstants.DRIVER_URL_PROPERTY, ""); } resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.FATAL_SQL_EXCEPTION)) { if (!isEqualProperties(value.toString(), this.poolProperties.getProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY))) { checkAssignable(name, String.class, value); if (notEmpty(value)) { newProperties.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, value.toString()); } else { newProperties.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, ""); } resultList.add(new Attribute(name, value)); } } else if (equalsProperty(name, ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME)) { setIntegerAttribute(name, ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_HOUSE_KEEPING_SLEEP_TIME, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.HOUSE_KEEPING_TEST_SQL)) { checkAssignable(name, String.class, value); if (notEmpty(value)) { newProperties.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, value.toString()); } else { newProperties.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, ""); } resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.TEST_BEFORE_USE)) { checkAssignable(name, Boolean.class, value); newProperties.setProperty(ProxoolConstants.TEST_BEFORE_USE_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.TEST_AFTER_USE)) { checkAssignable(name, Boolean.class, value); newProperties.setProperty(ProxoolConstants.TEST_AFTER_USE_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.MAXIMUM_ACTIVE_TIME)) { setIntegerAttribute(name, ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_ACTIVE_TIME, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.MAXIMUM_CONNECTION_COUNT)) { setIntegerAttribute(name, ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_CONNECTION_COUNT, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME)) { setIntegerAttribute(name, ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_CONNECTION_LIFETIME, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.MAXIMUM_NEW_CONNECTIONS)) { setIntegerAttribute(name, ProxoolConstants.MAXIMUM_NEW_CONNECTIONS_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_NEW_CONNECTIONS, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE)) { setIntegerAttribute(name, ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_SIMULTANEOUS_BUILD_THROTTLE, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.MINIMUM_CONNECTION_COUNT)) { checkAssignable(name, Integer.class, value); newProperties.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME)) { setIntegerAttribute(name, ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_OVERLOAD_WITHOUT_REFUSAL_THRESHOLD, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.PROTOTYPE_COUNT)) { checkAssignable(name, Integer.class, value); newProperties.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.RECENTLY_STARTED_THRESHOLD)) { setIntegerAttribute(name, ProxoolConstants.RECENTLY_STARTED_THRESHOLD_PROPERTY, value, ConnectionPoolDefinitionIF.DEFAULT_RECENTLY_STARTED_THRESHOLD, newProperties, resultList); } else if (equalsProperty(name, ProxoolConstants.STATISTICS)) { checkAssignable(name, String.class, value); if (notEmpty(value)) { newProperties.setProperty(ProxoolConstants.STATISTICS_PROPERTY, value.toString()); } else { newProperties.setProperty(ProxoolConstants.STATISTICS_PROPERTY, ""); } resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.STATISTICS_LOG_LEVEL)) { checkAssignable(name, String.class, value); if (notEmpty(value)) { newProperties.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, value.toString()); } else { newProperties.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ""); } resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.TRACE)) { checkAssignable(name, Boolean.class, value); newProperties.setProperty(ProxoolConstants.TRACE_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.VERBOSE)) { checkAssignable(name, Boolean.class, value); newProperties.setProperty(ProxoolConstants.VERBOSE_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else if (equalsProperty(name, ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS)) { checkAssignable(name, Boolean.class, value); newProperties.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, value.toString()); resultList.add(new Attribute(name, value)); } else { final String message = "Unknown attribute: " + name; LOG.error(message); throw new AttributeNotFoundException(message); } } catch (InvalidAttributeValueException e) { final String message = "Attribute value was illegal: " + e.getMessage(); LOG.error(message); throw new RuntimeOperationsException(new RuntimeException(message)); } catch (AttributeNotFoundException e) { throw new RuntimeOperationsException(new IllegalArgumentException(e.getMessage())); } } try { ProxoolFacade.updateConnectionPool(ProxoolConstants.PROPERTY_PREFIX + this.poolDefinition.getAlias(), newProperties); } catch (ProxoolException e) { LOG.error("Update of Proxool pool failed: ", e); throw new RuntimeOperationsException(new RuntimeException(e.getMessage())); } return resultList; } /** * @see javax.management.DynamicMBean#invoke(java.lang.String, java.lang.Object[], java.lang.String[]) */ public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException { if (operationName == null) { throw new RuntimeOperationsException(new IllegalArgumentException("Operation name cannot be null"), "Cannot invoke a null operation in " + CLASS_NAME); } else if (operationName.equals(OPERATION_NAME_SHUTDOWN)) { try { ProxoolFacade.removeConnectionPool(this.poolDefinition.getAlias()); } catch (ProxoolException e) { LOG.error("Shutdown of pool " + this.poolDefinition.getAlias() + " failed.", e); } return null; } else { throw new ReflectionException(new NoSuchMethodException(operationName), "Cannot find the operation " + operationName + "."); } } /** * @see javax.management.DynamicMBean#getMBeanInfo() */ public MBeanInfo getMBeanInfo() { return mBeanInfo; } private MBeanInfo getDynamicMBeanInfo(String alias) { final MBeanAttributeInfo[] attributeInfos = new MBeanAttributeInfo[]{ createProxoolAttribute(ProxoolConstants.ALIAS, String.class, false), createProxoolAttribute(ProxoolConstants.DRIVER_PROPERTIES, String.class), createProxoolAttribute(ProxoolConstants.DRIVER_URL, String.class), createProxoolAttribute(ProxoolConstants.FATAL_SQL_EXCEPTION, String.class), createProxoolAttribute(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME, Integer.class), createProxoolAttribute(ProxoolConstants.HOUSE_KEEPING_TEST_SQL, String.class), createProxoolAttribute(ProxoolConstants.TEST_BEFORE_USE, Boolean.class), createProxoolAttribute(ProxoolConstants.TEST_AFTER_USE, Boolean.class), createProxoolAttribute(ProxoolConstants.MAXIMUM_ACTIVE_TIME, Integer.class), createProxoolAttribute(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, Integer.class), createProxoolAttribute(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME, Integer.class), createProxoolAttribute(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE, Integer.class), createProxoolAttribute(ProxoolConstants.MINIMUM_CONNECTION_COUNT, Integer.class), createProxoolAttribute(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME, Integer.class), createProxoolAttribute(ProxoolConstants.PROTOTYPE_COUNT, Integer.class), createProxoolAttribute(ProxoolConstants.RECENTLY_STARTED_THRESHOLD, Integer.class), createProxoolAttribute(ProxoolConstants.STATISTICS, String.class), createProxoolAttribute(ProxoolConstants.STATISTICS_LOG_LEVEL, String.class), createProxoolAttribute(ProxoolConstants.TRACE, Boolean.class), createProxoolAttribute(ProxoolConstants.VERBOSE, Boolean.class), createProxoolAttribute(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS, String.class), }; final MBeanConstructorInfo[] constructorInfos = new MBeanConstructorInfo[]{ new MBeanConstructorInfo("ConnectionPoolMBean(): Construct a ConnectionPoolMBean object.", ConnectionPoolMBean.class.getConstructors()[0]) }; final MBeanOperationInfo[] operationInfos = new MBeanOperationInfo[]{ new MBeanOperationInfo(OPERATION_NAME_SHUTDOWN, "Stop and dispose this connection pool.", new MBeanParameterInfo[]{}, "void", MBeanOperationInfo.ACTION) }; return new MBeanInfo(CLASS_NAME, MessageFormat.format(getJMXText(RECOURCE_NAME_MBEAN_POOL_DESCRIPTION), new Object[]{alias}), attributeInfos, constructorInfos, operationInfos, new MBeanNotificationInfo[0]); } private static String getAttributeDescription(String attributeName) { String description = ""; if (ATTRIBUTE_DESCRIPTIONS_RESOURCE != null) { try { description = ATTRIBUTE_DESCRIPTIONS_RESOURCE.getString(attributeName); } catch (Exception e) { LOG.warn("Could not get description for attribute '" + attributeName + "' from resource " + ResourceNamesIF.ATTRIBUTE_DESCRIPTIONS + "."); } } return description; } private static String getJMXText(String key) { String value = ""; if (JMX_RESOURCE != null) { try { value = JMX_RESOURCE.getString(key); } catch (Exception e) { LOG.warn("Could not get value for attribute '" + key + "' from resource " + ResourceNamesIF.JMX + "."); } } return value; } private static ResourceBundle createAttributeDescriptionsResource() { try { return ResourceBundle.getBundle(ResourceNamesIF.ATTRIBUTE_DESCRIPTIONS); } catch (Exception e) { LOG.error("Could not find resource " + ResourceNamesIF.ATTRIBUTE_DESCRIPTIONS, e); } return null; } private static ResourceBundle createJMXResource() { try { return ResourceBundle.getBundle(ResourceNamesIF.JMX); } catch (Exception e) { LOG.error("Could not find resource " + ResourceNamesIF.JMX, e); } return null; } private static MBeanAttributeInfo createProxoolAttribute(String attributeName, Class type) { return createProxoolAttribute(attributeName, type, true); } private static MBeanAttributeInfo createProxoolAttribute(String attributeName, Class type, boolean writable) { return new MBeanAttributeInfo(ProxoolJMXHelper.getValidIdentifier(attributeName), type.getName(), getAttributeDescription(attributeName), true, writable, false); } private void checkAssignable(String name, Class clazz, Object value) throws InvalidAttributeValueException { if (value == null) { if (!String.class.equals(clazz)) { throw(new InvalidAttributeValueException("Cannot set attribute " + name + " to null " + " an instance of " + clazz.getName() + " expected.")); } } else { Class valueClass = value.getClass(); if (!clazz.isAssignableFrom(valueClass)) { throw(new InvalidAttributeValueException("Cannot set attribute " + name + " to a " + valueClass.getName() + " instance, " + clazz.getName() + " expected.")); } } } private boolean equalsProperty(String beanAttribute, String proxoolProperty) { return beanAttribute.equals(ProxoolJMXHelper.getValidIdentifier(proxoolProperty)); } private void setDelegateProperties(Properties properties, String propertyString) throws InvalidAttributeValueException { if (propertyString == null || propertyString.trim().length() == 0) { return; } StringTokenizer tokenizer = new StringTokenizer(propertyString, ","); String keyValuePair = null; int equalsIndex = -1; while (tokenizer.hasMoreElements()) { keyValuePair = tokenizer.nextToken().trim(); equalsIndex = keyValuePair.indexOf("="); if (equalsIndex != -1) { properties.put(keyValuePair.substring(0, equalsIndex).trim(), keyValuePair.substring(equalsIndex + 1).trim()); } else { throw new InvalidAttributeValueException("Could not find key/value delimiter '=' in property definition: '" + keyValuePair + "'."); } } } private String getDelegatePropertiesAsString(Properties properties) { final StringBuffer result = new StringBuffer(); Iterator keyIterator = properties.keySet().iterator(); String key = null; boolean first = true; while (keyIterator.hasNext()) { key = (String) keyIterator.next(); if (!key.startsWith(ProxoolConstants.PROPERTY_PREFIX)) { if (!first) { result.append(", "); } else { first = false; } result.append(key).append("=").append(properties.getProperty(key)); } } return result.toString(); } private boolean notEmpty(Object object) { return object != null && object.toString().trim().length() > 0; } private boolean notEmptyOrZero(Integer integer) { return integer != null && integer.intValue() > 0; } private String getValueOrEmpty(String property) { return property == null ? "" : property; } private void setIntegerAttribute(String attributeName, String propertyName, Object value, int defaultValue, Properties properties, AttributeList resultList) throws InvalidAttributeValueException { checkAssignable(attributeName, Integer.class, value); if (notEmptyOrZero((Integer) value)) { properties.setProperty(propertyName, value.toString()); resultList.add(new Attribute(attributeName, value)); } else { resultList.add(new Attribute(attributeName, new Integer(defaultValue))); } } private boolean isEqualProperties(String property1, String property2) { if (property1 == null) { return property2 == null; } else if (property2 == null) { return property1 == null; } else { return property1.equals(property2); } } private static MBeanNotificationInfo[] getNotificationInfos() { return new MBeanNotificationInfo[]{ new MBeanNotificationInfo( new String[]{NOTIFICATION_TYPE_DEFINITION_UPDATED}, Notification.class.getName(), getJMXText(RECOURCE_NAME_MBEAN_NOTIFICATION_DESCRIPTION)) }; } // Listener methods /** * Not used. * @see org.logicalcobwebs.proxool.ProxoolListenerIF#onRegistration(org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF, java.util.Properties) */ public void onRegistration(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo) { // Not used. } /** * If the given alias equals this pools alias: Unregister this JMX bean. * @see org.logicalcobwebs.proxool.ProxoolListenerIF#onShutdown(java.lang.String) */ public void onShutdown(String alias) { if (alias.equals(this.poolDefinition.getAlias())) { if (this.active) { this.active = false; ProxoolJMXHelper.unregisterPool(this.poolDefinition.getAlias(), this.poolProperties); LOG.info(this.poolDefinition.getAlias() + " MBean unregistered."); } } } /** * Update the attributes of this MBean and emit a {@link #NOTIFICATION_TYPE_DEFINITION_UPDATED} event. * @see org.logicalcobwebs.proxool.ConfigurationListenerIF#definitionUpdated(org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF, java.util.Properties, java.util.Properties) */ public void definitionUpdated(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo) { this.poolDefinition = connectionPoolDefinition; this.poolProperties = completeInfo; this.notificationHelper.sendNotification(new Notification(NOTIFICATION_TYPE_DEFINITION_UPDATED, this, definitionUpdatedSequence++, System.currentTimeMillis(), getJMXText(RECOURCE_NAME_MBEAN_NOTIFICATION_DEF_UPDATED))); } /** * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object) */ public void addNotificationListener(NotificationListener notificationListener, NotificationFilter notificationFilter, Object handBack) throws IllegalArgumentException { this.notificationHelper.addNotificationListener(notificationListener, notificationFilter, handBack); } /** * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener) */ public void removeNotificationListener(NotificationListener notificationListener) throws ListenerNotFoundException { this.notificationHelper.removeNotificationListener(notificationListener); } /** * @see javax.management.NotificationBroadcaster#getNotificationInfo() */ public MBeanNotificationInfo[] getNotificationInfo() { return NOTIFICATION_INFOS; } /** * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName) */ public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception { if (objectName == null) { throw new ProxoolException("objectName was null, but we can not construct an MBean instance without knowing" + " the pool alias."); } return objectName; } /** * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean) */ public void postRegister(Boolean success) { if (success.booleanValue() == true) { this.active = true; } } /** * @see javax.management.MBeanRegistration#preDeregister() */ public void preDeregister() throws Exception { this.active = false; } /** * @see javax.management.MBeanRegistration#postDeregister() */ public void postDeregister() { } } /* Revision history: $Log: ConnectionPoolMBean.java,v $ Revision 1.16 2007/06/19 11:33:36 billhorsman Changed time (millisecond) properties from int to long: maximumConnectionLifetime, houseKeepingSleepTime, recentlyStartedThreshold, overloadWithoutRefusalLifetime, maximumActiveTime Revision 1.15 2006/01/18 14:39:55 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.14 2003/10/20 07:37:07 chr32 Bettered handling of empty values. Now not setting attributes that has not changed. Revision 1.13 2003/09/30 18:38:27 billhorsman New properties Revision 1.12 2003/09/29 17:48:08 billhorsman New fatal-sql-exception-wrapper-class allows you to define what exception is used as a wrapper. This means that you can make it a RuntimeException if you need to. Revision 1.11 2003/09/14 21:29:31 chr32 Added support for wrap-fatal-sql-exceptions,statistics and statistics-log-level properties. Revision 1.10 2003/09/10 22:21:04 chr32 Removing > jdk 1.2 dependencies. Revision 1.9 2003/05/06 23:15:55 chr32 Moving JMX classes back in from sandbox. Revision 1.1 2003/03/07 16:35:17 billhorsman moved jmx stuff into sandbox until it is tested Revision 1.7 2003/03/05 23:28:56 billhorsman deprecated maximum-new-connections property in favour of more descriptive simultaneous-build-throttle Revision 1.6 2003/03/03 11:11:59 billhorsman fixed licence Revision 1.5 2003/02/26 19:04:30 chr32 Added active/inactive state check. Revision 1.4 2003/02/26 16:37:48 billhorsman fixed spelling in ConfigurationListenerIF Revision 1.3 2003/02/25 16:50:31 chr32 Added JMX notification and doc. Revision 1.2 2003/02/24 18:01:57 chr32 1st working version. Revision 1.1 2003/02/24 01:14:17 chr32 Init rev (unfinished). */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jmx/ProxoolJMXHelper.java0000644000175000017500000001601010730503124032411 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.jmx; import org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.MalformedObjectNameException; import java.util.Properties; import java.util.ArrayList; import java.util.StringTokenizer; import java.util.List; /** * Utilities for Proxool JMX instrumentation. * @version $Revision: 1.7 $, $Date: 2006/01/18 14:39:56 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ProxoolJMXHelper { private static final Log LOG = LogFactory.getLog(ProxoolJMXHelper.class); private ProxoolJMXHelper() { } /** * Create and register a {@link org.logicalcobwebs.proxool.admin.jmx.ConnectionPoolMBean} to the given agents. * Will log errors instead of throwing exceptions if one or more of the registrations fails. * @param poolPropeties the complete pool properties. * @throws org.logicalcobwebs.proxool.ProxoolException if the pool can not be found. */ public static void registerPool(String alias, Properties poolPropeties) throws ProxoolException { ConnectionPoolDefinitionIF connectionPoolDefinition = ProxoolFacade.getConnectionPoolDefinition(alias); String[] agentIds = getAgentIds(poolPropeties); ArrayList servers = null; for (int i = 0; i < agentIds.length; i++) { servers = MBeanServerFactory.findMBeanServer(agentIds[i]); if (servers == null || servers.size() < 1) { LOG.error("Could not register pool " + connectionPoolDefinition.getAlias() + " for JMX instrumentation" + " because lookup of MBeanServer using agent id " + agentIds[i] + " failed."); } else { MBeanServer mBeanServer = (MBeanServer) servers.get(0); ConnectionPoolMBean poolMBean = new ConnectionPoolMBean(alias, poolPropeties); try { mBeanServer.registerMBean(poolMBean, getObjectName(connectionPoolDefinition.getAlias())); LOG.info("Registered JMX MBean for pool " + connectionPoolDefinition.getAlias() + " in agent " + agentIds[i]); } catch (Exception e) { LOG.error("Registration of JMX MBean for pool " + connectionPoolDefinition.getAlias() + "in agent " + agentIds[i] + " failed.", e); } } } } /** * Unregister a {@link org.logicalcobwebs.proxool.admin.jmx.ConnectionPoolMBean} from the given agents. * Will log errors instead of throwing exceptions if one or more of the unregistrations fails. * @param poolPropeties the complete pool properties. */ public static void unregisterPool(String alias, Properties poolPropeties) { String[] agentIds = getAgentIds(poolPropeties); ArrayList servers = null; for (int i = 0; i < agentIds.length; i++) { servers = MBeanServerFactory.findMBeanServer(agentIds[i]); if (servers == null || servers.size() < 1) { LOG.error("Could not unregister MBean for pool " + alias + " because lookup of MBeanServer using agent id " + agentIds[i] + " failed."); } else { MBeanServer mBeanServer = (MBeanServer) servers.get(0); try { mBeanServer.unregisterMBean(getObjectName(alias)); LOG.info("Unregistered JMX MBean for pool " + alias + " in agent " + agentIds[i]); } catch (Exception e) { LOG.error("Unregistration of JMX MBean for pool " + alias + "in agent " + agentIds[i] + " failed.", e); } } } } /** * Get the prefered JMX object name for a Proxool pool. * @param alias the alias of the pool. * @return the generated object name. * @throws javax.management.MalformedObjectNameException if the creation of the object name fails. */ public static ObjectName getObjectName(String alias) throws MalformedObjectNameException { return new ObjectName("Proxool:type=Pool, name=" + alias); } private static String[] getAgentIds(Properties poolPropeties) { String idString = poolPropeties.getProperty(ProxoolConstants.JMX_AGENT_PROPERTY); if (idString == null || idString.trim().equals("")) { // null agent id means 'default agent' return new String[]{null}; } else { StringTokenizer tokenizer = new StringTokenizer(idString, ","); List tokens = new ArrayList(3); while (tokenizer.hasMoreElements()) { tokens.add(tokenizer.nextToken().trim()); } return (String[]) tokens.toArray(new String[tokens.size()]); } } /** * Generate a valid JMX identifier attribute name from a Proxool property name. * This basically involves changing all occurences of -<char> to * <uppercase char>.
* driver-properties will for instance become * driverProperties. * @param propertyName the name to be converted. * @return the converted attribute name. */ public static String getValidIdentifier(String propertyName) { if (propertyName.indexOf("-") == -1) { return propertyName; } else { StringBuffer buffer = new StringBuffer (propertyName); int index = -1; while ((index = buffer.toString().indexOf("-")) > -1) { buffer.deleteCharAt(index); buffer.setCharAt(index, Character.toUpperCase(buffer.charAt(index))); } return buffer.toString(); } } } /* Revision history: $Log: ProxoolJMXHelper.java,v $ Revision 1.7 2006/01/18 14:39:56 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.6 2003/05/06 23:15:56 chr32 Moving JMX classes back in from sandbox. Revision 1.1 2003/03/07 16:35:18 billhorsman moved jmx stuff into sandbox until it is tested Revision 1.4 2003/03/05 15:14:15 billhorsman fix for jdk 1.2 Revision 1.3 2003/03/03 11:12:00 billhorsman fixed licence Revision 1.2 2003/02/26 19:05:03 chr32 Added utility methods. Fixed mutiple servers bug. Revision 1.1 2003/02/24 18:01:29 chr32 Rewrite and renamed: ProxoolJMXHelper. Revision 1.1 2003/02/24 01:14:17 chr32 Init rev (unfinished). */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jmx/package.html0000644000175000017500000000035410730503124030652 0ustar twernertwerner Contains an MBean adapter to manage pools through JMX plus a utility to register/deregister these beans. See the configuration documentation to learn how to activate a pool for JMX. No programming is necessary to do this. libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jndi/0000755000175000017500000000000011054125603026517 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jndi/ProxoolJNDIHelper.java0000644000175000017500000000413210730503124032627 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.jndi; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolDataSource; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import java.util.Properties; /** * Utilities for Proxool JNDI operations. * @version $Revision: 1.3 $, $Date: 2004/06/17 21:33:12 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class ProxoolJNDIHelper { private ProxoolJNDIHelper() { } /** * Create a {@link org.logicalcobwebs.proxool.ProxoolDataSource} with the given alias * and bind it to JNDI using the given jndi properties. * @param jndiProperties the jndi related configuration properties. * @throws ProxoolException if the JNDI binding failes. */ public static void registerDatasource(String alias, Properties jndiProperties) throws ProxoolException { DataSource dataSource = new ProxoolDataSource(alias); final String jndiName = jndiProperties.getProperty(ProxoolConstants.JNDI_NAME); jndiProperties.remove(ProxoolConstants.JNDI_NAME); try { InitialContext initalContext = new InitialContext(jndiProperties); initalContext.rebind(jndiName, dataSource); } catch (NamingException e) { throw new ProxoolException("JNDI binding of DataSource for alias " + alias + " failed.", e); } } } /* Revision history: $Log: ProxoolJNDIHelper.java,v $ Revision 1.3 2004/06/17 21:33:12 billhorsman JavaDoc fix Revision 1.2 2004/03/18 17:13:48 chr32 Started using ProxoolDataSource instead of ProxoolManagedDataSource. Revision 1.1 2004/03/15 02:47:02 chr32 Added initial DataSource support. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/jndi/package.html0000644000175000017500000000033010730503124030772 0ustar twernertwerner Contains a helper that can create a Proxool datasource and bind it to JNDI. See the configuration documentation to learn how to register a DataSource for a pool. No programming is necessary to do this. libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/servlet/0000755000175000017500000000000011054125603027257 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/servlet/AdminServlet.java0000644000175000017500000011707310730607711032535 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.servlet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.*; import org.logicalcobwebs.proxool.admin.SnapshotIF; import org.logicalcobwebs.proxool.admin.StatisticsIF; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.Properties; /** * Use this to admin each pool within Proxool. It acts like a normal * servlet., so just configure it within your web app as you see fit. * For example, within web.xml: *
 *   <servlet>
 *       <servlet-name>Admin</servlet-name>
 *       <servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
 *       <init-param>
 *            <param-name>output</param-name>
 *            <param-value>full|simple</param-value>
 *        </init-param>
 *        <init-param>
 *            <param-name>cssFile</param-name>
 *            <param-value>/my_path/my.css</param-value>
 *        </init-param>
 *   </servlet>
 *   <servlet-mapping>
 *       <servlet-name>Admin</servlet-name>
 *       <url-pattern>/proxool</url-pattern>
 *   </servlet-mapping>
 * 
* * Options: * * * @author bill * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.16 $, $Date: 2007/12/14 23:20:41 $ * @since Proxool 0.7 */ public class AdminServlet extends HttpServlet { private static final Log LOG = LogFactory.getLog(AdminServlet.class); /** * The CSS class for a connection in different states: * */ private static final String[] STATUS_CLASSES = {"null", "available", "active", "offline"}; /** * OUtput full HTML including <HTML>, <HEAD> and <BODY> tags. * @see #output * @see AdminServlet configuration */ public static final String OUTPUT_FULL = "full"; /** * OUtput simple HTML excluding <HTML>, <HEAD> and <BODY> tags. * @see #output * @see AdminServlet configuration */ public static final String OUTPUT_SIMPLE = "simple"; /** * Either {@link #OUTPUT_FULL} (default) or {@link #OUTPUT_SIMPLE} * @see AdminServlet configuration */ private String output; /** * A valid URLL that can be linked to to override default, inline CSS. * @see AdminServlet configuration */ private String cssFile; /** * Used as part of the CSS class */ private static final String STATISTIC = "statistic"; /** * Used as part of the CSS class */ private static final String CORE_PROPERTY = "core-property"; /** * Used as part of the CSS class */ private static final String STANDARD_PROPERTY = "standard-property"; /** * Used as part of the CSS class */ private static final String DELEGATED_PROPERTY = "delegated-property"; /** * Used as part of the CSS class */ private static final String SNAPSHOT = "snapshot"; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); // Get output parameter. Default to OUTPUT_FULL. output = servletConfig.getInitParameter("output"); if (output != null) { if (output.equalsIgnoreCase(OUTPUT_FULL)) { output = OUTPUT_FULL; } else if (output.equalsIgnoreCase(OUTPUT_SIMPLE)) { output = OUTPUT_SIMPLE; } else { LOG.warn("Unrecognised output parameter for " + this.getClass().getName() + ". Expected: " + OUTPUT_FULL + " or " + OUTPUT_SIMPLE); output = null; } } if (output == null) { output = OUTPUT_FULL; } cssFile = servletConfig.getInitParameter("cssFile"); } /** * HH:mm:ss * @see #formatMilliseconds */ private static final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); /** * dd-MMM-yyyy HH:mm:ss */ private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); private static final String DETAIL = "detail"; private static final String DETAIL_MORE = "more"; private static final String DETAIL_LESS = "less"; /** * The request parameter name that defines: *
    *
  1. {@link #TAB_DEFINITION} (default)
  2. *
  3. {@link #TAB_SNAPSHOT}
  4. *
  5. {@link #TAB_STATISTICS}
  6. *
*/ private static final String TAB = "tab"; /** * @see #TAB */ private static final String TAB_DEFINITION = "definition"; /** * @see #TAB */ private static final String TAB_SNAPSHOT = "snapshot"; /** * @see #TAB */ private static final String TAB_STATISTICS = "statistics"; /** * The request parameter name that defines the pool */ private static final String ALIAS = "alias"; /** * If we are drilling down into a connection (on the {@link #TAB_SNAPSHOT snapshot} tab then * this points to the {@link org.logicalcobwebs.proxool.ProxyConnection#getId() ID} we are * getting detailed information for. */ private static final String CONNECTION_ID = "id"; /** * Delegate to {@link #doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)} */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } /** * Show the details for a pool. */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Pragma", "no-cache"); String link = request.getRequestURI(); // Check the alias and if not defined and there is only one // then use that. String alias = request.getParameter(ALIAS); // Check we can find the pool. ConnectionPoolDefinitionIF def = null; if (alias != null) { try { def = ProxoolFacade.getConnectionPoolDefinition(alias); } catch (ProxoolException e) { alias = null; } } String[] aliases = ProxoolFacade.getAliases(); if (alias == null) { if (aliases.length > 0) { alias = aliases[0]; } } if (def == null && alias != null) { try { def = ProxoolFacade.getConnectionPoolDefinition(alias); } catch (ProxoolException e) { throw new ServletException("Couldn't find pool with alias " + alias); } } String tab = request.getParameter(TAB); if (tab == null) { tab = TAB_DEFINITION; } // If we are showing the snapshot, are we showing it in detail or not? String snapshotDetail = request.getParameter(DETAIL); // If we are showing the snapshot, are we drilling down into a connection? String snapshotConnectionId = request.getParameter(CONNECTION_ID); try { if (output.equals(OUTPUT_FULL)) { response.setContentType("text/html"); openHtml(response.getOutputStream()); } response.getOutputStream().println("
Proxool " + Version.getVersion() + "
"); doList(response.getOutputStream(), alias, tab, link); // Skip everything if there aren't any pools if (aliases != null && aliases.length > 0) { StatisticsIF[] statisticsArray = ProxoolFacade.getStatistics(alias); final boolean statisticsAvailable = (statisticsArray != null && statisticsArray.length > 0); final boolean statisticsComingSoon = def.getStatistics() != null; // We can't be on the statistics tab if there are no statistics if (!statisticsComingSoon && tab.equals(TAB_STATISTICS)) { tab = TAB_DEFINITION; } doTabs(response.getOutputStream(), alias, link, tab, statisticsAvailable, statisticsComingSoon); if (tab.equals(TAB_DEFINITION)) { doDefinition(response.getOutputStream(), def); } else if (tab.equals(TAB_SNAPSHOT)) { doSnapshot(response.getOutputStream(), def, link, snapshotDetail, snapshotConnectionId); } else if (tab.equals(TAB_STATISTICS)) { doStatistics(response.getOutputStream(), statisticsArray, def); } else { throw new ServletException("Unrecognised tab '" + tab + "'"); } } } catch (ProxoolException e) { throw new ServletException("Problem serving Proxool Admin", e); } if (output.equals(OUTPUT_FULL)) { closeHtml(response.getOutputStream()); } } /** * Output the tabs that we are showing at the top of the page * @param out where to write the HTNL to * @param alias the current pool * @param link the URL to get back to this servlet * @param tab the active tab * @param statisticsAvailable whether statistics are available (true if configured and ready) * @param statisticsComingSoon whether statistics will be available (true if configured but not ready yet) */ private void doTabs(ServletOutputStream out, String alias, String link, String tab, boolean statisticsAvailable, boolean statisticsComingSoon) throws IOException { out.println(""); } /** * Output the statistics. If there are more than one set of statistics then show them all. * @param out where to write HTML to * @param statisticsArray the statistics we have ready to see * @param cpd defines the connection */ private void doStatistics(ServletOutputStream out, StatisticsIF[] statisticsArray, ConnectionPoolDefinitionIF cpd) throws IOException { for (int i = 0; i < statisticsArray.length; i++) { StatisticsIF statistics = statisticsArray[i]; openDataTable(out); printDefinitionEntry(out, ProxoolConstants.ALIAS, cpd.getAlias(), CORE_PROPERTY); // Period printDefinitionEntry(out, "Period", TIME_FORMAT.format(statistics.getStartDate()) + " to " + TIME_FORMAT.format(statistics.getStopDate()), STATISTIC); // Served printDefinitionEntry(out, "Served", statistics.getServedCount() + " (" + DECIMAL_FORMAT.format(statistics.getServedPerSecond()) + "/s)", STATISTIC); // Refused printDefinitionEntry(out, "Refused", statistics.getRefusedCount() + " (" + DECIMAL_FORMAT.format(statistics.getRefusedPerSecond()) + "/s)", STATISTIC); // averageActiveTime printDefinitionEntry(out, "Average active time", DECIMAL_FORMAT.format(statistics.getAverageActiveTime() / 1000) + "s", STATISTIC); // activityLevel StringBuffer activityLevelBuffer = new StringBuffer(); int activityLevel = (int) (100 * statistics.getAverageActiveCount() / cpd.getMaximumConnectionCount()); activityLevelBuffer.append(activityLevel); activityLevelBuffer.append("%
"); String[] colours = {"0000ff", "eeeeee"}; int[] lengths = {activityLevel, 100 - activityLevel}; drawBarChart(activityLevelBuffer, colours, lengths); printDefinitionEntry(out, "Activity level", activityLevelBuffer.toString(), STATISTIC); closeTable(out); } } /** * We can draw a bar chart simply enough. The two arrays passed as parameters must be of equal length * @param out where to write the HTML * @param colours the colur (CSS valid string) for each segment * @param lengths the length of each segment. Can be any size since the chart just takes up as much room * as possible as uses the relative length of each segment. */ private void drawBarChart(StringBuffer out, String[] colours, int[] lengths) { out.append(""); // Calculate total length int totalLength = 0; for (int i = 0; i < colours.length; i++) { totalLength += lengths[i]; } // Draw segments for (int j = 0; j < colours.length; j++) { String colour = colours[j]; int length = lengths[j]; if (length > 0) { out.append(""); } } out.append("
 
"); } /** * Output the {@link ConnectionPoolDefinitionIF definition} * @param out where to write the HTML * @param cpd the definition */ private void doDefinition(ServletOutputStream out, ConnectionPoolDefinitionIF cpd) throws IOException { openDataTable(out); /* TODO: it would be nice to have meta-data in the definition so that this is much easier. */ printDefinitionEntry(out, ProxoolConstants.ALIAS, cpd.getAlias(), CORE_PROPERTY); printDefinitionEntry(out, ProxoolConstants.DRIVER_URL, cpd.getUrl(), CORE_PROPERTY); printDefinitionEntry(out, ProxoolConstants.DRIVER_CLASS, cpd.getDriver(), CORE_PROPERTY); printDefinitionEntry(out, ProxoolConstants.MINIMUM_CONNECTION_COUNT, String.valueOf(cpd.getMinimumConnectionCount()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.MAXIMUM_CONNECTION_COUNT, String.valueOf(cpd.getMaximumConnectionCount()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.PROTOTYPE_COUNT, cpd.getPrototypeCount() > 0 ? String.valueOf(cpd.getPrototypeCount()) : null, STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE, String.valueOf(cpd.getSimultaneousBuildThrottle()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME, formatMilliseconds(cpd.getMaximumConnectionLifetime()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.MAXIMUM_ACTIVE_TIME, formatMilliseconds(cpd.getMaximumActiveTime()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME, (cpd.getHouseKeepingSleepTime() / 1000) + "s", STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.HOUSE_KEEPING_TEST_SQL, cpd.getHouseKeepingTestSql(), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.TEST_BEFORE_USE, String.valueOf(cpd.isTestBeforeUse()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.TEST_AFTER_USE, String.valueOf(cpd.isTestAfterUse()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.RECENTLY_STARTED_THRESHOLD, formatMilliseconds(cpd.getRecentlyStartedThreshold()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME, formatMilliseconds(cpd.getOverloadWithoutRefusalLifetime()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.INJECTABLE_CONNECTION_INTERFACE_NAME, String.valueOf(cpd.getInjectableConnectionInterface()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.INJECTABLE_STATEMENT_INTERFACE_NAME, String.valueOf(cpd.getInjectableStatementInterface()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME, String.valueOf(cpd.getInjectableCallableStatementInterface()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME, String.valueOf(cpd.getInjectablePreparedStatementInterface()), STANDARD_PROPERTY); // fatalSqlExceptions String fatalSqlExceptions = null; if (cpd.getFatalSqlExceptions() != null && cpd.getFatalSqlExceptions().size() > 0) { StringBuffer fatalSqlExceptionsBuffer = new StringBuffer(); Iterator i = cpd.getFatalSqlExceptions().iterator(); while (i.hasNext()) { String s = (String) i.next(); fatalSqlExceptionsBuffer.append(s); fatalSqlExceptionsBuffer.append(i.hasNext() ? ", " : ""); } fatalSqlExceptions = fatalSqlExceptionsBuffer.toString(); } printDefinitionEntry(out, ProxoolConstants.FATAL_SQL_EXCEPTION, fatalSqlExceptions, STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS, cpd.getFatalSqlExceptionWrapper(), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.STATISTICS, cpd.getStatistics(), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.STATISTICS_LOG_LEVEL, cpd.getStatisticsLogLevel(), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.VERBOSE, String.valueOf(cpd.isVerbose()), STANDARD_PROPERTY); printDefinitionEntry(out, ProxoolConstants.TRACE, String.valueOf(cpd.isTrace()), STANDARD_PROPERTY); // Now all the properties that are forwarded to the delegate driver. Properties p = cpd.getDelegateProperties(); Iterator i = p.keySet().iterator(); while (i.hasNext()) { String name = (String) i.next(); String value = p.getProperty(name); // Better hide the password! if (name.toLowerCase().indexOf("password") > -1 || name.toLowerCase().indexOf("passwd") > -1) { value = "******"; } printDefinitionEntry(out, name + " (delegated)", value, DELEGATED_PROPERTY); } closeTable(out); } /** * Output a {@link SnapshotIF snapshot} of the pool. * @param out where to write the HTML * @param cpd defines the pool * @param link the URL back to this servlet * @param level either {@link #DETAIL_LESS} or {@link #DETAIL_MORE} * @param connectionId the connection we want to drill into (optional) */ private void doSnapshot(ServletOutputStream out, ConnectionPoolDefinitionIF cpd, String link, String level, String connectionId) throws IOException, ProxoolException { boolean detail = (level != null && level.equals(DETAIL_MORE)); SnapshotIF snapshot = ProxoolFacade.getSnapshot(cpd.getAlias(), detail); if (snapshot != null) { openDataTable(out); printDefinitionEntry(out, ProxoolConstants.ALIAS, cpd.getAlias(), CORE_PROPERTY); // dateStarted printDefinitionEntry(out, "Start date", DATE_FORMAT.format(snapshot.getDateStarted()), SNAPSHOT); // snapshot date printDefinitionEntry(out, "Snapshot", TIME_FORMAT.format(snapshot.getSnapshotDate()), SNAPSHOT); // connections StringBuffer connectionsBuffer = new StringBuffer(); connectionsBuffer.append(snapshot.getActiveConnectionCount()); connectionsBuffer.append(" (active), "); connectionsBuffer.append(snapshot.getAvailableConnectionCount()); connectionsBuffer.append(" (available), "); if (snapshot.getOfflineConnectionCount() > 0) { connectionsBuffer.append(snapshot.getOfflineConnectionCount()); connectionsBuffer.append(" (offline), "); } connectionsBuffer.append(snapshot.getMaximumConnectionCount()); connectionsBuffer.append(" (max)
"); String[] colours = {"ff9999", "66cc66", "cccccc"}; int[] lengths = {snapshot.getActiveConnectionCount(), snapshot.getAvailableConnectionCount(), snapshot.getMaximumConnectionCount() - snapshot.getActiveConnectionCount() - snapshot.getAvailableConnectionCount()}; drawBarChart(connectionsBuffer, colours, lengths); printDefinitionEntry(out, "Connections", connectionsBuffer.toString(), SNAPSHOT); // servedCount printDefinitionEntry(out, "Served", String.valueOf(snapshot.getServedCount()), SNAPSHOT); // refusedCount printDefinitionEntry(out, "Refused", String.valueOf(snapshot.getRefusedCount()), SNAPSHOT); if (!detail) { out.println(" "); out.print("
"); out.print(""); out.print(""); out.print(""); out.print(""); out.println("
"); out.println(" "); } else { out.println(" "); out.print(" "); out.print("Details:
(click ID to drill down)"); out.println(""); out.print(" "); doSnapshotDetails(out, cpd, snapshot, link, connectionId); out.println(""); out.println(" "); long drillDownConnectionId; if (connectionId != null) { drillDownConnectionId = Long.valueOf(connectionId).longValue(); ConnectionInfoIF drillDownConnection = snapshot.getConnectionInfo(drillDownConnectionId); if (drillDownConnection != null) { out.println(" "); out.print(" "); out.print("Connection #" + connectionId); out.println(""); out.print(" "); doDrillDownConnection(out, drillDownConnection); out.println(""); out.println(" "); } } out.println(" "); out.print("
"); out.print(""); out.print(""); out.print(""); out.print(""); out.println("
"); out.println(" "); } closeTable(out); } } /** * If we want a {@link #DETAIL_MORE more} detailed {@link SnapshotIF snapshot} then {@link #doSnapshot(javax.servlet.ServletOutputStream, org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF, String, String, String)} * calls this too * @param out where to write the HTML * @param cpd defines the pool * @param snapshot snapshot * @param link the URL back to this servlet * @param connectionId the connection we want to drill into (optional) * @param connectionId * @throws IOException */ private void doSnapshotDetails(ServletOutputStream out, ConnectionPoolDefinitionIF cpd, SnapshotIF snapshot, String link, String connectionId) throws IOException { long drillDownConnectionId = 0; if (connectionId != null) { drillDownConnectionId = Long.valueOf(connectionId).longValue(); } if (snapshot.getConnectionInfos() != null && snapshot.getConnectionInfos().length > 0) { out.println(""); out.println(" "); out.print(""); out.print(""); out.print(""); out.print(""); out.print(""); out.print(""); out.print(""); ConnectionInfoIF[] connectionInfos = snapshot.getConnectionInfos(); for (int i = 0; i < connectionInfos.length; i++) { ConnectionInfoIF connectionInfo = connectionInfos[i]; if (connectionInfo.getStatus() != ConnectionInfoIF.STATUS_NULL) { out.print(""); // drillDownConnectionId out.print(""); // birth out.print(""); // started out.print(""); // active out.print(""); // requester out.print(""); out.println(""); } } out.println(" "); out.println("
#bornlast
start
lap
(ms)
 thread
"); out.print(connectionInfo.getId()); } else { out.print("border: 1px solid transparent;"); out.print("\">"); out.print(connectionInfo.getId()); out.print(""); } out.print(" "); out.print(TIME_FORMAT.format(connectionInfo.getBirthDate())); out.print(" "); out.print(connectionInfo.getTimeLastStartActive() > 0 ? TIME_FORMAT.format(new Date(connectionInfo.getTimeLastStartActive())) : "-"); out.print(""); String active = " "; if (connectionInfo.getTimeLastStopActive() > 0) { active = String.valueOf((int) (connectionInfo.getTimeLastStopActive() - connectionInfo.getTimeLastStartActive())); } else if (connectionInfo.getTimeLastStartActive() > 0) { active = String.valueOf((int) (snapshot.getSnapshotDate().getTime() - connectionInfo.getTimeLastStartActive())); } out.print(active); out.print("   "); out.print(connectionInfo.getRequester() != null ? connectionInfo.getRequester() : "-"); out.print("
"); } else { out.println("No connections yet"); } } /** * What CSS class to use for a particular connection. * @param info so we know the {@link org.logicalcobwebs.proxool.ConnectionInfoIF#getStatus()} status * @return the CSS class * @see #STATUS_CLASSES */ private static String getStatusClass(ConnectionInfoIF info) { try { return STATUS_CLASSES[info.getStatus()]; } catch (ArrayIndexOutOfBoundsException e) { LOG.warn("Unknown status: " + info.getStatus()); return "unknown-" + info.getStatus(); } } private void doDrillDownConnection(ServletOutputStream out, ConnectionInfoIF drillDownConnection) throws IOException { // sql calls String[] sqlCalls = drillDownConnection.getSqlCalls(); for (int i = 0; sqlCalls != null && i < sqlCalls.length; i++) { String sqlCall = sqlCalls[i]; out.print("
"); out.print("sql = "); out.print(sqlCall); out.print("
"); } // proxy out.print("
"); out.print("proxy = "); out.print(drillDownConnection.getProxyHashcode()); out.print("
"); // delegate out.print("
"); out.print("delegate = "); out.print(drillDownConnection.getDelegateHashcode()); out.print("
"); // url out.print("
"); out.print("url = "); out.print(drillDownConnection.getDelegateUrl()); out.print("
"); } private void openHtml(ServletOutputStream out) throws IOException { out.println("
Proxool Admin"); out.println(""); // If we have configured a cssFile then that will override what we have above if (cssFile != null) { out.println(""); } out.println("
"); } private void closeHtml(ServletOutputStream out) throws IOException { out.println(""); } private void openDataTable(ServletOutputStream out) throws IOException { out.println(""); out.println(" "); } private void closeTable(ServletOutputStream out) throws IOException { out.println(" "); out.println("
"); out.println("
"); } private void printDefinitionEntry(ServletOutputStream out, String name, String value, String type) throws IOException { out.println(" "); out.print(" "); out.print(name); out.println(":"); out.print(" "); if (value != null && !value.equals("null")) { out.print(value); } else { out.print("-"); } out.print(""); out.println(" "); } /** * Output the list of available connection pools. If there are none then display a message saying that. * If there is only one then just display nothing (and the pool will displayed by default) * @param out where to write the HTML * @param alias identifies the current pool * @param tab identifies the tab we are on so that changing pools doesn't change the tab * @param link the URL back to this servlet */ private void doList(ServletOutputStream out, String alias, String tab, String link) throws IOException { String[] aliases = ProxoolFacade.getAliases(); if (aliases.length == 0) { out.println("

No pools have been registered.

"); } else if (aliases.length == 1) { // Don't bother listing. Just show it. } else { out.println("
"); out.println(""); out.println(""); out.println(""); out.println("
"); } } /** * Express time in an easy to read HH:mm:ss format * * @param time in milliseconds * @return time (e.g. 180000 = 00:30:00) * @see #TIME_FORMAT */ private String formatMilliseconds(long time) { if (time > Integer.MAX_VALUE) { return time + "ms"; } else { Calendar c = Calendar.getInstance(); c.clear(); c.add(Calendar.MILLISECOND, (int) time); return TIME_FORMAT.format(c.getTime()); } } } /* Revision history: $Log: AdminServlet.java,v $ Revision 1.16 2007/12/14 23:20:41 billhorsman Change date format to yyyy-MM-dd to avoid CharConversionException in some locales. Revision 1.15 2007/06/19 11:33:35 billhorsman Changed time (millisecond) properties from int to long: maximumConnectionLifetime, houseKeepingSleepTime, recentlyStartedThreshold, overloadWithoutRefusalLifetime, maximumActiveTime Revision 1.14 2006/06/09 17:32:54 billhorsman Fix closing tag for select. Credit to Paolo Di Tommaso. Revision 1.13 2006/01/18 14:39:56 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.12 2005/10/07 08:23:10 billhorsman Doc Revision 1.11 2005/10/02 09:45:49 billhorsman Layout Revision 1.10 2005/09/26 21:47:46 billhorsman no message Revision 1.9 2005/09/26 13:31:14 billhorsman Smartened up AdminServlet Revision 1.8 2003/09/29 17:49:19 billhorsman Includes new fatal-sql-exception-wrapper-class in display Revision 1.7 2003/08/06 20:08:58 billhorsman fix timezone display of time (for millisecond based properties) Revision 1.6 2003/03/10 23:43:14 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.5 2003/03/10 15:26:51 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.4 2003/03/03 11:12:00 billhorsman fixed licence Revision 1.3 2003/02/26 16:59:18 billhorsman fixed spelling error in method name Revision 1.2 2003/02/26 16:51:12 billhorsman fixed units for average active time. now displays properly in seconds Revision 1.1 2003/02/24 10:19:44 billhorsman moved AdminServlet into servlet package Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.10 2003/02/12 12:28:27 billhorsman added url, proxyHashcode and delegateHashcode to ConnectionInfoIF Revision 1.9 2003/02/11 00:30:28 billhorsman add version Revision 1.8 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.7 2003/02/06 15:42:21 billhorsman display changes Revision 1.6 2003/02/05 17:04:02 billhorsman fixed date format Revision 1.5 2003/02/05 15:06:16 billhorsman removed dependency on JDK1.4 imaging. Revision 1.4 2003/01/31 16:53:21 billhorsman checkstyle Revision 1.3 2003/01/31 16:38:52 billhorsman doc (and removing public modifier for classes where possible) Revision 1.2 2003/01/31 11:35:57 billhorsman improvements to servlet (including connection details) Revision 1.1 2003/01/31 00:38:22 billhorsman *** empty log message *** */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/servlet/package.html0000644000175000017500000000125510730503124031541 0ustar twernertwerner

The AdminServlet provides information about running pools. This is only relevant if you are using Proxool inside a web application. You can configure the servlet in any way you like, but this is an example web.xml fragment:

       <servlet>
           <servlet-name>Monitor</servlet-name>
           <servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
       </servlet>

       <servlet-mapping>
           <servlet-name>Monitor</servlet-name>
           <url-pattern>/monitor</url-pattern>
       </servlet-mapping>
     
libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/Admin.java0000644000175000017500000002002010730503125027457 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF; import org.logicalcobwebs.proxool.ConnectionPoolStatisticsIF; import org.logicalcobwebs.proxool.ProxoolException; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; /** * Provides statistics about the performance of a pool. * * @version $Revision: 1.9 $, $Date: 2006/01/18 14:39:57 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class Admin { private static final Log LOG = LogFactory.getLog(Admin.class); private Log log; private Map statsRollers = new HashMap(); private CompositeStatisticsListener compositeStatisticsListener = new CompositeStatisticsListener(); /** * @param definition gives access to pool definition * @param definition see {@link org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF#getStatistics definition} */ public Admin(ConnectionPoolDefinitionIF definition) throws ProxoolException { log = LogFactory.getLog("org.logicalcobwebs.proxool.stats." + definition.getAlias()); StringTokenizer st = new StringTokenizer(definition.getStatistics(), ","); while (st.hasMoreTokens()) { String token = st.nextToken(); statsRollers.put(token, new StatsRoller(definition.getAlias(), compositeStatisticsListener, token)); } if (definition.getStatisticsLogLevel() != null) { compositeStatisticsListener.addListener(new StatisticsLogger(log, definition.getStatisticsLogLevel())); } } public void addStatisticsListener(StatisticsListenerIF statisticsListener) { this.compositeStatisticsListener.addListener(statisticsListener); } /** * Call this every time an active connection is returned to the pool * @param activeTime how long the connection was active */ public void connectionReturned(long activeTime) { try { Iterator i = statsRollers.values().iterator(); while (i.hasNext()) { StatsRoller statsRoller = (StatsRoller) i.next(); statsRoller.connectionReturned(activeTime); } } catch (Throwable e) { LOG.error("Stats connectionReturned call failed. Ignoring.", e); } } /** * Call this every time a connection is refused */ public void connectionRefused() { try { Iterator i = statsRollers.values().iterator(); while (i.hasNext()) { StatsRoller statsRoller = (StatsRoller) i.next(); statsRoller.connectionRefused(); } } catch (Exception e) { LOG.error("Stats connectionRefused call failed. Ignoring.", e); } } /** * Returns the most recent sample that has completed its period * @return sample (or null if no statistics are complete yet) */ public StatisticsIF getStatistics(String token) { try { return ((StatsRoller) statsRollers.get(token)).getCompleteStatistics(); } catch (NullPointerException e) { return null; } } /** * Cancels the timer that outputs the stats */ public void cancelAll() { Iterator i = statsRollers.values().iterator(); while (i.hasNext()) { StatsRoller statsRoller = (StatsRoller) i.next(); statsRoller.cancel(); } } public StatisticsIF[] getStatistics() { List statistics = new Vector(); Iterator i = statsRollers.values().iterator(); while (i.hasNext()) { StatsRoller statsRoller = (StatsRoller) i.next(); StatisticsIF s = statsRoller.getCompleteStatistics(); if (s != null) { statistics.add(s); } } return (StatisticsIF[]) statistics.toArray(new StatisticsIF[statistics.size()]); } /** * Get a new snapshot * @param cps used to help populate the snapshot * @param cpd used to help populate the snapshot * @return snapshot */ public static SnapshotIF getSnapshot(ConnectionPoolStatisticsIF cps, ConnectionPoolDefinitionIF cpd, Collection connectionInfos) { Snapshot s = new Snapshot(new Date()); s.setDateStarted(cps.getDateStarted()); s.setActiveConnectionCount(cps.getActiveConnectionCount()); s.setAvailableConnectionCount(cps.getAvailableConnectionCount()); s.setOfflineConnectionCount(cps.getOfflineConnectionCount()); s.setMaximumConnectionCount(cpd.getMaximumConnectionCount()); s.setServedCount(cps.getConnectionsServedCount()); s.setRefusedCount(cps.getConnectionsRefusedCount()); s.setConnectionInfos(connectionInfos); s.setConnectionCount(cps.getConnectionCount()); /* if (s.getActiveConnectionCount() != getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_ACTIVE)) { LOG.error("activeCount disparity: " + s.getActiveConnectionCount() + " != " + getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_ACTIVE)); } if (s.getAvailableConnectionCount() != getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_AVAILABLE)) { LOG.error("activeCount disparity: " + s.getAvailableConnectionCount() + " != " + getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_AVAILABLE)); } if (s.getOfflineConnectionCount() != getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_OFFLINE)) { LOG.error("offlineCount disparity: " + s.getOfflineConnectionCount() + " != " + getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_OFFLINE)); } */ return s; } } /* Revision history: $Log: Admin.java,v $ Revision 1.9 2006/01/18 14:39:57 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.8 2005/10/02 12:32:01 billhorsman Make connectionCount available to statistics Revision 1.7 2003/10/27 20:26:19 billhorsman connectionReturned() and connectionRefused() calls will now log any errors and continue rather than possibly throwing RuntimeExceptions back to the caller. In principle, stats should not cause problems to the core code. (No evidence of this happening - but it's more robust now.) Revision 1.6 2003/08/30 14:54:04 billhorsman Checkstyle Revision 1.5 2003/03/11 14:51:55 billhorsman more concurrency fixes relating to snapshots Revision 1.4 2003/03/10 23:43:14 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.3 2003/03/10 15:26:50 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.2 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.8 2003/02/07 15:08:51 billhorsman removed redundant accessor Revision 1.7 2003/02/07 14:16:45 billhorsman support for StatisticsListenerIF Revision 1.6 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.5 2003/02/05 00:20:27 billhorsman getSnapshot is now static (because it can be) Revision 1.4 2003/02/04 15:59:49 billhorsman finalize now shuts down StatsRoller timer Revision 1.3 2003/01/31 16:53:21 billhorsman checkstyle Revision 1.2 2003/01/31 16:38:51 billhorsman doc (and removing public modifier for classes where possible) Revision 1.1 2003/01/31 11:35:57 billhorsman improvements to servlet (including connection details) Revision 1.2 2003/01/31 00:28:57 billhorsman now handles multiple statistics Revision 1.1 2003/01/30 17:20:19 billhorsman fixes, improvements and doc */././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/CompositeStatisticsListener.javalibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/CompositeStatisticsListener.jav0000644000175000017500000000517310730503125034025 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.util.AbstractListenerContainer; /** * A {@link StatisticsListenerIF} that keeps a list of StatisticsListenerIFs * and notifies them in a thread safe manner. * It also implements {@link org.logicalcobwebs.proxool.util.ListenerContainerIF ListenerContainerIF} * which provides methods for * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#addListener(Object) adding} and * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#removeListener(Object) removing} listeners. * * @version $Revision: 1.5 $, $Date: 2006/01/18 14:39:57 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class CompositeStatisticsListener extends AbstractListenerContainer implements StatisticsListenerIF { static final Log LOG = LogFactory.getLog(CompositeStatisticsListener.class); /** * @see StatisticsListenerIF#statistics(String, StatisticsIF) */ public void statistics(String alias, StatisticsIF statistics) { Object[] listeners = getListeners(); for(int i=0; i 0) { return ((double) totalActiveTime / (double) servedCount); } else { return 0.0; } } /** * @see org.logicalcobwebs.proxool.admin.StatisticsIF#getAverageActiveCount */ public double getAverageActiveCount() { return (double) totalActiveTime / (double) getPeriod(); } /** * @see org.logicalcobwebs.proxool.admin.StatisticsIF#getServedPerSecond */ public double getServedPerSecond() { return (double) servedCount / ((double) getPeriod() / 1000.0); } /** * @see org.logicalcobwebs.proxool.admin.StatisticsIF#getRefusedPerSecond */ public double getRefusedPerSecond() { return (double) refusedCount / ((double) getPeriod() / 1000.0); } /** * @see org.logicalcobwebs.proxool.admin.StatisticsIF#getServedCount */ public long getServedCount() { return servedCount; } /** * @see org.logicalcobwebs.proxool.admin.StatisticsIF#getRefusedCount */ public long getRefusedCount() { return refusedCount; } } /* Revision history: $Log: Statistics.java,v $ Revision 1.2 2003/03/03 11:11:59 billhorsman fixed licence Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.3 2003/01/31 16:53:22 billhorsman checkstyle Revision 1.2 2003/01/31 16:38:53 billhorsman doc (and removing public modifier for classes where possible) Revision 1.1 2003/01/31 11:35:57 billhorsman improvements to servlet (including connection details) Revision 1.1 2003/01/30 17:20:13 billhorsman fixes, improvements and doc */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/StatisticsIF.java0000644000175000017500000000447710730503125031022 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import java.util.Date; /** * Provides statistical performance information for a period ot * time. * * @version $Revision: 1.2 $, $Date: 2003/03/03 11:11:59 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public interface StatisticsIF { /** * The length of time this sample represents, * @return period (milliseconds) */ long getPeriod(); /** * The average time that each connection spent active. * @return averageActiveTime (milliseconds) */ double getAverageActiveTime(); /** * The average number of active connections, * @return averageActiveCount */ double getAverageActiveCount(); /** * The number of connections served during this sample. * @return servedCount */ long getServedCount(); /** * The number of connections refused during this sample. * @return refusedCount */ long getRefusedCount(); /** * When this sample started. * @return startDate * @see #getStopDate * @see #getPeriod */ Date getStartDate(); /** * When this sample stopped * @return stopDate * @see #getStartDate * @see #getPeriod */ Date getStopDate(); /** * The rate at which we have served connections * @return servedPerSecond */ double getServedPerSecond(); /** * The rate at which we have refused connections * @return refusedPerSecond */ double getRefusedPerSecond(); } /* Revision history: $Log: StatisticsIF.java,v $ Revision 1.2 2003/03/03 11:11:59 billhorsman fixed licence Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.3 2003/01/31 16:53:23 billhorsman checkstyle Revision 1.2 2003/01/31 16:38:54 billhorsman doc (and removing public modifier for classes where possible) Revision 1.1 2003/01/31 11:35:57 billhorsman improvements to servlet (including connection details) Revision 1.1 2003/01/30 17:20:12 billhorsman fixes, improvements and doc */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/StatisticsListenerIF.java0000644000175000017500000000272710730503124032523 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; /** * Listen for new {@link StatisticsIF statistics} as they are produced. * The frequency with which they occur is defined in the * {@link org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF#getStatistics configuration}. * *
 * String alias = "myPool";
 * StatisticsListenerIF myStatisticsListener = new MyStatisticsListener();
 * ProxoolFacade.{@link org.logicalcobwebs.proxool.ProxoolFacade#addStatisticsListener addStatisticsListener}(alias, myStatisticsListener);
 * 
* @version $Revision: 1.2 $, $Date: 2003/03/03 11:11:59 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public interface StatisticsListenerIF { /** * A new set of statistics have just been produced * @param alias identifies the pool * @param statistics new statistics */ void statistics(String alias, StatisticsIF statistics); } /* Revision history: $Log: StatisticsListenerIF.java,v $ Revision 1.2 2003/03/03 11:11:59 billhorsman fixed licence Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.2 2003/02/08 00:35:29 billhorsman doc Revision 1.1 2003/01/31 15:16:12 billhorsman new listener */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/StatisticsLogger.java0000644000175000017500000000555010730503124031733 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.logicalcobwebs.proxool.ProxoolConstants; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; /** * Listens to statistics and logs them * @version $Revision: 1.3 $, $Date: 2006/01/18 14:39:57 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class StatisticsLogger implements StatisticsListenerIF { private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); private static final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); private Log log; private String logLevel; public StatisticsLogger(Log log, String logLevel) { this.log = log; this.logLevel = logLevel; } public void statistics(String alias, StatisticsIF statistics) { if (statistics != null && logLevel != null) { StringBuffer out = new StringBuffer(); out.append(TIME_FORMAT.format(statistics.getStartDate())); out.append(" - "); out.append(TIME_FORMAT.format(statistics.getStopDate())); out.append(", s:"); out.append(statistics.getServedCount()); out.append(":"); out.append(DECIMAL_FORMAT.format(statistics.getServedPerSecond())); out.append("/s, r:"); out.append(statistics.getRefusedCount()); out.append(":"); out.append(DECIMAL_FORMAT.format(statistics.getRefusedPerSecond())); out.append("/s, a:"); out.append(DECIMAL_FORMAT.format(statistics.getAverageActiveTime())); out.append("ms/"); out.append(DECIMAL_FORMAT.format(statistics.getAverageActiveCount())); if (logLevel.equals(ProxoolConstants.STATISTICS_LOG_LEVEL_TRACE)) { log.trace(out.toString()); } else if (logLevel.equals(ProxoolConstants.STATISTICS_LOG_LEVEL_DEBUG)) { log.debug(out.toString()); } else if (logLevel.equals(ProxoolConstants.STATISTICS_LOG_LEVEL_INFO)) { log.info(out.toString()); } } } } /* Revision history: $Log: StatisticsLogger.java,v $ Revision 1.3 2006/01/18 14:39:57 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.2 2003/03/03 11:11:59 billhorsman fixed licence Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.1 2003/02/07 14:16:46 billhorsman support for StatisticsListenerIF */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/StatsRoller.java0000644000175000017500000001734610730503124030725 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.logicalcobwebs.concurrent.WriterPreferenceReadWriteLock; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolException; import java.util.Calendar; /** * Responsbile for a single set of statistics. It rolls over to a new set * whenever it should. It provides access to the latest complete set * when it is available. * * @version $Revision: 1.9 $, $Date: 2006/01/18 14:39:58 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ class StatsRoller { private static final Log LOG = LogFactory.getLog(StatsRoller.class); private WriterPreferenceReadWriteLock readWriteLock = new WriterPreferenceReadWriteLock(); private Statistics completeStatistics; private Statistics currentStatistics; private Calendar nextRollDate; private int period; private int units; private boolean running = true; private CompositeStatisticsListener compositeStatisticsListener; private String alias; public StatsRoller(String alias, CompositeStatisticsListener compositeStatisticsListener, String token) throws ProxoolException { this.alias = alias; this.compositeStatisticsListener = compositeStatisticsListener; nextRollDate = Calendar.getInstance(); if (token.endsWith("s")) { units = Calendar.SECOND; nextRollDate.clear(Calendar.SECOND); nextRollDate.clear(Calendar.MILLISECOND); } else if (token.endsWith("m")) { units = Calendar.MINUTE; nextRollDate.clear(Calendar.MINUTE); nextRollDate.clear(Calendar.SECOND); nextRollDate.clear(Calendar.MILLISECOND); } else if (token.endsWith("h")) { nextRollDate.clear(Calendar.HOUR_OF_DAY); nextRollDate.clear(Calendar.MINUTE); nextRollDate.clear(Calendar.SECOND); nextRollDate.clear(Calendar.MILLISECOND); units = Calendar.HOUR_OF_DAY; } else if (token.endsWith("d")) { units = Calendar.DATE; nextRollDate.clear(Calendar.HOUR_OF_DAY); nextRollDate.clear(Calendar.MINUTE); nextRollDate.clear(Calendar.SECOND); nextRollDate.clear(Calendar.MILLISECOND); } else { throw new ProxoolException("Unrecognised suffix in statistics: " + token); } period = Integer.parseInt(token.substring(0, token.length() - 1)); // Now roll forward until you get one step into the future Calendar now = Calendar.getInstance(); while (nextRollDate.before(now)) { nextRollDate.add(units, period); } LOG.debug("Collecting first statistics for '" + token + "' at " + nextRollDate.getTime()); currentStatistics = new Statistics(now.getTime()); // Automatically trigger roll if no activity final Thread t = new Thread() { public void run() { while (running) { try { Thread.sleep(5000); } catch (InterruptedException e) { LOG.debug("Interruption", e); } roll(); } } }; t.setDaemon(true); t.start(); } /** * Cancels the timer that outputs the stats */ protected void cancel() { running = false; } private void roll() { if (!isCurrent()) { try { readWriteLock.writeLock().acquire(); if (!isCurrent()) { currentStatistics.setStopDate(nextRollDate.getTime()); completeStatistics = currentStatistics; currentStatistics = new Statistics(nextRollDate.getTime()); nextRollDate.add(units, period); compositeStatisticsListener.statistics(alias, completeStatistics); } } catch (Throwable e) { LOG.error("Unable to roll statistics log", e); } finally { readWriteLock.writeLock().release(); } } } private boolean isCurrent() { return (System.currentTimeMillis() < nextRollDate.getTime().getTime()); } /** * @see org.logicalcobwebs.proxool.admin.Admin#connectionReturned */ public void connectionReturned(long activeTime) { roll(); try { readWriteLock.readLock().acquire(); currentStatistics.connectionReturned(activeTime); } catch (InterruptedException e) { LOG.error("Unable to log connectionReturned", e); } finally { readWriteLock.readLock().release(); } } /** * @see org.logicalcobwebs.proxool.admin.Admin#connectionRefused */ public void connectionRefused() { roll(); try { readWriteLock.readLock().acquire(); currentStatistics.connectionRefused(); } catch (InterruptedException e) { LOG.error("Unable to log connectionRefused", e); } finally { readWriteLock.readLock().release(); } } /** * * @return */ public Statistics getCompleteStatistics() { try { readWriteLock.readLock().acquire(); return completeStatistics; } catch (InterruptedException e) { LOG.error("Couldn't read statistics", e); return null; } finally { readWriteLock.readLock().release(); } } } /* Revision history: $Log: StatsRoller.java,v $ Revision 1.9 2006/01/18 14:39:58 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.8 2003/10/27 20:24:48 billhorsman roll() now makes an additional call to isCurrent() *before* it asks for a write lock. Before it was getting a write lock every five seconds which effectively blocks all connections (if only briefly). Revision 1.7 2003/09/10 22:21:04 chr32 Removing > jdk 1.2 dependencies. Revision 1.6 2003/03/11 00:12:11 billhorsman switch to concurrent package Revision 1.5 2003/03/06 21:56:27 billhorsman remove too much debug Revision 1.4 2003/03/06 12:44:02 billhorsman add readWriteLock Revision 1.3 2003/03/03 11:11:59 billhorsman fixed licence Revision 1.2 2003/02/28 12:42:45 billhorsman removed unnecessary sleep in timer Revision 1.1 2003/02/19 23:36:51 billhorsman renamed monitor package to admin Revision 1.11 2003/02/08 14:27:51 chr32 Style fixes. Also tried to fix the dublicate linebreaks in the logging classes. Revision 1.10 2003/02/07 14:16:46 billhorsman support for StatisticsListenerIF Revision 1.9 2003/02/06 17:41:06 billhorsman now uses imported logging Revision 1.8 2003/02/06 15:41:18 billhorsman add statistics-log-level Revision 1.7 2003/02/04 17:17:03 billhorsman make Timer a daemon Revision 1.6 2003/02/04 15:59:49 billhorsman finalize now shuts down StatsRoller timer Revision 1.5 2003/02/02 23:32:48 billhorsman fixed bug caused by last variable name change. :( Revision 1.4 2003/01/31 16:53:23 billhorsman checkstyle Revision 1.3 2003/01/31 16:38:54 billhorsman doc (and removing public modifier for classes where possible) Revision 1.2 2003/01/31 14:33:19 billhorsman fix for DatabaseMetaData Revision 1.1 2003/01/31 11:35:57 billhorsman improvements to servlet (including connection details) Revision 1.1 2003/01/31 00:28:57 billhorsman now handles multiple statistics */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/admin/package.html0000644000175000017500000000040610730503125030053 0ustar twernertwerner

Provides statistical information on each pool. Like:

  • averageActiveTime
  • averageActiveCount
  • servedCount
  • refusedCount
  • startDate
  • stopDate
  • servedPerSecond
  • refusedPerSecond
  • libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/0000755000175000017500000000000011054125603027352 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/NewFolder/0000755000175000017500000000000011053761073031245 5ustar twernertwerner././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/AvalonConfigurator.javalibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/AvalonConfigurator.java0000644000175000017500000002611610730503124034024 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Configurator for the Avalon Framework. * The configuration can contain any number of <proxool> elements. The <proxool> elements * are delegated to {@link XMLConfigurator}, * and have exactly the same format as is documented in that class. *

    * This is a "faceless" Avalon component. This means that it does not present an operational interface, it * simply configures Proxool when Avalon calls its configure method. You need to lookup this * component in your bootstrap code to make this happen. *

    *

    * The configuration takes one attribute: close-on-dispose *
    * You can use this to let this configurator know * wether or not to close the pools it has created * when it is disposed. *
    Legal values are true or false. Default: true. *

    * * @version $Revision: 1.14 $, $Date: 2006/01/18 14:39:58 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class AvalonConfigurator implements Component, Configurable, ThreadSafe, Disposable { private static final Log LOG = LogFactory.getLog(AvalonConfigurator.class); /** * Avalon ROLE id for this component. */ public static final String ROLE = AvalonConfigurator.class.getName(); /** * Constant for the boolean "close-on-dispose" attribute that signifies * wether or not this configurator shall close the pools it has created * when it is disposed. Legal values are "true" or "false". Default: true. * */ public static final String CLOSE_ON_DISPOSE_ATTRIBUTE = "close-on-dispose"; private boolean closeOnDispose = true; private final List configuredPools = new ArrayList(3); /** * Check that all top level elements are named proxool and hand them to * {@link XMLConfigurator}. * @param configuration the configuration handed over by the Avalon Framework. * @throws ConfigurationException if the configuration fails. */ public void configure(Configuration configuration) throws ConfigurationException { final XMLConfigurator xmlConfigurator = new XMLConfigurator(); this.closeOnDispose = configuration.getAttributeAsBoolean(CLOSE_ON_DISPOSE_ATTRIBUTE, true); final Configuration[] children = configuration.getChildren(); for (int i = 0; i < children.length; ++i) { if (!children[i].getName().equals(ProxoolConstants.PROXOOL)) { throw new ConfigurationException("Found element named " + children[i].getName() + ". Only " + ProxoolConstants.PROXOOL + " top level elements are alowed."); } } try { xmlConfigurator.startDocument(); reportProperties(xmlConfigurator, configuration.getChildren()); xmlConfigurator.endDocument(); } catch (SAXException e) { throw new ConfigurationException("", e); } } /** * If {@link #CLOSE_ON_DISPOSE_ATTRIBUTE} is set: Close all connection pools that this configurator has configured. *
    ...else: do nothing. */ public void dispose() { LOG.info("Disposing."); if (this.closeOnDispose) { Iterator configuredPools = this.configuredPools.iterator(); String alias = null; while (configuredPools.hasNext()) { alias = (String) configuredPools.next(); LOG.info("Closing connection pool '" + alias + "'."); try { ProxoolFacade.removeConnectionPool(alias); } catch (ProxoolException e) { LOG.error("Closing of connection pool '" + alias + "' failed.", e); } } } else { LOG.info(CLOSE_ON_DISPOSE_ATTRIBUTE + " attribute is not set, so configured pools will not be closed."); } LOG.info("Disposed."); } // Parse the properties recursively, and report found properties to the given XMLConfigurator private void reportProperties(XMLConfigurator xmlConfigurator, Configuration[] properties) throws ConfigurationException, SAXException { Configuration[] children = null; String value = null; String namespace = null; for (int i = 0; i < properties.length; ++i) { Configuration configuration = properties[i]; namespace = configuration.getNamespace(); if (namespace == null) { namespace = ""; } if (LOG.isDebugEnabled()) { LOG.debug("Reporting element start for " + configuration.getName()); } final String lName = namespace.length() == 0 ? "" : configuration.getName(); final String qName = namespace.length() == 0 ? configuration.getName() : ""; xmlConfigurator.startElement(namespace, lName, qName, getAttributes(configuration)); children = configuration.getChildren(); // If this is a leaf node, report the value, // else recurse. if (children == null || children.length < 1) { value = configuration.getValue(null); if (value != null) { xmlConfigurator.characters(value.toCharArray(), 0, value.length()); } } else { reportProperties(xmlConfigurator, children); } xmlConfigurator.endElement(namespace, lName, qName); if (lName.equals(ProxoolConstants.PROXOOL) || qName.equals(ProxoolConstants.PROXOOL)) { Configuration conf = configuration.getChild(ProxoolConstants.ALIAS, false); if (conf != null) { if (LOG.isDebugEnabled()) { LOG.debug("Adding to configured pools: " + conf.getValue()); } this.configuredPools.add(conf.getValue()); } else { LOG.error("proxool element was missing required element 'alias'"); } } } } // create a SAX attributes instance from // Avalon configuration attributes private Attributes getAttributes(Configuration configuration) throws ConfigurationException { final AttributesImpl attributes = new AttributesImpl(); final String[] avalonAttributeNames = configuration.getAttributeNames(); if (avalonAttributeNames != null && avalonAttributeNames.length > 0) { for (int i = 0; i < avalonAttributeNames.length; ++i) { if (LOG.isDebugEnabled()) { LOG.debug("Adding attribute " + avalonAttributeNames[i] + " with value " + configuration.getAttribute(avalonAttributeNames[i])); } attributes.addAttribute("", avalonAttributeNames[i], avalonAttributeNames[i], "CDATA", configuration.getAttribute(avalonAttributeNames[i])); LOG.debug("In attributes: " + avalonAttributeNames[i] + " with value " + attributes.getValue(avalonAttributeNames[i])); } } return attributes; } } /* Revision history: $Log: AvalonConfigurator.java,v $ Revision 1.14 2006/01/18 14:39:58 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.13 2003/03/10 15:26:53 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.12 2003/03/03 11:12:00 billhorsman fixed licence Revision 1.11 2003/02/19 16:52:39 chr32 Added support for close-on-dispose attribute. Revision 1.10 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.9 2003/01/27 18:26:42 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.8 2002/12/23 02:59:38 chr32 Tiny doc fix. Revision 1.7 2002/12/23 02:58:16 chr32 Improved doc. Revision 1.6 2002/12/23 02:44:44 chr32 Added ROLE id and started implementing Component. Improved namespace support. Revision 1.5 2002/12/18 23:31:57 chr32 Expanded doc. Revision 1.4 2002/12/16 11:47:00 billhorsman checkstyle Revision 1.3 2002/12/16 02:37:14 chr32 Updated to new driver-properties xml format. Revision 1.2 2002/12/15 19:42:18 chr32 Rewrite. Now delegates to XMLConfigurator. Revision 1.1 2002/12/15 18:48:33 chr32 Movied in from 'ext' source tree. Revision 1.5 2002/10/27 13:05:01 billhorsman checkstyle Revision 1.4 2002/10/27 12:00:14 billhorsman moved classes from ext sub-package which is now obsolete - let's keep everything together in one place Revision 1.2 2002/10/23 21:04:37 billhorsman checkstyle fixes (reduced max line width and lenient naming convention Revision 1.1 2002/09/19 08:53:41 billhorsman created new ext package Revision 1.2 2002/09/18 13:48:56 billhorsman checkstyle and doc Revision 1.1.1.1 2002/09/13 08:14:16 billhorsman new Revision 1.5 2002/08/24 19:57:15 billhorsman checkstyle changes Revision 1.4 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.3 2002/07/10 10:52:51 billhorsman doc fix Revision 1.2 2002/07/02 23:08:55 billhorsman new config package to allow us to introduce other ways Revision 1.1 2002/07/02 23:05:31 billhorsman New config package so that we can introduce other ways of configuring pools. Revision 1.6 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.5 2002/07/02 11:14:26 billhorsman added test (andbug fixes) for FileLogger Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc Revision 1.3 2002/06/05 09:01:31 billhorsman removed ConnectionFacadeIF interface in preparation for new, cleaner ProxoolFacade class. _And_ did a code layout update. Why, of why did I mix that up with one commit? It makes it unclear where the cosmetic changes and code changes were made. I won't do it again. Revision 1.2 2002/06/04 22:23:00 billhorsman added class header comments Revision 1.1.1.1 2002/06/04 14:24:01 billhorsman start */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/JAXPConfigurator.java0000644000175000017500000001504610730503124033346 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolException; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; /** * Configurator that uses JAXP to get a parser for Proxool configuration xml. The parser relies on JAXP version 1.1 or higher * and is namespace aware. *

    * See {@link XMLConfigurator} for the Proxool xml configuration format. *

    *

    * All the configure methods of this class takes a boolean argument describing whether the * xml should be validated or not. If you want your xml to be validated be sure to read the * Validation chapter in the JavaDoc for {@link XMLConfigurator}. *

    * @version $Revision: 1.12 $, $Date: 2006/01/18 14:39:58 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class JAXPConfigurator { private static final Log LOG = LogFactory.getLog(JAXPConfigurator.class); private static final boolean NAMESPACE_AWARE = true; /** * Configure Proxool with xml from the given file. * @param xmlFileName the file to read xml from. * @param validate true if the parsel shall be validating, and false otherwise. * @throws ProxoolException if the configuration fails. */ public static void configure(String xmlFileName, boolean validate) throws ProxoolException { try { if (LOG.isDebugEnabled()) { LOG.debug("Configuring from xml file: " + xmlFileName); } configure(new InputSource(new FileReader(xmlFileName)), validate); } catch (FileNotFoundException e) { throw new ProxoolException(e); } } /** * Configure Proxool with xml from the given InputSource. * @param inputSource the InputSource to read xml from. * @param validate true if the parsel shall be validating, and false otherwise. * @throws ProxoolException if the configuration fails. */ public static void configure(InputSource inputSource, boolean validate) throws ProxoolException { try { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); if (LOG.isDebugEnabled()) { LOG.debug("SAXParserFactory class: " + saxParserFactory.getClass().getName()); } saxParserFactory.setValidating(validate); final SAXParser saxParser = saxParserFactory.newSAXParser(); if (LOG.isDebugEnabled()) { LOG.debug("sax parser class" + saxParser.getClass().getName()); } final XMLReader xmlReader = saxParser.getXMLReader(); if (LOG.isDebugEnabled()) { LOG.debug("XML reader class: " + xmlReader.getClass().getName()); } final XMLConfigurator xmlConfigurator = new XMLConfigurator(); xmlReader.setErrorHandler(xmlConfigurator); setSAXFeature(xmlReader, "http://xml.org/sax/features/namespaces", NAMESPACE_AWARE); setSAXFeature(xmlReader, "http://xml.org/sax/features/namespace-prefixes", !NAMESPACE_AWARE); saxParser.parse(inputSource, xmlConfigurator); } catch (ParserConfigurationException pce) { throw new ProxoolException("Parser configuration failed", pce); } catch (SAXException se) { throw new ProxoolException("Parsing failed.", se); } catch (IOException ioe) { throw new ProxoolException("Parsing failed.", ioe); } } /** * Configure Proxool with xml from the given reader. * @param reader the reader to read xml from. * @param validate true if the parsel shall be validating, and false otherwise. * @throws ProxoolException if the configuration fails. */ public static void configure(Reader reader, boolean validate) throws ProxoolException { if (LOG.isDebugEnabled()) { LOG.debug("Configuring from reader: " + reader); } configure(new InputSource(reader), validate); } // only log warning on problems with recognition and support of features // we'll probably pull through anyway... private static void setSAXFeature(XMLReader xmlReader, String feature, boolean state) { if (LOG.isDebugEnabled()) { LOG.debug("Setting sax feature: '" + feature + "'. State: " + state + "."); } try { xmlReader.setFeature(feature, state); } catch (SAXNotRecognizedException e) { LOG.warn("Feature: '" + feature + "' not recognised by xml reader " + xmlReader + ".", e); } catch (SAXNotSupportedException e) { LOG.warn("Feature: '" + feature + "' not supported by xml reader " + xmlReader + ".", e); } } } /* Revision history: $Log: JAXPConfigurator.java,v $ Revision 1.12 2006/01/18 14:39:58 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2004/05/14 21:15:47 brenuart Fix type in method name Revision 1.10 2003/03/10 23:43:15 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.9 2003/03/10 15:26:54 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.8 2003/03/03 11:12:00 billhorsman fixed licence Revision 1.7 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.6 2003/01/27 18:26:42 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.5 2002/12/18 23:31:57 chr32 Expanded doc. Revision 1.4 2002/12/16 11:46:59 billhorsman checkstyle Revision 1.3 2002/12/16 02:38:47 chr32 Updated to new driver-properties xml format. Revision 1.2 2002/12/15 19:43:11 chr32 Style fixes. Revision 1.1 2002/12/15 18:49:55 chr32 Init rev. */././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/PropertyConfigurator.javalibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/PropertyConfigurator.ja0000644000175000017500000002041310730503124034073 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; /** * Uses a standard Java properties file to configure Proxool. For example: * *
     * jdbc-0.proxool.alias=property-test
     * jdbc-0.proxool.driver-url=jdbc:hsqldb:.
     * jdbc-0.proxool.driver-class=org.hsqldb.jdbcDriver
     * jdbc-0.user=foo
     * jdbc-0.password=bar
     * jdbc-0.proxool.house-keeping-sleep-time=40000
     * jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
     * jdbc-0.proxool.maximum-connection-count=10
     * jdbc-0.proxool.minimum-connection-count=3
     * jdbc-0.proxool.maximum-connection-lifetime=18000000
     * jdbc-0.proxool.simultaneous-build-throttle=5
     * jdbc-0.proxool.recently-started-threshold=40000
     * jdbc-0.proxool.overload-without-refusal-lifetime=50000
     * jdbc-0.proxool.maximum-active-time=60000
     * jdbc-0.proxool.verbose=true
     * jdbc-0.proxool.trace=true
     * jdbc-0.proxool.fatal-sql-exception=Fatal error
     * jdbc-0.proxool.prototype-count=2
     *
     * jdbc-1.proxool.alias=property-test-2
     * jdbc-1.proxool.driver-url=jdbc:hsqldb:.
     * jdbc-1.proxool.driver-class=org.hsqldb.jdbcDriver
     * jdbc-1.user=scott
     * jdbc-1.password=tiger
     * jdbc-1.proxool.house-keeping-sleep-time=40000
     * jdbc-1.proxool.house-keeping-test-sql=select CURRENT_DATE
     * jdbc-1.proxool.maximum-connection-count=10
     * jdbc-1.proxool.minimum-connection-count=3
     * jdbc-1.proxool.maximum-connection-lifetime=18000000
     * jdbc-1.proxool.simultaneous-build-throttle=5
     * jdbc-1.proxool.recently-started-threshold=40000
     * jdbc-1.proxool.overload-without-refusal-lifetime=50000
     * jdbc-1.proxool.maximum-active-time=60000
     * jdbc-1.proxool.verbose=true
     * jdbc-1.proxool.trace=true
     * jdbc-1.proxool.fatal-sql-exception=Fatal error
     * jdbc-1.proxool.prototype-count=2
     * 
    * *

    The first word (up to the first dot) must start with "jdbc", but it can * be anything you like. Use unique names to identify each pool. Any property * not starting with "jdbc" will be ignored.

    *

    * The properties prefixed with "proxool." will be used by Proxool while * the properties that are not prefixed will be passed on to the * delegate JDBC driver. *

    * * @version $Revision: 1.11 $, $Date: 2006/01/18 14:39:58 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class PropertyConfigurator { private static final Log LOG = LogFactory.getLog(PropertyConfigurator.class); protected static final String PREFIX = "jdbc"; private static final String DOT = "."; private static final String EXAMPLE_FORMAT = PREFIX + "*" + DOT + "*"; /** * Configure proxool with the given properties file. * @param filename the filename of the properties file. * @throws ProxoolException if the configuration fails. */ public static void configure(String filename) throws ProxoolException { Properties properties = new Properties(); try { properties.load(new FileInputStream(filename)); } catch (IOException e) { throw new ProxoolException("Couldn't load property file " + filename); } configure(properties); } /** * Configure proxool with the given properties. * @param properties the properties instance to use. * @throws ProxoolException if the configuration fails. */ public static void configure(Properties properties) throws ProxoolException { final Map propertiesMap = new HashMap(); final Iterator allPropertyKeysIterator = properties.keySet().iterator(); Properties proxoolProperties = null; while (allPropertyKeysIterator.hasNext()) { String key = (String) allPropertyKeysIterator.next(); String value = properties.getProperty(key); if (key.startsWith(PREFIX)) { int a = key.indexOf(DOT); if (a == -1) { throw new ProxoolException("Property " + key + " must be of the format " + EXAMPLE_FORMAT); } final String tag = key.substring(0, a); final String name = key.substring(a + 1); proxoolProperties = (Properties) propertiesMap.get(tag); if (proxoolProperties == null) { proxoolProperties = new Properties(); propertiesMap.put(tag, proxoolProperties); } proxoolProperties.put(name, value); } } final Iterator tags = propertiesMap.keySet().iterator(); while (tags.hasNext()) { proxoolProperties = (Properties) propertiesMap.get(tags.next()); // make sure that required propeties are defined // and build the url // Check that we have defined the minimum information final String driverClass = proxoolProperties.getProperty(ProxoolConstants.DRIVER_CLASS_PROPERTY); final String driverUrl = proxoolProperties.getProperty(ProxoolConstants.DRIVER_URL_PROPERTY); if (driverClass == null || driverUrl == null) { throw new ProxoolException("You must define the " + ProxoolConstants.DRIVER_CLASS_PROPERTY + " and the " + ProxoolConstants.DRIVER_URL_PROPERTY + "."); } final String alias = proxoolProperties.getProperty(ProxoolConstants.ALIAS_PROPERTY); // Build the URL; optionally defining a name StringBuffer url = new StringBuffer(); url.append("proxool"); if (alias != null) { url.append(ProxoolConstants.ALIAS_DELIMITER); url.append(alias); proxoolProperties.remove(ProxoolConstants.ALIAS_PROPERTY); } url.append(ProxoolConstants.URL_DELIMITER); url.append(driverClass); proxoolProperties.remove(ProxoolConstants.DRIVER_CLASS_PROPERTY); url.append(ProxoolConstants.URL_DELIMITER); url.append(driverUrl); proxoolProperties.remove(ProxoolConstants.DRIVER_URL_PROPERTY); if (LOG.isDebugEnabled()) { LOG.debug("Created url: " + url); } ProxoolFacade.registerConnectionPool(url.toString(), proxoolProperties); } } } /* Revision history: $Log: PropertyConfigurator.java,v $ Revision 1.11 2006/01/18 14:39:58 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.10 2003/03/05 23:28:56 billhorsman deprecated maximum-new-connections property in favour of more descriptive simultaneous-build-throttle Revision 1.9 2003/03/03 11:12:00 billhorsman fixed licence Revision 1.8 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.7 2003/02/05 14:46:31 billhorsman fixed copyright and made PREFIX protected for use by ServletConfigurator Revision 1.6 2003/01/27 18:26:43 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.5 2003/01/23 10:41:05 billhorsman changed use of pool-name to alias for consistency Revision 1.4 2003/01/22 17:35:01 billhorsman checkstyle Revision 1.3 2003/01/18 15:13:12 billhorsman Signature changes (new ProxoolException thrown) on the ProxoolFacade API. Revision 1.2 2002/12/26 11:32:59 billhorsman Rewrote to support new format. Revision 1.1 2002/12/15 18:48:33 chr32 Movied in from 'ext' source tree. Revision 1.4 2002/11/09 15:57:57 billhorsman fix doc Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/10/27 13:05:01 billhorsman checkstyle Revision 1.1 2002/10/27 12:00:16 billhorsman moved classes from ext sub-package which is now obsolete - let's keep everything together in one place Revision 1.1 2002/10/25 10:40:27 billhorsman draft */ ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/ServletConfigurator.javalibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/ServletConfigurator.jav0000644000175000017500000001551510730503124034070 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import java.io.File; import java.util.Enumeration; import java.util.Properties; /** *

    Allows you to configure Proxool using a servlet. There are three * different ways: * * The init parameters * can either directly configure Proxool (in a similar fashion to the * PropertyConfigurator) or they can point to separate XML or * property files. For example:

    * *

    1. XML file delegates to {@link JAXPConfigurator} passing * in the filename. If the filename is not absolute then it is prepended * with the application directory.

    * *
     *    <servlet>
     *        <servlet-name>ServletConfigurator</servlet-name>
     *        <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
     *        <init-param>
     *            <param-name>xmlFile</param-name>
     *            <param-value>WEB-INF/proxool.xml</param-value>
     *        </init-param>
     *    </servlet>
     * 
    * * 2. Property file delegates to {@link PropertyConfigurator} * passing in the filename. If the filename is not absolute then it is prepended * with the application directory. * *
     *    <servlet>
     *        <servlet-name>ServletConfigurator</servlet-name>
     *        <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
     *        <init-param>
     *            <param-name>propertyFile</param-name>
     *            <param-value>WEB-INF/proxool.properties</param-value>
     *        </init-param>
     *    </servlet>
     * 
    * * 3. Init parameters delegates to {@link PropertyConfigurator} * by passing in a new Properties object based on the servlet's init * parameters. * *
     *    <servlet>
     *        <servlet-name>ServletConfigurator</servlet-name>
     *        <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
     *        <init-param>
     *            <param-name>jdbc-0.proxool.alias</param-name>
     *            <param-value>test</param-value>
     *        </init-param>
     *        <init-param>
     *            <param-name>jdbc-0.proxool.driver-url</param-name>
     *            <param-value>jdbc:hsqldb:.</param-value>
     *        </init-param>
     *        <init-param>
     *            <param-name>jdbc-0.proxool.driver-class</param-name>
     *            <param-value>org.hsqldb.jdbcDriver</param-value>
     *        </init-param>
     *    </servlet>
     * 
    * *

    It will also automatically shutdown Proxool. See * {@link #destroy}.

    * * @version $Revision: 1.7 $, $Date: 2006/01/18 14:39:58 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class ServletConfigurator extends HttpServlet { private static final Log LOG = LogFactory.getLog(ServletConfigurator.class); private static final String XML_FILE_PROPERTY = "xmlFile"; private static final String PROPERTY_FILE_PROPERTY = "propertyFile"; private static final String AUTO_SHUTDOWN_PROPERTY = "autoShutdown"; private boolean autoShutdown = true; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); String appDir = servletConfig.getServletContext().getRealPath("/"); Properties properties = new Properties(); Enumeration names = servletConfig.getInitParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); String value = servletConfig.getInitParameter(name); if (name.equals(XML_FILE_PROPERTY)) { try { File file = new File(value); if (file.isAbsolute()) { JAXPConfigurator.configure(value, false); } else { JAXPConfigurator.configure(appDir + File.separator + value, false); } } catch (ProxoolException e) { LOG.error("Problem configuring " + value, e); } } else if (name.equals(PROPERTY_FILE_PROPERTY)) { try { File file = new File(value); if (file.isAbsolute()) { PropertyConfigurator.configure(value); } else { PropertyConfigurator.configure(appDir + File.separator + value); } } catch (ProxoolException e) { LOG.error("Problem configuring " + value, e); } } else if (name.equals(AUTO_SHUTDOWN_PROPERTY)) { autoShutdown = Boolean.valueOf(value).booleanValue(); } else if (name.startsWith(PropertyConfigurator.PREFIX)) { properties.setProperty(name, value); } } if (properties.size() > 0) { try { PropertyConfigurator.configure(properties); } catch (ProxoolException e) { LOG.error("Problem configuring using init properties", e); } } } /** * Shuts down Proxool by removing all connection pools. If you want * to disable this behaviour then use: *
         * <init-param>
         *   <param-name>autoShutdown</param-name>
         *   <param-value>false</param-value>
         * </init-param>
         * 
    */ public void destroy() { if (autoShutdown) { ProxoolFacade.shutdown(0); } } } /* Revision history: $Log: ServletConfigurator.java,v $ Revision 1.7 2006/01/18 14:39:58 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.6 2003/03/10 15:26:54 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.5 2003/03/03 11:12:00 billhorsman fixed licence Revision 1.4 2003/02/07 17:26:25 billhorsman use shutdown() instead of removeAllConnectionPools() Revision 1.3 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.2 2003/02/06 15:45:26 billhorsman trivial doc changes Revision 1.1 2003/02/05 15:03:49 billhorsman new configuration servlet. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/XMLConfigurator.java0000644000175000017500000002573410730503124033251 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import java.util.Properties; /** *

    A SAX 2 ContentHandler that can configure Proxool from an XML source.

    * *

    This is just a ContentHandler, so you must associate it with a SAX parser for it to actually do anything. * If you have JAXP available {@link JAXPConfigurator} will do this for you.

    * *

    Properties that you pass on to the delegate driver have to be treated specially. They * must be contained within a <driver-properties> element.

    * *

    See the Proxool properties for documentation * on the available configuration properties.

    * * Example configuration: *
     * <proxool>
     *     <alias>apple</alias>
     *     <driver-url>jdbc:hsqldb:.</driver-url>
     *     <driver-class>org.hsqldb.jdbcDriver</driver-class>
     *     <driver-properties>
     *         <property name="user" value="abc" />
     *         <property name="password" value="def" />
     *     </driver-properties>
     *     <house-keeping-sleep-time>40000</house-keeping-sleep-time>
     *     <house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
     *     <maximum-connection-count>10</maximum-connection-count>
     *     <minimum-connection-count>3</minimum-connection-count>
     *     <maximum-connection-lifetime>18000000</maximum-connection-lifetime> <!-- 5 hours -->
     *     <simultaneous-build-throttle>5</simultaneous-build-throttle>
     *     <recently-started-threshold>40000</recently-started-threshold>
     *     <overload-without-refusal-lifetime>50000</overload-without-refusal-lifetime>
     *     <maximum-active-time>60000</maximum-active-time>
     *     <verbose>true</verbose>
     *     <trace>true</trace>
     *     <fatal-sql-exception>ORA-1234</fatal-sql-exception>
     *     <prototype-count>2</prototype-count>
     * </proxool>
     * 
    * * When the parser reaches the end of the <proxool> element the pool * is automatically registered. You can contain the <proxool> element * in any other elements as you wish. And the <proxool> element can * occur as many times as you wish. This allows you to use an XML file that * configures your whole application as the source. This configurator will * ignore everything apart from the elements contained within the <proxool> * element. *

    * Validation
    * A couple of additional steps are required if you want your SAX parser to validate your Proxool xml confguration: *

    *

    *

    This class is not thread safe.

    * * @version $Revision: 1.18 $, $Date: 2006/01/18 14:39:58 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class XMLConfigurator extends DefaultHandler { private static final Log LOG = LogFactory.getLog(XMLConfigurator.class); private StringBuffer content = new StringBuffer(); private String poolName; private String driverClass; private String driverUrl; private Properties properties = new Properties(); private static final String PROXOOL = "proxool"; private static final String DRIVER_PROPERTIES = "driver-properties"; private static final String PROPERTY = "property"; private static final String NAME = "name"; private static final String VALUE = "value"; private boolean insideDelegateProperties; private boolean insideProxool; /** * @see org.xml.sax.ContentHandler#startElement */ public void startElement(String uri, String lname, String qname, Attributes attributes) throws SAXException { content.setLength(0); if (!namespaceOk(uri)) { return; } final String elementName = getElementName(uri, lname, qname); if (elementName.equals(PROXOOL)) { if (insideProxool) { throw new SAXException("A <" + PROXOOL + "> element can't contain another <" + PROXOOL + "> element."); } insideProxool = true; properties.clear(); driverClass = null; driverUrl = null; } if (insideProxool) { if (elementName.equals(DRIVER_PROPERTIES)) { insideDelegateProperties = true; } else if (insideDelegateProperties) { if (elementName.equals(PROPERTY)) { setDriverProperty(attributes); } } } } /** * @see org.xml.sax.ContentHandler#characters */ public void characters(char[] chars, int start, int length) throws SAXException { if (insideProxool) { content.append(chars, start, length); } } /** * @see org.xml.sax.ContentHandler#endElement */ public void endElement(String uri, String lname, String qname) throws SAXException { if (!namespaceOk(uri)) { return; } final String elementName = getElementName(uri, lname, qname); // Are we ending a proxool configuration section? if (elementName.equals(PROXOOL)) { // Check that we have defined the minimum information if (driverClass == null || driverUrl == null) { throw new SAXException("You must define the " + ProxoolConstants.DRIVER_CLASS + " and the " + ProxoolConstants.DRIVER_URL + "."); } // Build the URL; optinally defining a name StringBuffer url = new StringBuffer(); url.append("proxool"); if (poolName != null) { url.append(ProxoolConstants.ALIAS_DELIMITER); url.append(poolName); } url.append(ProxoolConstants.URL_DELIMITER); url.append(driverClass); url.append(ProxoolConstants.URL_DELIMITER); url.append(driverUrl); if (LOG.isDebugEnabled()) { LOG.debug("Created url: " + url); } // Register the pool try { ProxoolFacade.registerConnectionPool(url.toString(), properties); } catch (ProxoolException e) { throw new SAXException(e); } // This ensures we ignore remaining XML until we come across another // element. insideProxool = false; } if (insideProxool && !elementName.equals(PROXOOL)) { if (elementName.equals(DRIVER_PROPERTIES)) { insideDelegateProperties = false; } else if (!insideDelegateProperties) { setProxoolProperty(elementName, content.toString().trim()); } } } private void setProxoolProperty(String localName, String value) { if (localName.equals(ProxoolConstants.ALIAS)) { poolName = value; } else if (localName.equals(ProxoolConstants.DRIVER_CLASS)) { driverClass = value; } else if (localName.equals(ProxoolConstants.DRIVER_URL)) { driverUrl = value; } else { if (LOG.isDebugEnabled()) { LOG.debug("Setting property '" + ProxoolConstants.PROPERTY_PREFIX + localName + "' to value '" + value + "'."); } properties.put(ProxoolConstants.PROPERTY_PREFIX + localName, value); } } private void setDriverProperty(Attributes attributes) throws SAXException { final String name = attributes.getValue(NAME); final String value = attributes.getValue(VALUE); if (name == null || name.length() < 1 || value == null) { throw new SAXException("Name or value attribute missing from property element." + "Name: '" + name + "' Value: '" + value + "'."); } if (LOG.isDebugEnabled()) { if (name.toLowerCase().indexOf("password") > -1) { LOG.debug("Adding driver property: " + name + "=" + "*******"); } else { LOG.debug("Adding driver property: " + name + "=" + value); } } properties.put(name, value); } /** * @see org.xml.sax.ErrorHandler#warning(SAXParseException) */ public void warning(SAXParseException e) throws SAXException { // Just debug-log the warning. We'll probably survive. LOG.debug("The saxparser reported a warning.", e); } /** * @see org.xml.sax.ErrorHandler#error(SAXParseException) */ public void error(SAXParseException e) throws SAXException { // On error we rethrow the exception. // This should cause the parser stop and an exeption be thrown back to the client. throw e; } /** * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException) */ public void fatalError(SAXParseException e) throws SAXException { // On fatal error we rethrow the exception. // This should cause the parser stop and an exeption be thrown back to the client. throw e; } // If no namespace use qname, else use lname. private String getElementName(String uri, String lname, String qname) { if (uri == null || "".equals(uri)) { return qname; } else { return lname; } } private boolean namespaceOk(String uri) { return uri == null || uri.length() == 0 || uri.equals(ProxoolConstants.PROXOOL_XML_NAMESPACE_URI); } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/package.html0000644000175000017500000000010410730503124031624 0ustar twernertwerner Helpers for configuring Proxool from various sources. libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/configuration/proxool.dtd0000644000175000017500000001317010730503124031551 0ustar twernertwerner libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/proxy/0000755000175000017500000000000011054125603025664 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/proxy/InvokerFacade.java0000644000175000017500000000710010730503125031225 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.proxy; import org.logicalcobwebs.proxool.ProxoolException; import java.util.Map; import java.util.HashMap; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * Invokes a method using a cached method. * @version $Revision: 1.3 $, $Date: 2004/07/13 21:13:14 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class InvokerFacade { private static Map methodMappers = new HashMap(); /** * Returns the method in the concrete class with an indentical signature to that passed * @param concreteClass the class that we want to invoke methods on. It should either implement all methods on * the injectable interface, or provide methods with an identical signature. * @param injectableMethod provides signature that we are trying to match * @return the method in the concrete class that we can invoke as if it were in the interface * @throws org.logicalcobwebs.proxool.ProxoolException if the method is not found. */ public static Method getConcreteMethod(Class concreteClass, Method injectableMethod) throws ProxoolException { // Unless the concrete class is public we can't do anything if (Modifier.isPublic(concreteClass.getModifiers())) { Object key = concreteClass.getName() + ":" + injectableMethod.getName(); MethodMapper methodMapper = (MethodMapper) methodMappers.get(key); if (methodMapper == null) { methodMapper = new MethodMapper(concreteClass); methodMappers.put(key, methodMapper); } return methodMapper.getConcreteMethod(injectableMethod); } else { return injectableMethod; } } /** * Override the method provided by the {@link #getConcreteMethod(java.lang.Class, java.lang.reflect.Method)}. Use this * if you decide that the concrete method provided wasn't any good. For instance, if you get an IllegalAccessException * whilst invoking the concrete method then you should perhaps try using the proxy supplied method instead. * @param concreteClass the class we are invoking upon * @param injectableMethod the method supplied by the proxy * @param overridenMethod the one we are going to use (probably the same as injectrableMethod actually) */ public static void overrideConcreteMethod(Class concreteClass, Method injectableMethod, Method overridenMethod) { Object key = concreteClass.getName() + ":" + injectableMethod.getName(); MethodMapper methodMapper = (MethodMapper) methodMappers.get(key); if (methodMapper == null) { methodMapper = new MethodMapper(concreteClass); methodMappers.put(key, methodMapper); } methodMapper.overrideConcreteMethod(injectableMethod, overridenMethod); } } /* Revision history: $Log: InvokerFacade.java,v $ Revision 1.3 2004/07/13 21:13:14 billhorsman Optimise using injectable interfaces on methods that are declared in non-public classes by not bothering to use concrete methods at all (it's not possible). Revision 1.2 2004/07/13 21:06:16 billhorsman Fix problem using injectable interfaces on methods that are declared in non-public classes. Revision 1.1 2004/06/02 20:43:53 billhorsman New classes to support injectable interfaces */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/proxy/MethodMapper.java0000644000175000017500000001111610730503125031113 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.proxy; import org.logicalcobwebs.proxool.ProxoolException; import java.lang.reflect.Method; import java.util.Map; import java.util.HashMap; /** * Handles the mapping between methods with identical signatures but that are not related * by inheritance. This allows you to invoke a method on a class using an interface that * it doesn't actually implement. It caches the result of its reflective lookup to save time. * If the concreteClass does in fact implement the injectable interface then it quickly * returns the method without the penalty of mapping using reflection. * * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.2 $, $Date: 2004/07/13 21:06:18 $ * @since Proxool 0.9 */ public class MethodMapper { private Class concreteClass; private Map cachedConcreteMethods = new HashMap(); ; /** * @param concreteClass the class that we want to invoke methods on. It should either implement all methods on * the injectable interface, or provide methods with an identical signature. */ public MethodMapper(Class concreteClass) { this.concreteClass = concreteClass; } /** * Returns the method in the concrete class with an indentical signature to that passed * as a parameter * * @param injectableMethod provides signature that we are trying to match * @return the method in the concrete class that we can invoke as if it were in the interface * @throws org.logicalcobwebs.proxool.ProxoolException * if the method is not found. */ protected Method getConcreteMethod(Method injectableMethod) throws ProxoolException { // Do we have a cached reference? Method concreteMethod = (Method) cachedConcreteMethods.get(injectableMethod); if (concreteMethod == null) { // Look it up Method[] candidateMethods = concreteClass.getMethods(); for (int i = 0; i < candidateMethods.length; i++) { Method candidateMethod = candidateMethods[i]; // First pass: does the name, parameter count and return type match? if (candidateMethod.getName().equals(injectableMethod.getName()) && candidateMethod.getParameterTypes().length == injectableMethod.getParameterTypes().length && candidateMethod.getReturnType().equals(injectableMethod.getReturnType())) { // Let's check each parameter type boolean matches = true; Class[] candidateTypes = candidateMethod.getParameterTypes(); Class[] injectableTypes = injectableMethod.getParameterTypes(); for (int j = 0; j < candidateTypes.length; j++) { if (!candidateTypes[j].equals(injectableTypes[j])) { matches = false; break; } } if (matches) { concreteMethod = candidateMethod; break; } } } // Success? if (concreteMethod == null) { throw new ProxoolException("Couldn't match injectable method " + injectableMethod + " with any of those " + "found in " + concreteClass.getName()); } // Remember it cachedConcreteMethods.put(injectableMethod, concreteMethod); } return concreteMethod; } /** * Don't use the one we calculate using {@link #getConcreteMethod(java.lang.reflect.Method)}, use this one instead. * @param injectableMethod the method supplied by the proxy * @param overridenMethod the one we are going to use (probably the same as injectrableMethod actually) */ public void overrideConcreteMethod(Method injectableMethod, Method overridenMethod) { cachedConcreteMethods.put(injectableMethod, overridenMethod); } } /* Revision history: $Log: MethodMapper.java,v $ Revision 1.2 2004/07/13 21:06:18 billhorsman Fix problem using injectable interfaces on methods that are declared in non-public classes. Revision 1.1 2004/06/02 20:43:53 billhorsman New classes to support injectable interfaces */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/resources/0000755000175000017500000000000011054125603026515 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/resources/ResourceNamesIF.java0000644000175000017500000000210410730503125032346 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.resources; /** * Constants for Proxool resource names. * @version $Revision: 1.3 $, $Date: 2003/03/03 11:12:01 $ * @author Christian Nedregaard (christian.nedregard@findexa.no) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public interface ResourceNamesIF { /** * Name of the attributeDescriptions resource. */ static final String ATTRIBUTE_DESCRIPTIONS = "org.logicalcobwebs.proxool.resources.attributeDescriptions"; /** * Name of the jmx resource. */ static final String JMX = "org.logicalcobwebs.proxool.resources.jmx"; } /* $Log: ResourceNamesIF.java,v $ Revision 1.3 2003/03/03 11:12:01 billhorsman fixed licence Revision 1.2 2003/02/26 16:59:54 billhorsman fixed encoding in chr's name Revision 1.1 2003/02/24 01:12:01 chr32 Init rev. */ ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/resources/attributeDescriptions.propertieslibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/resources/attributeDescriptions.prope0000644000175000017500000002062210730503125034157 0ustar twernertwerneralias=\ The name used to uniquely identify the pool to Proxool. driver-url=\ The delegate JDBC driver class. driver-properties=\ A set of comma separated propeties that are passed to the delegate driver. \ Example: user=foo, password=bar. fatal-sql-exception=\ All SQLExceptions are caught and tested for containing this text fragment. \ If it matches than this connection is considered useless and it is discarded. \ Regardless of what happens the exception is always thrown again. This property \ behaves like a collection; separate multiple exception fragments with a comma. \ Default: null. fatal-sql-exception-wrapper-class=\ If this is not-null then any fatal SQLException is wrapped up inside \ an instance of this class. If null, then the original exception is \ thrown. Range: any valid class name that is a subclass of SQLException or \ RuntimeException. Default: null (original exception is thrown) \ Examples: 'org.logicalcobwebs.proxool.FatalSQLException' or \ org.logicalcobwebs.proxool.FatalRuntimeException' house-keeping-sleep-time=\ How long the house keeping thread sleeps for (milliseconds). \ The house keeper is responsible for checking the state of all the connections and sees whether any need to be \ destroyed or created. It also runs any tests that have been configured. Default is 30000 (30 seconds). house-keeping-test-sql=\ If the house keeping thread finds any idle connections it will test them \ with this SQL statement. It should be _very_ quick to execute. Something like checking the current date or something. \ If not defined then this test is omitted. Default: null. injectable-connection-interface=\ If this is set then all connections will implement this interface. You will be able to cast a served connection \ into this interface and call any of its methods. Note: the vendor connection does not have to implement this method \ directly - in fact it shouldn't, because if it does it will be exposed automatically. If the vendor connection \ doesn't implement a method that matches the signature of the interface method then you will get a RuntimeException \ when you try and call that method. Default: null (no additional interfaces are exposed. injectable-statement-interface=\ If this is set then all statements will implement this interface. You will be able to cast a served statement \ into this interface and call any of its methods. Note: the vendor statement does not have to implement this method \ directly - in fact it shouldn't, because if it does it will be exposed automatically. If the vendor statement \ doesn't implement a method that matches the signature of the interface method then you will get a RuntimeException \ when you try and call that method. Default: null (no additional interfaces are exposed. injectable-prepared-statement-interface=\ If this is set then all prepared statements will implement this interface. You will be able to cast a served prepared statement \ into this interface and call any of its methods. Note: the vendor prepared statement does not have to implement this method \ directly - in fact it shouldn't, because if it does it will be exposed automatically. If the vendor prepared statement \ doesn't implement a method that matches the signature of the interface method then you will get a RuntimeException \ when you try and call that method. Default: null (no additional interfaces are exposed. injectable-callable-statement-interface=\ If this is set then all callable statements will implement this interface. You will be able to cast a served callable statement \ into this interface and call any of its methods. Note: the vendor callable statement does not have to implement this method \ directly - in fact it shouldn't, because if it does it will be exposed automatically. If the vendor callable statement \ doesn't implement a method that matches the signature of the interface method then you will get a RuntimeException \ when you try and call that method. Default: null (no additional interfaces are exposed. jmx=\ Indicate wether this pool should be registered with JMX or not. True or false. Default is false. jmx-agent-id=\ Get a comma separated list of JMX agent ids (as used by MBeanServerFactory) to register the pool to. maximum-active-time=\ If the housekeeper comes across a thread that has been active for longer than \ this then it will kill it. So make sure you set this to a number bigger than your slowest expected response! \ Units: milliseconds. Default: 300000 (5 minutes). maximum-connection-count=\ The maximum number of connections to the database. Default: 15. maximum-connection-lifetime=\ The maximum amount of time that a connection exists for before it is \ killed. Units: milliseconds. Default: 14400000 (4 hours). maximum-new-connections=\ This is the maximum number of connections we can be building at any \ one time. That is, the number of new connections that have been requested but aren't yet available for use. \ Because connections can be built using more than one thread (for instance, when they are built on demand) and it \ takes a finite time between deciding to build the connection and it becoming available we need some way of ensuring \ that a lot of threads don't all decide to build a connection at once. (We could solve this in a smarter way - and \ indeed we will one day) Default: 10. minimum-connection-count=\ The minimum number of connections we will keep open, regardless of \ whether anyone needs them or not. Default: 5. overload-without-refusal-lifetime=\ This helps us determine the pool status. If we have refused a \ connection within this threshold (milliseconds) then we are overloaded. Units: milliseconds. Default: 60000 (1 minute). prototype-count=\ If there are fewer than this number of connections available then we will \ build some more (assuming the maximum-connection-count is not exceeded). For example. Of we have 3 active \ connections and 2 available, but our prototype-count is 4 then it will attempt to build another 2. \ This differs from minimum-connection-count because it takes into account the number of active connections. \ minimum-connection-count is absolute and doesn't care how many are in use. prototype-count is the number of \ spare connections it strives to keep over and above the ones that are currently active. Default: 0. recently-started-threshold=\ This helps us determine whether the pool status is up, down or \ overloaded. As long as at least one connection was started within this threshold (milliseconds) or there are some \ spare connections available then we assume the pool is up. Units: milliseconds. Default: 60000 (1 minute). simultaneous-build-throttle=\ This is the maximum number of connections we can be building at any \ one time. That is, the number of new connections that have been requested but aren't yet available for use. \ Because connections can be built using more than one thread (for instance, when they are built on demand) and it \ takes a finite time between deciding to build the connection and it becoming available we need some way of ensuring \ that a lot of threads don't all decide to build a connection at once. (We could solve this in a smarter way - and \ indeed we will one day) Default: 10. statistics=\ The sample length when taking statistical information, comma-delimited. \ For example: '10s,15m' would mean take samples every 10 seconds and every 15 minutes. Valid units are \ s(econds), m(inutes), h(ours) and d(ays). Default: null (no statistics). statistics-log-level=\ Whether statistics are logged as they are produced. \ Range: DEBUG, INFO, WARN, ERROR, FATAL. Default: null (no logging). test-after-use=\ If you set this to true then each connection is tested (with whatever is defined in \ house-keeping-test-sql) after it is closed (that is, returned to the connection pool). \ If a connection fails then it is discarded. True or false. Default: false. test-before-use=\ If you set this to true then each connection is tested (with whatever is defined in house-keeping-test-sql) \ before being served. If a connection fails then it is discarded and another one is picked. If all \ connections fail a new one is built. If that one fails then you get an SQLException saying so. \ True or false. Default: false. trace=\ If true then each SQL call gets logged (DEBUG level) along with the execution time. \ You can also get this information by registering a ConnectionListener (see ProxoolFacade). \ True or false. Default: false. verbose=\ Either false (quiet) or true (loud). True or false. Default: false. libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/resources/jmx.properties0000644000175000017500000000031710730503125031431 0ustar twernertwernermbean.notification.defUpdated=\ The pool definition has been updated. mbean.notification.description=\ Only standard Notification instances are used. mbean.pool.description=\ The ''{0}'' connection pool. libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/util/0000755000175000017500000000000011054125603025460 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/util/AbstractListenerContainer.java0000644000175000017500000001040310025537541033442 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.util; /** * Implementation of {@link ListenerContainerIF} that uses a reads/write lock to handle concurrency in a safe and * fast way. *

    * The registered listeners are offered to subclasses through the protected {@link #getListeners} method. This * method returns a reference to an array containing the registered listeners. A new array holding the listeners * is created everytime a modification on the registration list is required (add/remove listener). Therefore, * subclasses can safely iterate over the received array. * * Your code sould look like this: * *

         Object[] listeners = getListeners();
         for(int i=0; i
     
     * 

    * * @version $Revision: 1.8 $, $Date: 2004/03/16 08:48:33 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: brenuart $ (current maintainer) * @since Proxool 0.7 */ public abstract class AbstractListenerContainer implements ListenerContainerIF { private Object[] listeners = EMPTY_LISTENERS; private static final Object[] EMPTY_LISTENERS = new Object[]{}; /** * @see ListenerContainerIF#addListener(Object) */ public synchronized void addListener(Object listener) { if(listener==null) throw new NullPointerException("Unexpected NULL listener argument received"); // create a new array Object[] newListeners = new Object[listeners.length+1]; // copy listeners currently registered System.arraycopy(listeners, 0, newListeners, 0, listeners.length); // add the new one newListeners[listeners.length] = listener; // commit changes listeners = newListeners; } /** * @see ListenerContainerIF#removeListener(Object) */ public synchronized boolean removeListener(Object listener) { if(listener==null) throw new NullPointerException("Unexpected NULL listener argument received"); // find listener to remove in the list int index=-1; for(int i=0; i 0 ) System.arraycopy(listeners, 0, newListeners, 0, index); if( index < listeners.length-1 ) System.arraycopy(listeners, index+1, newListeners, index, listeners.length-index-1); // commit listeners = newListeners; return true; } /** * Get a reference to the array of registered listeners. * * @return reference to the array containing registered listeners (always not NULL) */ protected Object[] getListeners() { return listeners; } /** * @see ListenerContainerIF#isEmpty() */ public boolean isEmpty() { return listeners.length==0; } } /* Revision history: $Log: AbstractListenerContainer.java,v $ Revision 1.8 2004/03/16 08:48:33 brenuart Changes in the AbstractListenerContainer: - provide more efficient concurrent handling; - better handling of RuntimeException thrown by external listeners. Revision 1.7 2003/03/11 00:12:11 billhorsman switch to concurrent package Revision 1.6 2003/03/10 15:26:55 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.5 2003/03/03 11:12:01 billhorsman fixed licence Revision 1.4 2003/02/19 19:35:21 chr32 Formated code in javadoc. Revision 1.3 2003/02/07 17:20:18 billhorsman checkstyle Revision 1.2 2003/02/07 15:06:43 billhorsman fixed isEmpty bug Revision 1.1 2003/02/07 01:46:31 chr32 Initial revition. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/util/FastArrayList.java0000644000175000017500000011663610730503124031066 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net * * THIS CLASS WAS COPIED FROM THE JAKARTA COMMONS COLLECTIONS * VERSION 2.1. WE ARE GRATEFUL FOR THEIR CONTRIBUTION. We decided * not to introduce the whole library as a dependency at this stage but might decide * to at a later date. */ /* * $Header: /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/proxool/util/FastArrayList.java,v 1.4 2003/03/10 23:43:18 billhorsman Exp $ * $Revision: 1.4 $ * $Date: 2003/03/10 23:43:18 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ package org.logicalcobwebs.proxool.util; import java.util.ArrayList; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** *

    A customized implementation of java.util.ArrayList designed * to operate in a multithreaded environment where the large majority of * method calls are read-only, instead of structural changes. When operating * in "fast" mode, read calls are non-synchronized and write calls perform the * following steps:

    *
      *
    • Clone the existing collection *
    • Perform the modification on the clone *
    • Replace the existing collection with the (modified) clone *
    *

    When first created, objects of this class default to "slow" mode, where * all accesses of any type are synchronized but no cloning takes place. This * is appropriate for initially populating the collection, followed by a switch * to "fast" mode (by calling setFast(true)) after initialization * is complete.

    * *

    NOTE: If you are creating and accessing an * ArrayList only within a single thread, you should use * java.util.ArrayList directly (with no synchronization), for * maximum performance.

    * *

    NOTE: This class is not cross-platform. * Using it may cause unexpected failures on some architectures. * It suffers from the same problems as the double-checked locking idiom. * In particular, the instruction that clones the internal collection and the * instruction that sets the internal reference to the clone can be executed * or perceived out-of-order. This means that any read operation might fail * unexpectedly, as it may be reading the state of the internal collection * before the internal collection is fully formed. * For more information on the double-checked locking idiom, see the * * Double-Checked Locking Idiom Is Broken Declartion.

    * * @since Proxool 0.6 * @author Craig R. McClanahan * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.4 $ $Date: 2003/03/10 23:43:18 $ */ public class FastArrayList extends ArrayList { // ----------------------------------------------------------- Constructors /** * Construct a an empty list. */ public FastArrayList() { super(); this.list = new ArrayList(); } /** * Construct an empty list with the specified capacity. * * @param capacity The initial capacity of the empty list */ public FastArrayList(int capacity) { super(); this.list = new ArrayList(capacity); } /** * Construct a list containing the elements of the specified collection, * in the order they are returned by the collection's iterator. * * @param collection The collection whose elements initialize the contents * of this list */ public FastArrayList(Collection collection) { super(); this.list = new ArrayList(collection); } // ----------------------------------------------------- Instance Variables /** * The underlying list we are managing. */ private ArrayList list = null; // ------------------------------------------------------------- Properties /** * Are we operating in "fast" mode? */ private boolean fast = false; /** * Returns true if this list is operating in fast mode. * * @return true if this list is operating in fast mode */ public boolean getFast() { return (this.fast); } /** * Sets whether this list will operate in fast mode. * * @param fast true if the list should operate in fast mode */ public void setFast(boolean fast) { this.fast = fast; } // --------------------------------------------------------- Public Methods /** * Appends the specified element to the end of this list. * * @param element The element to be appended */ public boolean add(Object element) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); boolean result = temp.add(element); list = temp; return (result); } } else { synchronized (list) { return (list.add(element)); } } } /** * Insert the specified element at the specified position in this list, * and shift all remaining elements up one position. * * @param index Index at which to insert this element * @param element The element to be inserted * * @exception java.lang.IndexOutOfBoundsException if the index is out of range */ public void add(int index, Object element) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); temp.add(index, element); list = temp; } } else { synchronized (list) { list.add(index, element); } } } /** * Append all of the elements in the specified Collection to the end * of this list, in the order that they are returned by the specified * Collection's Iterator. * * @param collection The collection to be appended */ public boolean addAll(Collection collection) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); boolean result = temp.addAll(collection); list = temp; return (result); } } else { synchronized (list) { return (list.addAll(collection)); } } } /** * Insert all of the elements in the specified Collection at the specified * position in this list, and shift any previous elements upwards as * needed. * * @param index Index at which insertion takes place * @param collection The collection to be added * * @exception java.lang.IndexOutOfBoundsException if the index is out of range */ public boolean addAll(int index, Collection collection) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); boolean result = temp.addAll(index, collection); list = temp; return (result); } } else { synchronized (list) { return (list.addAll(index, collection)); } } } /** * Remove all of the elements from this list. The list will be empty * after this call returns. * * @exception java.lang.UnsupportedOperationException if clear() * is not supported by this list */ public void clear() { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); temp.clear(); list = temp; } } else { synchronized (list) { list.clear(); } } } /** * Return a shallow copy of this FastArrayList instance. * The elements themselves are not copied. */ public Object clone() { FastArrayList results = null; if (fast) { results = new FastArrayList(list); } else { synchronized (list) { results = new FastArrayList(list); } } results.setFast(getFast()); return (results); } /** * Return true if this list contains the specified element. * * @param element The element to test for */ public boolean contains(Object element) { if (fast) { return (list.contains(element)); } else { synchronized (list) { return (list.contains(element)); } } } /** * Return true if this list contains all of the elements * in the specified Collection. * * @param collection Collection whose elements are to be checked */ public boolean containsAll(Collection collection) { if (fast) { return (list.containsAll(collection)); } else { synchronized (list) { return (list.containsAll(collection)); } } } /** * Increase the capacity of this ArrayList instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param capacity The new minimum capacity */ public void ensureCapacity(int capacity) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); temp.ensureCapacity(capacity); list = temp; } } else { synchronized (list) { list.ensureCapacity(capacity); } } } /** * Compare the specified object with this list for equality. This * implementation uses exactly the code that is used to define the * list equals function in the documentation for the * List.equals method. * * @param o Object to be compared to this list */ public boolean equals(Object o) { // Simple tests that require no synchronization if (o == this) { return (true); } else if (!(o instanceof List)) { return (false); } List lo = (List) o; // Compare the sets of elements for equality if (fast) { ListIterator li1 = list.listIterator(); ListIterator li2 = lo.listIterator(); while (li1.hasNext() && li2.hasNext()) { Object o1 = li1.next(); Object o2 = li2.next(); if (!(o1 == null ? o2 == null : o1.equals(o2))) { return (false); } } return (!(li1.hasNext() || li2.hasNext())); } else { synchronized (list) { ListIterator li1 = list.listIterator(); ListIterator li2 = lo.listIterator(); while (li1.hasNext() && li2.hasNext()) { Object o1 = li1.next(); Object o2 = li2.next(); if (!(o1 == null ? o2 == null : o1.equals(o2))) { return (false); } } return (!(li1.hasNext() || li2.hasNext())); } } } /** * Return the element at the specified position in the list. * * @param index The index of the element to return * * @exception java.lang.IndexOutOfBoundsException if the index is out of range */ public Object get(int index) { if (fast) { return (list.get(index)); } else { synchronized (list) { return (list.get(index)); } } } /** * Return the hash code value for this list. This implementation uses * exactly the code that is used to define the list hash function in the * documentation for the List.hashCode method. */ public int hashCode() { if (fast) { int hashCode = 1; java.util.Iterator i = list.iterator(); while (i.hasNext()) { Object o = i.next(); hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode()); } return (hashCode); } else { synchronized (list) { int hashCode = 1; java.util.Iterator i = list.iterator(); while (i.hasNext()) { Object o = i.next(); hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode()); } return (hashCode); } } } /** * Search for the first occurrence of the given argument, testing * for equality using the equals() method, and return * the corresponding index, or -1 if the object is not found. * * @param element The element to search for */ public int indexOf(Object element) { if (fast) { return (list.indexOf(element)); } else { synchronized (list) { return (list.indexOf(element)); } } } /** * Test if this list has no elements. */ public boolean isEmpty() { if (fast) { return (list.isEmpty()); } else { synchronized (list) { return (list.isEmpty()); } } } /** * Return an iterator over the elements in this list in proper sequence. *

    * IMPLEMENTATION NOTE - If the list is operating in fast * mode, an Iterator is returned, and a structural modification to the * list is made, then the Iterator will continue over the previous contents * of the list (at the time that the Iterator was created), rather than * failing due to concurrent modifications. */ public Iterator iterator() { if (fast) { return new ListIter(0); } else { return list.iterator(); } } /** * Search for the last occurrence of the given argument, testing * for equality using the equals() method, and return * the corresponding index, or -1 if the object is not found. * * @param element The element to search for */ public int lastIndexOf(Object element) { if (fast) { return (list.lastIndexOf(element)); } else { synchronized (list) { return (list.lastIndexOf(element)); } } } /** * Return an iterator of the elements of this list, in proper sequence. * See the implementation note on iterator(). */ public ListIterator listIterator() { if (fast) { return new ListIter(0); } else { return list.listIterator(); } } /** * Return an iterator of the elements of this list, in proper sequence, * starting at the specified position. * See the implementation note on iterator(). * * @param index The starting position of the iterator to return * * @exception java.lang.IndexOutOfBoundsException if the index is out of range */ public ListIterator listIterator(int index) { if (fast) { return new ListIter(index); } else { return list.listIterator(index); } } /** * Remove the element at the specified position in the list, and shift * any subsequent elements down one position. * * @param index Index of the element to be removed * * @exception java.lang.IndexOutOfBoundsException if the index is out of range */ public Object remove(int index) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); Object result = temp.remove(index); list = temp; return (result); } } else { synchronized (list) { return (list.remove(index)); } } } /** * Remove the first occurrence of the specified element from the list, * and shift any subsequent elements down one position. * * @param element Element to be removed */ public boolean remove(Object element) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); boolean result = temp.remove(element); list = temp; return (result); } } else { synchronized (list) { return (list.remove(element)); } } } /** * Remove from this collection all of its elements that are contained * in the specified collection. * * @param collection Collection containing elements to be removed * * @exception java.lang.UnsupportedOperationException if this optional operation * is not supported by this list */ public boolean removeAll(Collection collection) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); boolean result = temp.removeAll(collection); list = temp; return (result); } } else { synchronized (list) { return (list.removeAll(collection)); } } } /** * Remove from this collection all of its elements except those that are * contained in the specified collection. * * @param collection Collection containing elements to be retained * * @exception java.lang.UnsupportedOperationException if this optional operation * is not supported by this list */ public boolean retainAll(Collection collection) { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); boolean result = temp.retainAll(collection); list = temp; return (result); } } else { synchronized (list) { return (list.retainAll(collection)); } } } /** * Replace the element at the specified position in this list with * the specified element. Returns the previous object at that position. *

    * IMPLEMENTATION NOTE - This operation is specifically * documented to not be a structural change, so it is safe to be performed * without cloning. * * @param index Index of the element to replace * @param element The new element to be stored * * @exception java.lang.IndexOutOfBoundsException if the index is out of range */ public Object set(int index, Object element) { if (fast) { return (list.set(index, element)); } else { synchronized (list) { return (list.set(index, element)); } } } /** * Return the number of elements in this list. */ public int size() { if (fast) { return (list.size()); } else { synchronized (list) { return (list.size()); } } } /** * Return a view of the portion of this list between fromIndex * (inclusive) and toIndex (exclusive). The returned list is backed * by this list, so non-structural changes in the returned list are * reflected in this list. The returned list supports * all of the optional list operations supported by this list. * * @param fromIndex The starting index of the sublist view * @param toIndex The index after the end of the sublist view * * @exception java.lang.IndexOutOfBoundsException if an index is out of range */ public List subList(int fromIndex, int toIndex) { if (fast) { return new SubList(fromIndex, toIndex); } else { return list.subList(fromIndex, toIndex); } } /** * Return an array containing all of the elements in this list in the * correct order. */ public Object[] toArray() { if (fast) { return (list.toArray()); } else { synchronized (list) { return (list.toArray()); } } } /** * Return an array containing all of the elements in this list in the * correct order. The runtime type of the returned array is that of * the specified array. If the list fits in the specified array, it is * returned therein. Otherwise, a new array is allocated with the * runtime type of the specified array, and the size of this list. * * @param array Array defining the element type of the returned list * * @exception java.lang.ArrayStoreException if the runtime type of array * is not a supertype of the runtime type of every element in this list */ public Object[] toArray(Object array[]) { if (fast) { return (list.toArray(array)); } else { synchronized (list) { return (list.toArray(array)); } } } /** * Return a String representation of this object. */ public String toString() { StringBuffer sb = new StringBuffer("FastArrayList["); sb.append(list.toString()); sb.append("]"); return (sb.toString()); } /** * Trim the capacity of this ArrayList instance to be the * list's current size. An application can use this operation to minimize * the storage of an ArrayList instance. */ public void trimToSize() { if (fast) { synchronized (this) { ArrayList temp = (ArrayList) list.clone(); temp.trimToSize(); list = temp; } } else { synchronized (list) { list.trimToSize(); } } } private class SubList implements List { private int first; private int last; private List expected; public SubList(int first, int last) { this.first = first; this.last = last; this.expected = list; } private List get(List l) { if (list != expected) { throw new ConcurrentModificationException(); } return l.subList(first, last); } public void clear() { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); get(temp).clear(); last = first; list = temp; expected = temp; } } else { synchronized (list) { get(expected).clear(); } } } public boolean remove(Object o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); boolean r = get(temp).remove(o); if (r) { last--; } list = temp; expected = temp; return r; } } else { synchronized (list) { return get(expected).remove(o); } } } public boolean removeAll(Collection o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); List sub = get(temp); boolean r = sub.removeAll(o); if (r) { last = first + sub.size(); } list = temp; expected = temp; return r; } } else { synchronized (list) { return get(expected).removeAll(o); } } } public boolean retainAll(Collection o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); List sub = get(temp); boolean r = sub.retainAll(o); if (r) { last = first + sub.size(); } list = temp; expected = temp; return r; } } else { synchronized (list) { return get(expected).retainAll(o); } } } public int size() { if (fast) { return get(expected).size(); } else { synchronized (list) { return get(expected).size(); } } } public boolean isEmpty() { if (fast) { return get(expected).isEmpty(); } else { synchronized (list) { return get(expected).isEmpty(); } } } public boolean contains(Object o) { if (fast) { return get(expected).contains(o); } else { synchronized (list) { return get(expected).contains(o); } } } public boolean containsAll(Collection o) { if (fast) { return get(expected).containsAll(o); } else { synchronized (list) { return get(expected).containsAll(o); } } } public Object[] toArray(Object[] o) { if (fast) { return get(expected).toArray(o); } else { synchronized (list) { return get(expected).toArray(o); } } } public Object[] toArray() { if (fast) { return get(expected).toArray(); } else { synchronized (list) { return get(expected).toArray(); } } } public boolean equals(Object o) { if (o == this) { return true; } if (fast) { return get(expected).equals(o); } else { synchronized (list) { return get(expected).equals(o); } } } public int hashCode() { if (fast) { return get(expected).hashCode(); } else { synchronized (list) { return get(expected).hashCode(); } } } public boolean add(Object o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); boolean r = get(temp).add(o); if (r) { last++; } list = temp; expected = temp; return r; } } else { synchronized (list) { return get(expected).add(o); } } } public boolean addAll(Collection o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); boolean r = get(temp).addAll(o); if (r) { last += o.size(); } list = temp; expected = temp; return r; } } else { synchronized (list) { return get(expected).addAll(o); } } } public void add(int i, Object o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); get(temp).add(i, o); last++; list = temp; expected = temp; } } else { synchronized (list) { get(expected).add(i, o); } } } public boolean addAll(int i, Collection o) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); boolean r = get(temp).addAll(i, o); list = temp; if (r) { last += o.size(); } expected = temp; return r; } } else { synchronized (list) { return get(expected).addAll(i, o); } } } public Object remove(int i) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); Object o = get(temp).remove(i); last--; list = temp; expected = temp; return o; } } else { synchronized (list) { return get(expected).remove(i); } } } public Object set(int i, Object a) { if (fast) { synchronized (FastArrayList.this) { ArrayList temp = (ArrayList) list.clone(); Object o = get(temp).set(i, a); list = temp; expected = temp; return o; } } else { synchronized (list) { return get(expected).set(i, a); } } } public Iterator iterator() { return new SubListIter(0); } public ListIterator listIterator() { return new SubListIter(0); } public ListIterator listIterator(int i) { return new SubListIter(i); } public Object get(int i) { if (fast) { return get(expected).get(i); } else { synchronized (list) { return get(expected).get(i); } } } public int indexOf(Object o) { if (fast) { return get(expected).indexOf(o); } else { synchronized (list) { return get(expected).indexOf(o); } } } public int lastIndexOf(Object o) { if (fast) { return get(expected).lastIndexOf(o); } else { synchronized (list) { return get(expected).lastIndexOf(o); } } } public List subList(int f, int l) { if (list != expected) { throw new ConcurrentModificationException(); } return new SubList(first + f, f + l); } private class SubListIter implements ListIterator { private List expected; private ListIterator iter; private int lastReturnedIndex = -1; public SubListIter(int i) { this.expected = list; this.iter = SubList.this.get(expected).listIterator(i); } private void checkMod() { if (list != expected) { throw new ConcurrentModificationException(); } } List get() { return SubList.this.get(expected); } public boolean hasNext() { checkMod(); return iter.hasNext(); } public Object next() { checkMod(); lastReturnedIndex = iter.nextIndex(); return iter.next(); } public boolean hasPrevious() { checkMod(); return iter.hasPrevious(); } public Object previous() { checkMod(); lastReturnedIndex = iter.previousIndex(); return iter.previous(); } public int previousIndex() { checkMod(); return iter.previousIndex(); } public int nextIndex() { checkMod(); return iter.nextIndex(); } public void remove() { checkMod(); if (lastReturnedIndex < 0) { throw new IllegalStateException(); } get().remove(lastReturnedIndex); last--; expected = list; iter = get().listIterator(previousIndex()); lastReturnedIndex = -1; } public void set(Object o) { checkMod(); if (lastReturnedIndex < 0) { throw new IllegalStateException(); } get().set(lastReturnedIndex, o); expected = list; iter = get().listIterator(previousIndex() + 1); } public void add(Object o) { checkMod(); int i = nextIndex(); get().add(i, o); last++; iter = get().listIterator(i + 1); lastReturnedIndex = 1; } } } private class ListIter implements ListIterator { private List expected; private ListIterator iter; private int lastReturnedIndex = -1; public ListIter(int i) { this.expected = list; this.iter = get().listIterator(i); } private void checkMod() { if (list != expected) { throw new ConcurrentModificationException(); } } List get() { return expected; } public boolean hasNext() { checkMod(); return iter.hasNext(); } public Object next() { checkMod(); lastReturnedIndex = iter.nextIndex(); return iter.next(); } public boolean hasPrevious() { checkMod(); return iter.hasPrevious(); } public Object previous() { checkMod(); lastReturnedIndex = iter.previousIndex(); return iter.previous(); } public int previousIndex() { checkMod(); return iter.previousIndex(); } public int nextIndex() { checkMod(); return iter.nextIndex(); } public void remove() { checkMod(); if (lastReturnedIndex < 0) { throw new IllegalStateException(); } get().remove(lastReturnedIndex); expected = list; iter = get().listIterator(previousIndex()); lastReturnedIndex = -1; } public void set(Object o) { checkMod(); if (lastReturnedIndex < 0) { throw new IllegalStateException(); } get().set(lastReturnedIndex, o); expected = list; iter = get().listIterator(previousIndex() + 1); } public void add(Object o) { checkMod(); int i = nextIndex(); get().add(i, o); iter = get().listIterator(i + 1); lastReturnedIndex = 1; } } } /* Revision history: $Log: FastArrayList.java,v $ Revision 1.4 2003/03/10 23:43:18 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.3 2003/03/10 15:27:00 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.2 2003/03/03 11:12:02 billhorsman fixed licence Revision 1.1 2003/02/07 01:40:34 chr32 Ok. Now *really* moving in from main proxool package. Revision 1.4 2003/02/07 01:34:17 chr32 Made class public. Revision 1.3 2003/02/07 01:33:31 chr32 Moved in from main proxool package. Revision 1.2 2003/01/15 14:51:14 billhorsman checkstyle */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/util/ListenerContainerIF.java0000644000175000017500000000243210730503124032171 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.util; /** * A container for event listeners. Implementations should cater to only one type of listeners. * @version $Revision: 1.2 $, $Date: 2003/03/03 11:12:02 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public interface ListenerContainerIF { /** * Add a listener to this container. * @param listener the listener to add. */ void addListener(Object listener); /** * Remove a listener from this container. * @param listener the listener to be removed. * @return wether the listnener was found and removed or not. */ boolean removeListener(Object listener); /** * Get wether this container is empty or not. * @return wether this container is empty or not. */ boolean isEmpty() ; } /* Revision history: $Log: ListenerContainerIF.java,v $ Revision 1.2 2003/03/03 11:12:02 billhorsman fixed licence Revision 1.1 2003/02/07 01:46:31 chr32 Initial revition. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/AbstractProxyStatement.java0000644000175000017500000003027210730503125032043 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.SQLException; import java.sql.Statement; import java.sql.Connection; import java.util.*; import java.text.DateFormat; import java.text.SimpleDateFormat; /** * Contains most of the functionality that we require to manipilate the * statement. The subclass of this defines how we delegate to the * real statement. * @version $Revision: 1.23 $, $Date: 2007/01/25 23:38:24 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ abstract class AbstractProxyStatement { private static final Log LOG = LogFactory.getLog(ProxyStatement.class); private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy.HH:mm:ss"); private Statement statement; private ConnectionPool connectionPool; private ProxyConnectionIF proxyConnection; private Map parameters; private String sqlStatement; private StringBuffer sqlLog = new StringBuffer(); /** * @param statement the real statement that we will delegate to * @param connectionPool the connection pool that we are using * @param proxyConnection the connection that was used to create the statement * @param sqlStatement the SQL statement that was used to create this statement * (optional, can be null) so that we can use if for tracing. */ public AbstractProxyStatement(Statement statement, ConnectionPool connectionPool, ProxyConnectionIF proxyConnection, String sqlStatement) { this.statement = statement; this.connectionPool = connectionPool; this.proxyConnection = proxyConnection; this.sqlStatement = sqlStatement; } /** * Check to see whether an exception is a fatal one. If it is, then throw the connection * away (and it won't be made available again) * @param t the exception to test */ protected boolean testException(Throwable t) { if (FatalSqlExceptionHelper.testException(connectionPool.getDefinition(), t)) { // This SQL exception indicates a fatal problem with this connection. We should probably // just junk it. try { statement.close(); connectionPool.throwConnection(proxyConnection, ConnectionListenerIF.FATAL_SQL_EXCEPTION_DETECTED, "Fatal SQL Exception has been detected"); // We should check all the existing connections as soon as possible HouseKeeperController.sweepNow(connectionPool.getDefinition().getAlias()); LOG.warn("Connection has been thrown away because fatal exception was detected", t); } catch (SQLException e2) { LOG.error("Problem trying to throw away suspect connection", e2); } return true; } else { return false; } } /** * Gets the real Statement that we got from the delegate driver * @return delegate statement */ public Statement getDelegateStatement() { return statement; } /** * The connection pool we are using * @return connectionPool */ protected ConnectionPool getConnectionPool() { return connectionPool; } /** * The real, delegate statement * @return statement */ protected Statement getStatement() { return statement; } /** * Close the statement and tell the ProxyConnection that it did so. * @throws SQLException if it couldn't be closed * @see ProxyConnectionIF#registerClosedStatement */ public void close() throws SQLException { statement.close(); proxyConnection.registerClosedStatement(statement); } protected Connection getConnection() { return ProxyFactory.getWrappedConnection((ProxyConnection) proxyConnection); } /** * Whether the delegate statements are the same * @see Object#equals */ public boolean equals(Object obj) { return (statement.hashCode() == obj.hashCode()); } /** * Add a parameter so that we can show its value when tracing * @param index within the procedure * @param value an object describing its value */ protected void putParameter(int index, Object value) { // Lazily instantiate parameters if necessary if (parameters == null) { parameters = new TreeMap(new Comparator() { public int compare(Object o1, Object o2) { int c = 0; if (o1 instanceof Integer && o2 instanceof Integer) { c = ((Integer) o1).compareTo(((Integer) o2)); } return c; } }); } Object key = new Integer(index); if (value == null) { parameters.put(key, "NULL"); } else if (value instanceof String) { parameters.put(key, "'" + value + "'"); } else if (value instanceof Number) { parameters.put(key, value); } else if (value instanceof Boolean) { parameters.put(key, ((Boolean) value).toString()); } else if (value instanceof Date) { parameters.put(key, "'" + getDateAsString((Date) value) + "'"); } else { String className = value.getClass().getName(); StringTokenizer st = new StringTokenizer(className, "."); while (st.hasMoreTokens()) { className = st.nextToken(); } parameters.put(key, className); } } /** * Trace the call that was just made * @param startTime so we can log how long it took * @param exception if anything went wrong during execution * @throws SQLException if the {@link ConnectionPool#onExecute onExecute} method threw one. */ protected void trace(long startTime, Exception exception) throws SQLException { if (isTrace()) { // Log if configured to if (connectionPool.getLog().isDebugEnabled() && connectionPool.getDefinition().isTrace()) { connectionPool.getLog().debug(sqlLog.toString() + " (" + (System.currentTimeMillis() - startTime) + " milliseconds" + (exception != null ? ", threw a " + exception.getClass().getName() + ": " + exception.getMessage() + ")" : ")")); } // Send to any listener connectionPool.onExecute(sqlLog.toString(), (System.currentTimeMillis() - startTime), exception); } // Clear parameters for next time if (parameters != null) { parameters.clear(); } sqlStatement = null; sqlLog.setLength(0); } protected void startExecute() { if (isTrace()) { ((ProxyConnection) proxyConnection).addSqlCall(sqlLog.toString()); } } /** * Get the parameters that have been built up and use them to fill in any parameters * withing the sqlStatement and produce a log. If the log already exists (for instance, * if a batch is being peformed) then it is appended to the end. */ protected void appendToSqlLog() { if (sqlStatement != null && sqlStatement.length() > 0 && isTrace()) { int parameterIndex = 0; StringTokenizer st = new StringTokenizer(sqlStatement, "?"); while (st.hasMoreTokens()) { if (parameterIndex > 0) { if (parameters != null) { final Object value = parameters.get(new Integer(parameterIndex)); if (value != null) { sqlLog.append(value); } else { sqlLog.append("?"); } } else { sqlLog.append("?"); } } parameterIndex++; sqlLog.append(st.nextToken()); } if (sqlStatement.endsWith("?")) { if (parameterIndex > 0) { if (parameters != null) { final Object value = parameters.get(new Integer(parameterIndex)); if (value != null) { sqlLog.append(value); } else { sqlLog.append("?"); } } else { sqlLog.append("?"); } } } if (sqlStatement != null && !sqlStatement.trim().endsWith(";")) { sqlLog.append("; "); } } if (parameters != null) { parameters.clear(); } } protected boolean isTrace() { return getConnectionPool().isConnectionListenedTo() || (getConnectionPool().getDefinition().isTrace()); } /** * Sets sqlStatement if it isn't already set * @param sqlStatement the statement we are sending the database */ protected void setSqlStatementIfNull(String sqlStatement) { if (this.sqlStatement == null) { this.sqlStatement = sqlStatement; } } protected static String getDateAsString(Date date) { return DATE_FORMAT.format(date); } } /* Revision history: $Log: AbstractProxyStatement.java,v $ Revision 1.23 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.22 2006/03/03 09:58:26 billhorsman Fix for statement.getConnection(). See bug 1149834. Revision 1.21 2006/01/18 14:40:00 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.20 2005/10/07 08:25:15 billhorsman Support new sqlCalls list and isTrace() is now true if the connection pool is being listened to or if trace is on. It no longer depends on the log level. This is because the sqlCalls are available in AdminServlet and not just the logs. Revision 1.19 2005/09/26 10:01:31 billhorsman Added lastSqlCall when trace is on. Revision 1.18 2004/06/02 20:04:54 billhorsman Fixed sql log: boolean and date now supported, and last parameter is included Revision 1.17 2003/11/04 13:54:02 billhorsman checkstyle Revision 1.16 2003/10/27 12:21:59 billhorsman Optimisation to avoid preparing sql log if tracing is off. Revision 1.15 2003/10/27 11:18:42 billhorsman Fix for sqlStatement being null. Revision 1.14 2003/10/19 09:50:08 billhorsman Debug exception displays class name. Revision 1.13 2003/10/18 20:44:48 billhorsman Better SQL logging (embed parameter values within SQL call) and works properly with batched statements now. Revision 1.12 2003/09/30 18:39:07 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.11 2003/09/05 16:26:50 billhorsman testException() now returns true if a fatal exception was detected. Revision 1.10 2003/03/10 23:43:09 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.9 2003/03/10 15:26:42 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.8 2003/03/05 18:42:32 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools Revision 1.7 2003/03/03 11:11:56 billhorsman fixed licence Revision 1.6 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.5 2003/02/19 22:38:32 billhorsman fatal sql exception causes house keeper to run immediately Revision 1.4 2003/02/13 17:06:42 billhorsman allow for sqlStatement in execute() method Revision 1.3 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.2 2003/01/28 11:47:08 billhorsman new isTrace() and made close() public Revision 1.1 2003/01/27 18:26:35 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/CompositeConfigurationListener.java0000644000175000017500000000575610730503125033562 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.util.AbstractListenerContainer; /** * A {@link ConfigurationListenerIF} that keeps a list of ConfigurationListenerIFs * and notifies them in a thread safe manner. * It also implements {@link org.logicalcobwebs.proxool.util.ListenerContainerIF ListenerContainerIF} * which provides methods for * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#addListener(Object) adding} and * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#removeListener(Object) removing} listeners. * * @version $Revision: 1.7 $, $Date: 2006/01/18 14:40:01 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class CompositeConfigurationListener extends AbstractListenerContainer implements ConfigurationListenerIF { static final Log LOG = LogFactory.getLog(CompositeConfigurationListener.class); /** * @see ConfigurationListenerIF#definitionUpdated(ConnectionPoolDefinitionIF, Properties, Properties) */ public void definitionUpdated( ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo) { Object[] listeners = getListeners(); for(int i=0; iConnectionListenerIFs * and notifies them in a thread safe manner. * It also implements {@link org.logicalcobwebs.proxool.util.ListenerContainerIF ListenerContainerIF} * which provides methods for * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#addListener(Object) adding} and * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#removeListener(Object) removing} listeners. * * @version $Revision: 1.8 $, $Date: 2007/01/25 23:38:24 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class CompositeConnectionListener extends AbstractListenerContainer implements ConnectionListenerIF { static final Log LOG = LogFactory.getLog(CompositeConnectionListener.class); /** * @see ConnectionListenerIF#onBirth(Connection) */ public void onBirth(Connection connection) throws SQLException { Object[] listeners = getListeners(); for(int i=0; iProxoolListenerIFs * and notifies them in a thread safe manner. * It also implements {@link org.logicalcobwebs.proxool.util.ListenerContainerIF ListenerContainerIF} * which provides methods for * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#addListener(Object) adding} and * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#removeListener(Object) removing} listeners. * * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:01 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class CompositeProxoolListener extends AbstractListenerContainer implements ProxoolListenerIF { static final Log LOG = LogFactory.getLog(CompositeProxoolListener.class); /** * @see ProxoolListenerIF#onRegistration(ConnectionPoolDefinitionIF, Properties) */ public void onRegistration( ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo) { Object[] listeners = getListeners(); for(int i=0; iStateListenerIFs * and notifies them in a thread safe manner. * It also implements {@link org.logicalcobwebs.proxool.util.ListenerContainerIF ListenerContainerIF} * which provides methods for * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#addListener(Object) adding} and * {@link org.logicalcobwebs.proxool.util.ListenerContainerIF#removeListener(Object) removing} listeners. * * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:01 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class CompositeStateListener extends AbstractListenerContainer implements StateListenerIF { static final Log LOG = LogFactory.getLog(CompositeStateListener.class); /** * @see StateListenerIF#upStateChanged(int) */ public void upStateChanged(int upState) { Object[] listeners = getListeners(); for(int i=0; i * String alias = "myPool"; * ConfigurationListenerIF myConfigurationListener = new MyConfigurationListener(); * ProxoolFacade.{@link ProxoolFacade#addConfigurationListener addConfigurationListener}(alias, myConfigurationListener); *
    * * @version $Revision: 1.5 $, $Date: 2003/03/03 11:11:56 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public interface ConfigurationListenerIF { /** * Gets called once after a pool has been updated. * @param connectionPoolDefinition the new definition * @param completeInfo the properties that could be used to create this definition * @param changedInfo only the properties that have changed since the pool was * registered, or this method was las called. */ void definitionUpdated(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo); } /* Revision history: $Log: ConfigurationListenerIF.java,v $ Revision 1.5 2003/03/03 11:11:56 billhorsman fixed licence Revision 1.4 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.3 2003/02/08 00:35:30 billhorsman doc Revision 1.2 2003/01/23 11:41:56 billhorsman doc Revision 1.1 2003/01/18 15:12:23 billhorsman renamed ConfiguratorIF to ConfigurationListenerIF to better reflect role Revision 1.3 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.2 2002/12/12 10:49:43 billhorsman now includes properties in definitionChanged event Revision 1.1 2002/12/04 13:19:43 billhorsman draft ConfigurationListenerIF stuff for persistent configuration */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionBuilderIF.java0000644000175000017500000000137510730503125031200 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.SQLException; /** * @author Bertrand Renuart * */ public interface ConnectionBuilderIF { Connection buildConnection(ConnectionPoolDefinitionIF cp) throws SQLException; } /* Revision history: $Log: ConnectionBuilderIF.java,v $ Revision 1.1 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionInfo.java0000644000175000017500000001075310730503125030266 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.logicalcobwebs.proxool.util.FastArrayList; import java.util.Date; import java.util.List; /** * Implementation of ConnectionInfoIF. Unlike ConnectionPool it is * frozen and will not change. Used with a {@link org.logicalcobwebs.proxool.admin.SnapshotIF snapshot} * * @version $Revision: 1.8 $, $Date: 2005/10/07 08:18:23 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ class ConnectionInfo implements ConnectionInfoIF { private Date birthDate; private long age; private long id; private int mark; private int status; private long timeLastStartActive; private long timeLastStopActive; private String requester; private String delegateDriver; private String delegateUrl; private String proxyHashcode; private String delegateHashcode; private List sqlCalls = new FastArrayList(); public Date getBirthDate() { return birthDate; } public long getBirthTime() { return birthDate.getTime(); } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public long getAge() { return age; } public void setAge(long age) { this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } public int getMark() { return mark; } public void setMark(int mark) { this.mark = mark; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public long getTimeLastStartActive() { return timeLastStartActive; } public void setTimeLastStartActive(long timeLastStartActive) { this.timeLastStartActive = timeLastStartActive; } public long getTimeLastStopActive() { return timeLastStopActive; } public void setTimeLastStopActive(long timeLastStopActive) { this.timeLastStopActive = timeLastStopActive; } public String getRequester() { return requester; } public void setRequester(String requester) { this.requester = requester; } public String getDelegateDriver() { return delegateDriver; } public void setDelegateDriver(String delegateDriver) { this.delegateDriver = delegateDriver; } public String getDelegateUrl() { return delegateUrl; } public void setDelegateUrl(String delegateUrl) { this.delegateUrl = delegateUrl; } public String getProxyHashcode() { return proxyHashcode; } public void setProxyHashcode(String proxyHashcode) { this.proxyHashcode = proxyHashcode; } public String getDelegateHashcode() { return delegateHashcode; } public void setDelegateHashcode(String delegateHashcode) { this.delegateHashcode = delegateHashcode; } /** * Compares using {@link #getId()} * @param o must be another {@link ConnectionInfoIF} implementation * @return the comparison * @see Comparable#compareTo(Object) */ public int compareTo(Object o) { return new Long(((ConnectionInfoIF) o).getId()).compareTo(new Long(getId())); } public String[] getSqlCalls() { return (String[]) sqlCalls.toArray(new String[0]); } public void addSqlCall(String sqlCall) { this.sqlCalls.add(sqlCall); } } /* Revision history: $Log: ConnectionInfo.java,v $ Revision 1.8 2005/10/07 08:18:23 billhorsman New sqlCalls gives list of SQL calls rather than just he most recent (for when a connection makes more than one call before being returned to the pool) Revision 1.7 2005/09/26 10:01:31 billhorsman Added lastSqlCall when trace is on. Revision 1.6 2003/10/30 00:05:50 billhorsman now implements Comparable (using ID) Revision 1.5 2003/03/03 11:11:56 billhorsman fixed licence Revision 1.4 2003/02/19 23:46:09 billhorsman renamed monitor package to admin Revision 1.3 2003/02/12 12:28:27 billhorsman added url, proxyHashcode and delegateHashcode to ConnectionInfoIF Revision 1.2 2003/01/31 16:53:15 billhorsman checkstyle Revision 1.1 2003/01/31 11:47:14 billhorsman new snapshot of connection info */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionInfoIF.java0000644000175000017500000001267110730503125030506 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Date; /** * Provides information about an individual connection. You can get a collection * of these from {@link ProxoolFacade#getConnectionInfos ProxoolFacade}. You * get back information about all the connections in a particular pool. * *
     * String alias = "myPool";
     * Iterator i = ProxoolFacade.getConnectionInfos(alias).iterator();
     * while (i.hasNext()) {
     *  ConnectionInfoIF c = (ConnectionInfoIF)i.next();
     *   ...
     * }
     * 
    * * @version $Revision: 1.12 $, $Date: 2005/10/07 08:18:23 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface ConnectionInfoIF extends Comparable { /** * Default - treat as normal * @see #getMark */ static final int MARK_FOR_USE = 0; /** * The next time this connection is made available we should expire it. * @see #getMark */ static final int MARK_FOR_EXPIRY = 1; /** * This is the start and end state of every connection * @see #getStatus */ static final int STATUS_NULL = 0; /** * The connection is available for use * @see #getStatus */ static final int STATUS_AVAILABLE = 1; /** * The connection is in use * @see #getStatus */ static final int STATUS_ACTIVE = 2; /** * The connection is in use by the house keeping thread * @see #getStatus */ static final int STATUS_OFFLINE = 3; /** * The time that this connection was created. * The number of milliseconds * since midnight, January 1, 1970 UTC. */ long getBirthTime(); /** * Like {@link #getBirthTime} but in Date format * @return birthDate */ Date getBirthDate(); /** * The age in millseconds since this connection was built */ long getAge(); /** * A unique ID for this connection */ long getId(); /** * Sometimes we want do something to a connection but can't because it is still * active and we don't want to disrupt its use. So we mark it instead and when it * stops being active we can perform the necessary operation. * * The only thing we do at the moment is {@link #MARK_FOR_EXPIRY expire} the * connection (if it is too old for instance). And this will happen if the * housekeeper decides it should but the connection is still active. */ int getMark(); /** * The status of the connection. Can be either: * {@link #STATUS_NULL null}, * {@link #STATUS_AVAILABLE available}, * {@link #STATUS_ACTIVE active} or * {@link #STATUS_OFFLINE offline}. */ int getStatus(); /** * When this connection was last given out. The number of milliseconds * since midnight, January 1, 1970 UTC. */ long getTimeLastStartActive(); /** * When this connection was last given back (or zero if it is still active). * The number of milliseconds * since midnight, January 1, 1970 UTC. */ long getTimeLastStopActive(); /** * The name of the thread that asked for this connection. */ String getRequester(); /** * The hashcode (in hex) of the ProxyConnection object. This * uniquely identifies this proxy connection. * @return proxyHashcode */ String getProxyHashcode(); /** * The hashcode (in hex) of the delegate connection object. This * uniquely identifies the underlying connection. * @return delegateHashcode */ String getDelegateHashcode(); /** * The URL that this connection is using (the definition * might have changed since this connection was built). * @return delegateUrl */ String getDelegateUrl(); /** * A log of the last SQL used on this connection. Only populated * if {@link org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF#isTrace()} * is enabled. * @return the most recent SQL to be used */ String[] getSqlCalls(); } /* Revision history: $Log: ConnectionInfoIF.java,v $ Revision 1.12 2005/10/07 08:18:23 billhorsman New sqlCalls gives list of SQL calls rather than just he most recent (for when a connection makes more than one call before being returned to the pool) Revision 1.11 2005/09/26 10:01:31 billhorsman Added lastSqlCall when trace is on. Revision 1.10 2003/10/30 00:05:50 billhorsman now implements Comparable (using ID) Revision 1.9 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.8 2003/02/12 12:28:27 billhorsman added url, proxyHashcode and delegateHashcode to ConnectionInfoIF Revision 1.7 2003/01/31 11:38:57 billhorsman birthDate now stored as Date not long Revision 1.6 2003/01/27 18:26:35 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.5 2003/01/15 00:12:13 billhorsman doc Revision 1.4 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.3 2002/10/25 16:00:19 billhorsman added better class javadoc Revision 1.2 2002/09/18 13:48:56 billhorsman checkstyle and doc Revision 1.1.1.1 2002/09/13 08:12:32 billhorsman new Revision 1.3 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionListenerIF.java0000644000175000017500000001433210730503125031374 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.SQLException; /** * You can listen to the lifecycle of a connection. Sometimes, you may * want to perform a task when the connection is born or dies. Actually, * the reason why we originally did this is now obsolete. But the code * remains here just in case. You need to * {@link ProxoolFacade#setConnectionListener register} * your implementation with ProxoolFacade. * *
     * String alias = "myPool";
     * ConnectionListenerIF myConnectionListener = new MyConnectionListener();
     * ProxoolFacade.{@link org.logicalcobwebs.proxool.ProxoolFacade#addConnectionListener addConnectionListener}(alias, myConnectionListener);
     * 
    * * @version $Revision: 1.9 $, $Date: 2007/01/25 23:38:24 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface ConnectionListenerIF { /** * We are killing a connection because the * {@link org.logicalcobwebs.proxool.ProxoolConstants#MAXIMUM_ACTIVE_TIME MAXIMUM_ACTIVE_TIME} * has been exceeded. * @see #onDeath(java.sql.Connection, int) */ static final int MAXIMUM_ACTIVE_TIME_EXPIRED = 1; /** * We are killing a connection because it's manually been expired (by something external to * Proxool) * @see #onDeath(java.sql.Connection, int) */ static final int MANUAL_EXPIRY = 2; /** * We are killing a connection because it has not been * {@link org.logicalcobwebs.proxool.ConnectionValidatorIF#validate(ConnectionPoolDefinitionIF, java.sql.Connection) validated}. * @see #onDeath(java.sql.Connection, int) */ static final int VALIDATION_FAIL = 3; /** * We are killing a connection because Proxool is shutting down * @see #onDeath(java.sql.Connection, int) */ static final int SHUTDOWN = 4; /** * We are killing a connection because it couldn't be {@link org.logicalcobwebs.proxool.ConnectionResetter#reset(java.sql.Connection, String) reset} * after it was returned to the pool and we don't want to give it out again in an unknown state. * @see #onDeath(java.sql.Connection, int) */ static final int RESET_FAIL = 5; /** * We are killing a connection because the routine house keeper test failed * @see #onDeath(java.sql.Connection, int) */ static final int HOUSE_KEEPER_TEST_FAIL = 6; /** * We are killing a connection because it's {@link org.logicalcobwebs.proxool.ProxoolConstants#MAXIMUM_CONNECTION_LIFETIME MAXIMUM_CONNECTION_LIFETIME} * has been exceeded. * @see #onDeath(java.sql.Connection, int) */ static final int MAXIMUM_CONNECTION_LIFETIME_EXCEEDED = 7; /** * We are killing a connection because a {@link org.logicalcobwebs.proxool.ProxoolConstants#FATAL_SQL_EXCEPTION FATAL_SQL_EXCEPTION} * has been detected. * @see #onDeath(java.sql.Connection, int) */ static final int FATAL_SQL_EXCEPTION_DETECTED = 8; /** * Happens everytime we create a new connection. You can use this * to allocate resources to a connection that might be useful during * the lifetime of the connection. * * @param connection the connection that has just been created * @throws SQLException if anything goes wrong (which will then be logged but ignored) */ void onBirth(Connection connection) throws SQLException; /** * Happens just before we expire a connection. You can use this to * reclaim resources from a connection. * * @param connection the connection that is about to expire * @param reasonCode {@link #MAXIMUM_ACTIVE_TIME_EXPIRED}, * {@link #HOUSE_KEEPER_TEST_FAIL}, * {@link #FATAL_SQL_EXCEPTION_DETECTED}, * {@link #MANUAL_EXPIRY}, * {@link #MAXIMUM_CONNECTION_LIFETIME_EXCEEDED}, * {@link #RESET_FAIL}, * {@link #SHUTDOWN}, or * {@link #VALIDATION_FAIL} * @throws SQLException if anything goes wrong (which will then be logged but ignored) */ void onDeath(Connection connection, int reasonCode) throws SQLException; /** * Happens after every successful execute. Note that the command * is not fully implemented at this stage. At some point it might represent * the SQL that is sent to the database (or the procedure call that was used). * * @param command what command was being executed * @param elapsedTime how long the call took (in milliseconds) */ void onExecute(String command, long elapsedTime); /** * Happens everytime an exception was thrown during an execute method * Note that the command * is not fully implemented at this stage. At some point it might represent * the SQL that is sent to the database (or the procedure call that was used). * * @param command what command was being executed * @param exception what exception was thrown */ void onFail(String command, Exception exception); } /* Revision history: $Log: ConnectionListenerIF.java,v $ Revision 1.9 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.8 2007/01/25 00:10:24 billhorsman New onAboutToDie event for ConnectionListenerIF that gets called if the maximum-active-time is exceeded. Revision 1.7 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.6 2003/02/08 00:35:30 billhorsman doc Revision 1.5 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.4 2002/10/25 16:00:20 billhorsman added better class javadoc Revision 1.3 2002/10/23 21:04:36 billhorsman checkstyle fixes (reduced max line width and lenient naming convention Revision 1.2 2002/10/16 11:45:52 billhorsman removed obsolete cleanupClob method and added more javadoc Revision 1.1.1.1 2002/09/13 08:12:34 billhorsman new Revision 1.5 2002/08/24 19:43:04 billhorsman new execute events Revision 1.4 2002/06/28 11:15:41 billhorsman didn't really need ListenerIF */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionPool.java0000644000175000017500000015440010730503125030302 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.concurrent.ReaderPreferenceReadWriteLock; import org.logicalcobwebs.concurrent.WriterPreferenceReadWriteLock; import org.logicalcobwebs.proxool.admin.Admin; import org.logicalcobwebs.proxool.util.FastArrayList; import java.sql.Connection; import java.sql.SQLException; import java.util.*; /** * This is where most things happen. (In fact, probably too many things happen in this one * class). * @version $Revision: 1.86 $, $Date: 2007/01/25 23:38:24 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ class ConnectionPool implements ConnectionPoolStatisticsIF { /** * Use this for messages that aren't useful for the pool specific log */ private static final Log LOG = LogFactory.getLog(ConnectionPool.class); /** * Here we deviate from the standard of using the classname for the log * name. Here we want to use the alias for the pool so that we can log * each pool to different places. So we have to instantiate the log later. */ private Log log; private ReaderPreferenceReadWriteLock connectionStatusReadWriteLock = new ReaderPreferenceReadWriteLock(); /** * If you want to shutdown the pool you should get a write lock on this. And if you use the pool then * get a read lock. This stops us trying to shutdown the pool whilst it is in use. Only, we don't want * to delay shutdown just because some greedy user has got a connection active. Shutdown should be * relatively immediate. So we don't ask for a read lock for the whole time that a connection is active. */ private WriterPreferenceReadWriteLock primaryReadWriteLock = new WriterPreferenceReadWriteLock(); private static final String[] STATUS_DESCRIPTIONS = {"NULL", "AVAILABLE", "ACTIVE", "OFFLINE"}; private static final String MSG_MAX_CONNECTION_COUNT = "Couldn't get connection because we are at maximum connection count and there are none available"; /** This is the pool itself */ private List proxyConnections; /** This is the "round robin" that makes sure we use all the connections */ private int nextAvailableConnection = 0; private long connectionsServedCount = 0; private long connectionsRefusedCount = 0; /** This keeps a count of how many connections there are in each state */ private int[] connectionCountByState = new int[4]; private ConnectionPoolDefinition definition; private CompositeConnectionListener compositeConnectionListener = new CompositeConnectionListener(); private CompositeStateListener compositeStateListener = new CompositeStateListener(); private long timeOfLastRefusal = 0; private int upState; private static boolean loggedLegend; private Admin admin; private boolean locked = false; private Date dateStarted = new Date(); private boolean connectionPoolUp = false; /** * This gets set during {@link #shutdown}. We use it to notify shutdown * that all connections are now non-active. */ private Thread shutdownThread; private Prototyper prototyper; /** * Initialised in {@link ConnectionPool#ConnectionPool constructor}. */ private ConnectionResetter connectionResetter; private ConnectionValidatorIF connectionValidator; protected ConnectionPool(ConnectionPoolDefinition definition) throws ProxoolException { // Use the FastArrayList for performance and thread safe // behaviour. We set its behaviour to "fast" (meaning reads are // unsynchronized, whilst writes are not). FastArrayList fal = new FastArrayList(); fal.setFast(true); proxyConnections = fal; log = LogFactory.getLog("org.logicalcobwebs.proxool." + definition.getAlias()); connectionResetter = new ConnectionResetter(log, definition.getDriver()); setDefinition(definition); connectionValidator = new DefaultConnectionValidator(); if (definition.getStatistics() != null) { try { admin = new Admin(definition); } catch (ProxoolException e) { log.error("Failed to initialise statistics", e); } } ShutdownHook.init(); } /** Starts up house keeping and prototyper threads. */ protected void start() throws ProxoolException { connectionPoolUp = true; prototyper = new Prototyper(this); HouseKeeperController.register(this); } /** * Get a connection from the pool. If none are available or there was an Exception * then an exception is thrown and something written to the log */ protected Connection getConnection() throws SQLException { String requester = Thread.currentThread().getName(); /* *If we're busy, we need to return as quickly as possible. Because this is unsynchronized * we run the risk of refusing a connection when we might actually be able to. But that will * only happen when we're right at or near maximum connections anyway. */ try { prototyper.quickRefuse(); } catch (SQLException e) { connectionsRefusedCount++; if (admin != null) { admin.connectionRefused(); } log.info(displayStatistics() + " - " + MSG_MAX_CONNECTION_COUNT); timeOfLastRefusal = System.currentTimeMillis(); setUpState(StateListenerIF.STATE_OVERLOADED); throw e; } prototyper.checkSimultaneousBuildThrottle(); ProxyConnection proxyConnection = null; try { // We need to look at all the connections, but we don't want to keep looping round forever for (int connectionsTried = 0; connectionsTried < proxyConnections.size(); connectionsTried++) { // By doing this in a try/catch we avoid needing to synch on the size(). We need to do be // able to cope with connections being removed whilst we are going round this loop try { proxyConnection = (ProxyConnection) proxyConnections.get(nextAvailableConnection); } catch (ArrayIndexOutOfBoundsException e) { // This is thrown by a Vector (which we no longer use), but is // kept here for a while. nextAvailableConnection = 0; proxyConnection = (ProxyConnection) proxyConnections.get(nextAvailableConnection); } catch (IndexOutOfBoundsException e) { // This is thrown by a true List nextAvailableConnection = 0; proxyConnection = (ProxyConnection) proxyConnections.get(nextAvailableConnection); } // setActive() returns false if the ProxyConnection wasn't available. You // can't set it active twice (at least, not without making it available again // in between) if (proxyConnection != null && proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_ACTIVE)) { // Okay. So we have it. But is it working ok? if (getDefinition().isTestBeforeUse()) { if (!testConnection(proxyConnection)) { // Oops. No it's not. Let's choose another. proxyConnection = null; } } if (proxyConnection != null) { nextAvailableConnection++; break; } } else { proxyConnection = null; } nextAvailableConnection++; } // Did we get one? if (proxyConnection == null) { try { // No! Let's see if we can create one proxyConnection = prototyper.buildConnection(ProxyConnection.STATUS_ACTIVE, "on demand"); // Okay. So we have it. But is it working ok? if (getDefinition().isTestBeforeUse()) { if (!testConnection(proxyConnection)) { // Oops. No it's not. There's not much more we can do for now throw new SQLException("Created a new connection but it failed its test"); } } } catch (SQLException e) { throw e; } catch (ProxoolException e) { log.debug("Couldn't get connection", e); throw new SQLException(e.toString()); } catch (Throwable e) { log.error("Couldn't get connection", e); throw new SQLException(e.toString()); } } } catch (SQLException e) { throw e; } catch (Throwable t) { log.error("Problem getting connection", t); throw new SQLException(t.toString()); } finally { if (proxyConnection != null) { connectionsServedCount++; proxyConnection.setRequester(requester); } else { connectionsRefusedCount++; if (admin != null) { admin.connectionRefused(); } timeOfLastRefusal = System.currentTimeMillis(); setUpState(StateListenerIF.STATE_OVERLOADED); } } if (proxyConnection == null) { throw new SQLException("Unknown reason for not getting connection. Sorry."); } if (log.isDebugEnabled() && getDefinition().isVerbose()) { log.debug(displayStatistics() + " - Connection #" + proxyConnection.getId() + " served"); } // This gives the proxy connection a chance to reset itself before it is served. proxyConnection.open(); return ProxyFactory.getWrappedConnection(proxyConnection); } /** * Test the connection (if required) * If the connection fails the test, it is removed from the pool. * If no ConnectionValidatorIF is defined, then the test always succeed. * * @param proxyConnection the connection to test * @return TRUE if the connection pass the test, FALSE if it fails */ private boolean testConnection(ProxyConnectionIF proxyConnection) { // is validation enabled ? if( connectionValidator == null ) { return true; } // validate the connection boolean success = connectionValidator.validate(getDefinition(), proxyConnection.getConnection()); if( success ) { if (LOG.isDebugEnabled()) { LOG.debug(displayStatistics() + " - Connection #" + proxyConnection.getId() + " tested: OK"); } } else { proxyConnection.setStatus(ProxyConnectionIF.STATUS_NULL); removeProxyConnection(proxyConnection, ConnectionListenerIF.VALIDATION_FAIL, "it didn't pass the validation", ConnectionPool.REQUEST_EXPIRY, true); } // return return success; } /** * Add a ProxyConnection to the pool * @param proxyConnection new connection * @return true if the connection was added or false if it wasn't (for instance, if the definition it * was built with is out of date). */ protected boolean addProxyConnection(ProxyConnectionIF proxyConnection) { boolean added = false; try { acquireConnectionStatusWriteLock(); if (proxyConnection.getDefinition() == getDefinition()) { proxyConnections.add(proxyConnection); connectionCountByState[proxyConnection.getStatus()]++; added = true; } } finally { releaseConnectionStatusWriteLock(); } return added; } protected static String getStatusDescription(int status) { try { return STATUS_DESCRIPTIONS[status]; } catch (ArrayIndexOutOfBoundsException e) { return "Unknown status: " + status; } } /** * When you have finished with a Connection you should put it back here. That will make it available to others. * Unless it's due for expiry, in which case it will... expire */ protected void putConnection(ProxyConnectionIF proxyConnection) { if (admin != null) { long now = System.currentTimeMillis(); long start = proxyConnection.getTimeLastStartActive(); if (now - start < 0) { log.warn("Future start time detected. #" + proxyConnection.getId() + " start = " + new Date(start) + " (" + (now - start) + " milliseconds)"); } else if (now - start > 1000000) { log.warn("Suspiciously long active time. #" + proxyConnection.getId() + " start = " + new Date(start)); } admin.connectionReturned(now - start); } // It's possible that this connection is due for expiry if (proxyConnection.isMarkedForExpiry()) { if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_ACTIVE, ProxyConnectionIF.STATUS_NULL)) { expireProxyConnection(proxyConnection, proxyConnection.getReasonCode(), proxyConnection.getReasonForMark(), REQUEST_EXPIRY); } } else { // Optionally, test it to see if it is ok if (getDefinition().isTestAfterUse()) { // It will get removed by this call if it is no good testConnection(proxyConnection); } // Let's make it available for someone else if (!proxyConnection.setStatus(ProxyConnectionIF.STATUS_ACTIVE, ProxyConnectionIF.STATUS_AVAILABLE)) { if (proxyConnection.getStatus() == ProxyConnectionIF.STATUS_AVAILABLE) { // This is *probably* because the connection has been closed twice. // Although we can't tell for sure. We'll have to refactor this to use // throw away wrappers to avoid this problem. log.warn("Unable to close connection " + proxyConnection.getId() + " - I suspect that it has been closed already. Closing it more" + " than once is unwise and should be avoided."); } else { log.warn("Unable to set status of connection " + proxyConnection.getId() + " from " + getStatusDescription(ProxyConnectionIF.STATUS_ACTIVE) + " to " + getStatusDescription(ProxyConnectionIF.STATUS_AVAILABLE) + " because it's state was " + getStatusDescription(proxyConnection.getStatus())); } } } if (log.isDebugEnabled() && getDefinition().isVerbose()) { log.debug(displayStatistics() + " - Connection #" + proxyConnection.getId() + " returned (now " + getStatusDescription(proxyConnection.getStatus()) + ")"); } } /** This means that there's something wrong the connection and it's probably best if no one uses it again. */ protected void throwConnection(ProxyConnectionIF proxyConnection, int reasonCode, String reason) { expireConnectionAsSoonAsPossible(proxyConnection, reasonCode, reason, true); } /** Get a ProxyConnection by index */ private ProxyConnectionIF getProxyConnection(int i) { return (ProxyConnectionIF) proxyConnections.get(i); } /** * Return an array of all the connections * @return array of connections */ protected ProxyConnectionIF[] getProxyConnections() { return (ProxyConnectionIF[]) proxyConnections.toArray(new ProxyConnectionIF[proxyConnections.size()]); } /** * Remove a ProxyConnection by calling its {@link ConnectionListenerIF#onDeath onDeath} event, * closing it (for real) and then removing it from the list. * @param proxyConnection the connection to remove * @param reason for log audit * @param forceExpiry true means close now, whether it is active or not; false means if it is active then * merely mark it for expiry so that it is removed as soon as it finished being active * @param triggerSweep if true then this removal will trigger a prototype sweep */ protected void removeProxyConnection(ProxyConnectionIF proxyConnection, int reasonCode, String reason, boolean forceExpiry, boolean triggerSweep) { // Just check that it is null if (forceExpiry || proxyConnection.isNull()) { proxyConnection.setStatus(ProxyConnectionIF.STATUS_NULL); /* Run some code everytime we destroy a connection */ try { onDeath(proxyConnection.getConnection(), reasonCode); } catch (SQLException e) { log.error("Problem during onDeath (ignored)", e); } // The reallyClose() method also decrements the connectionCount. try { proxyConnection.reallyClose(); } catch (SQLException e) { log.error(e); } try { // If we're shutting down then getting a write lock will cause a deadlock if (isConnectionPoolUp()) { acquireConnectionStatusWriteLock(); } proxyConnections.remove(proxyConnection); } finally { if (isConnectionPoolUp()) { releaseConnectionStatusWriteLock(); } } if (log.isDebugEnabled()) { log.debug(displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId()) + " removed because " + reason + "."); } if (triggerSweep) { PrototyperController.triggerSweep(getDefinition().getAlias()); } } else { log.error(displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId()) + " was not removed because isNull() was false."); } } protected void expireProxyConnection(ProxyConnectionIF proxyConnection, int reasonCode, String reason, boolean forceExpiry) { removeProxyConnection(proxyConnection, reasonCode, reason, forceExpiry, true); } /** * Call this to shutdown gracefully. * @param delay how long to wait for connections to become free before forcing them to close anyway */ protected void shutdown(int delay, String finalizerName) throws Throwable { final String alias = getDefinition().getAlias(); try { /* This will stop us giving out any more connections and may cause some of the threads to die. */ acquirePrimaryWriteLock(); if (connectionPoolUp) { connectionPoolUp = false; long startFinalize = System.currentTimeMillis(); shutdownThread = Thread.currentThread(); if (delay > 0) { log.info("Shutting down '" + alias + "' pool started at " + dateStarted + " - waiting for " + delay + " milliseconds for everything to stop. [ " + finalizerName + "]"); } else { log.info("Shutting down '" + alias + "' pool immediately [" + finalizerName + "]"); } /* Interrupt the threads (in case they're sleeping) */ boolean connectionClosedManually = false; try { try { HouseKeeperController.cancel(alias); } catch (ProxoolException e) { log.error("Shutdown couldn't cancel house keeper", e); } // Cancel the admin thread (for statistics) if (admin != null) { admin.cancelAll(); } /* Patience, patience. */ if (connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE] != 0) { long endWait = startFinalize + delay; LOG.info("Waiting until " + new Date(endWait) + " for all connections to become inactive (active count is " + connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE] + ")."); while (true) { long timeout = endWait - System.currentTimeMillis(); if (timeout > 0) { synchronized (Thread.currentThread()) { try { Thread.currentThread().wait(timeout); } catch (InterruptedException e) { log.debug("Interrupted whilst sleeping."); } } } int activeCount = connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE]; if (activeCount == 0) { break; } if (System.currentTimeMillis() < endWait) { LOG.info("Still waiting for active count to reach zero (currently " + activeCount + ")."); } else { // There are still connections active. Oh well, we're not _that_ patient LOG.warn("Shutdown waited for " + (System.currentTimeMillis() - startFinalize) + " milliseconds for all " + "the connections to become inactive but the active count is still " + activeCount + ". Shutting down anyway."); break; } Thread.sleep(100); } } prototyper.cancel(); // Silently close all connections for (int i = proxyConnections.size() - 1; i >= 0; i--) { long id = getProxyConnection(i).getId(); try { connectionClosedManually = true; removeProxyConnection(getProxyConnection(i), ConnectionListenerIF.SHUTDOWN, "of shutdown", true, false); if (log.isDebugEnabled()) { log.debug("Connection #" + id + " closed"); } } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("Problem closing connection #" + id, t); } } } } catch (Throwable t) { log.error("Unknown problem finalizing pool", t); } finally { ConnectionPoolManager.getInstance().removeConnectionPool(alias); if (log.isDebugEnabled()) { log.info("'" + alias + "' pool has been closed down by " + finalizerName + " in " + (System.currentTimeMillis() - startFinalize) + " milliseconds."); if (!connectionClosedManually) { log.debug("No connections required manual removal."); } } super.finalize(); } } else { if (log.isDebugEnabled()) { log.debug("Ignoring duplicate attempt to shutdown '" + alias + "' pool by " + finalizerName); } } } catch (Throwable t) { log.error(finalizerName + " couldn't shutdown pool", t); } finally { releasePrimaryWriteLock(); } } /** * You should {@link #acquireConnectionStatusReadLock acquire} * a read lock if you want this to be accurate (but that might have * an impact on the performance of your pool). * @see ConnectionPoolStatisticsIF#getAvailableConnectionCount */ public int getAvailableConnectionCount() { return connectionCountByState[ConnectionInfoIF.STATUS_AVAILABLE]; } /** * You should {@link #acquireConnectionStatusReadLock acquire} * a read lock if you want this to be accurate (but that might have * an impact on the performance of your pool). * @see ConnectionPoolStatisticsIF#getActiveConnectionCount */ public int getActiveConnectionCount() { return connectionCountByState[ConnectionInfoIF.STATUS_ACTIVE]; } /** * You should {@link #acquireConnectionStatusReadLock acquire} * a read lock if you want this to be accurate (but that might have * an impact on the performance of your pool). * @see ConnectionPoolStatisticsIF#getOfflineConnectionCount */ public int getOfflineConnectionCount() { return connectionCountByState[ConnectionInfoIF.STATUS_OFFLINE]; } protected String displayStatistics() { if (!loggedLegend) { log.info("Proxool statistics legend: \"s - r (a/t/o)\" > s=served, r=refused (only shown if non-zero), a=active, t=total, o=offline (being tested)"); loggedLegend = true; } StringBuffer statistics = new StringBuffer(); statistics.append(FormatHelper.formatBigNumber(getConnectionsServedCount())); if (getConnectionsRefusedCount() > 0) { statistics.append(" -"); statistics.append(FormatHelper.formatBigNumber(getConnectionsRefusedCount())); } statistics.append(" ("); statistics.append(FormatHelper.formatSmallNumber(getActiveConnectionCount())); statistics.append("/"); statistics.append(FormatHelper.formatSmallNumber(getAvailableConnectionCount() + getActiveConnectionCount())); statistics.append("/"); statistics.append(FormatHelper.formatSmallNumber(getOfflineConnectionCount())); statistics.append(")"); // Don't need this triple check any more. /* if (getDefinition().getDebugLevel() == ConnectionPoolDefinitionIF.DEBUG_LEVEL_LOUD) { statistics.append(", cc="); statistics.append(connectionCount); statistics.append(", ccc="); statistics.append(connectedConnectionCount); } */ return statistics.toString(); } protected void expireAllConnections(int reasonCode, String reason, boolean merciful) { // Do this in two stages because expiring a connection will trigger // the prototyper to make more. And that might mean we end up // killing a newly made connection; Set pcs = new HashSet(); for (int i = proxyConnections.size() - 1; i >= 0; i--) { pcs.add(proxyConnections.get(i)); } Iterator i = pcs.iterator(); while (i.hasNext()) { ProxyConnectionIF pc = (ProxyConnectionIF) i.next(); expireConnectionAsSoonAsPossible(pc, reasonCode, reason, merciful); } } protected void expireConnectionAsSoonAsPossible(ProxyConnectionIF proxyConnection, int reasonCode, String reason, boolean merciful) { if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE)) { if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL)) { // It is. Expire it now . expireProxyConnection(proxyConnection, reasonCode, reason, REQUEST_EXPIRY); } } else { // Oh no, it's in use. if (merciful) { //Never mind, we'll mark it for expiry // next time it is available. This will happen in the // putConnection() method. proxyConnection.markForExpiry(reason); if (log.isDebugEnabled()) { log.debug(displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId()) + " marked for expiry."); } } else { // So? Kill, kill, kill // We have to make sure it's null first. expireProxyConnection(proxyConnection, reasonCode, reason, FORCE_EXPIRY); } } // END if (proxyConnection.setOffline()) } protected void registerRemovedConnection(int status) { prototyper.connectionRemoved(); connectionCountByState[status]--; } /** * You should {@link #acquireConnectionStatusWriteLock acquire} a write lock * before calling this method * @param oldStatus so we know which count to decrement * @param newStatus so we know which count to increment */ protected void changeStatus(int oldStatus, int newStatus) { // LOG.debug("About to change status"); connectionCountByState[oldStatus]--; connectionCountByState[newStatus]++; // LOG.debug("Changing status from " + oldStatus + " to " + newStatus); // Check to see if shutdown is waiting for all connections to become // non-active if (shutdownThread != null && connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE] == 0) { synchronized (shutdownThread) { shutdownThread.notify(); } } } public long getConnectionsServedCount() { return connectionsServedCount; } public long getConnectionsRefusedCount() { return connectionsRefusedCount; } protected ConnectionPoolDefinition getDefinition() { return definition; } /** * Changes both the way that any new connections will be made, and the behaviour of the pool. Consider * calling expireAllConnections() if you're in a hurry. */ protected synchronized void setDefinition(ConnectionPoolDefinition definition) throws ProxoolException { this.definition = definition; try { Class.forName(definition.getDriver()); } catch (ClassNotFoundException e) { log.error("Couldn't load class " + definition.getDriver(), e); throw new ProxoolException("Couldn't load class " + definition.getDriver()); } catch (NullPointerException e) { log.error("Definition did not contain driver", e); throw new ProxoolException("Definition did not contain driver"); } } /** * @deprecated use {@link #addStateListener(StateListenerIF)} instead. */ public void setStateListener(StateListenerIF stateListener) { addStateListener(stateListener); } public void addStateListener(StateListenerIF stateListener) { this.compositeStateListener.addListener(stateListener); } public boolean removeStateListener(StateListenerIF stateListener) { return this.compositeStateListener.removeListener(stateListener); } /** * @deprecated use {@link #addConnectionListener(ConnectionListenerIF)} instead. */ public void setConnectionListener(ConnectionListenerIF connectionListener) { addConnectionListener(connectionListener); } public void addConnectionListener(ConnectionListenerIF connectionListener) { this.compositeConnectionListener.addListener(connectionListener); } public boolean removeConnectionListener(ConnectionListenerIF connectionListener) { return this.compositeConnectionListener.removeListener(connectionListener); } /** Call the onBirth() method on each StateListenerIF . */ protected void onBirth(Connection connection) throws SQLException { this.compositeConnectionListener.onBirth(connection); } /** Call the onDeath() method on each StateListenerIF . */ protected void onDeath(Connection connection, int reasonCode) throws SQLException { this.compositeConnectionListener.onDeath(connection, reasonCode); } /** Call the onExecute() method on each StateListenerIF . */ protected void onExecute(String command, long elapsedTime, Exception exception) throws SQLException { if (exception == null) { this.compositeConnectionListener.onExecute(command, elapsedTime); } else { this.compositeConnectionListener.onFail(command, exception); } } /** * Is there a {@link ConnectionListenerIF listener} for connections * @return true if there is a listener registered. */ protected boolean isConnectionListenedTo() { return !compositeConnectionListener.isEmpty(); } public String toString() { return getDefinition().toString(); } public int getUpState() { return upState; } public void setUpState(int upState) { if (this.upState != upState) { compositeStateListener.upStateChanged(upState); this.upState = upState; } } protected Collection getConnectionInfos() { Collection cis = null; cis = new TreeSet(); Iterator i = proxyConnections.iterator(); while (i.hasNext()) { ConnectionInfoIF connectionInfo = (ConnectionInfoIF) i.next(); ConnectionInfo ci = new ConnectionInfo(); ci.setAge(connectionInfo.getAge()); ci.setBirthDate(connectionInfo.getBirthDate()); ci.setId(connectionInfo.getId()); ci.setMark(connectionInfo.getMark()); ci.setRequester(connectionInfo.getRequester()); ci.setStatus(connectionInfo.getStatus()); ci.setTimeLastStartActive(connectionInfo.getTimeLastStartActive()); ci.setTimeLastStopActive(connectionInfo.getTimeLastStopActive()); ci.setDelegateUrl(connectionInfo.getDelegateUrl()); ci.setProxyHashcode(connectionInfo.getProxyHashcode()); ci.setDelegateHashcode(connectionInfo.getDelegateHashcode()); String[] sqlCalls = connectionInfo.getSqlCalls(); for (int j = 0; j < sqlCalls.length; j++) { ci.addSqlCall(sqlCalls[j]); } cis.add(ci); } return cis; } /** * Manually expire a connection. * @param id the id of the connection to kill * @param forceExpiry use true to expire even if it is in use * @return true if the connection was found and expired, else false */ public boolean expireConnection(long id, boolean forceExpiry) { boolean success = false; ProxyConnection proxyConnection = null; // We need to look at all the connections, but we don't want to keep looping round forever for (int connectionsTried = 0; connectionsTried < proxyConnections.size(); connectionsTried++) { // By doing this in a try/catch we avoid needing to synch on the size(). We need to do be // able to cope with connections being removed whilst we are going round this loop try { proxyConnection = (ProxyConnection) proxyConnections.get(nextAvailableConnection); } catch (IndexOutOfBoundsException e) { nextAvailableConnection = 0; proxyConnection = (ProxyConnection) proxyConnections.get(nextAvailableConnection); } if (proxyConnection.getId() == id) { // This is the one proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE); proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL); removeProxyConnection(proxyConnection, ConnectionListenerIF.MANUAL_EXPIRY, "it was manually killed", forceExpiry, true); success = true; break; } nextAvailableConnection++; } if (!success) { if (log.isDebugEnabled()) { log.debug(displayStatistics() + " - couldn't find " + FormatHelper.formatMediumNumber(proxyConnection.getId()) + " and I've just been asked to expire it"); } } return success; } public Log getLog() { return log; } /** * {@link ConnectionResetter#initialise Initialises} the ConnectionResetter. * @param connection sample Connection to use for default values */ protected void initialiseConnectionResetter(Connection connection) { connectionResetter.initialise(connection); } /** * {@link ConnectionResetter#reset Resets} a Connection to its * original state. * @param connection the one to reset * @param id the id of the connection * @throws SQLException if the call to {@link java.sql.Connection#isClosed()} fails * @return true if it was successfully reset, false if there was a problem (like the connection being already closed) */ protected boolean resetConnection(Connection connection, String id) throws SQLException { if (connection.isClosed()) { return false; } else { return connectionResetter.reset(connection, id); } } /** * @see ConnectionPoolStatisticsIF#getDateStarted */ public Date getDateStarted() { return dateStarted; } /** * Get the admin for this pool * @return admin */ protected Admin getAdmin() { return admin; } protected boolean isLocked() { return locked; } protected void lock() { locked = true; } protected void unlock() { locked = false; } /** * Call this if you want to do something important to the pool. Like shut it down. * @throws InterruptedException if we couldn't */ protected void acquirePrimaryReadLock() throws InterruptedException { // if (log.isDebugEnabled()) { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("About to acquire primary read lock", e); // } // // log.debug("About to acquire primary read lock"); // } primaryReadWriteLock.readLock().acquire(); // if (log.isDebugEnabled()) { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("Acquired primary read lock", e); // } // //log.debug("Acquired primary read lock"); // } } /** * @see #acquirePrimaryReadLock */ protected void releasePrimaryReadLock() { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("Released primary read lock", e); // } //log.debug("Released primary read lock"); primaryReadWriteLock.readLock().release(); } /** * Call this everytime you build a connection. It ensures that we're not * trying to shutdown the pool whilst we are building a connection. So you * should check that the pool is still {@link #isConnectionPoolUp up}. * @throws InterruptedException if there was a problem. */ protected void acquirePrimaryWriteLock() throws InterruptedException { // boolean success = false; // try { // if (log.isDebugEnabled()) { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("About to acquire primary write lock", e); // } // //log.debug("About to acquire primary write lock"); // } primaryReadWriteLock.writeLock().acquire(); // success = true; // if (log.isDebugEnabled()) { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("Acquired primary write lock", e); // } // //log.debug("Acquired primary write lock"); // } // } finally { // if (log.isDebugEnabled() && !success) { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("Failed to acquire primary write lock", e); // } // //log.debug("Failed to acquire primary write lock"); // } // } } /** * @see #acquirePrimaryReadLock */ protected void releasePrimaryWriteLock() { primaryReadWriteLock.writeLock().release(); // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // log.debug("Released primary write lock", e); // } //log.debug("Released primary write lock"); } /** * Is the pool up? * @return false is the connection pool has been {@link #shutdown shutdown} * (or is in the process of being shutdown). */ protected boolean isConnectionPoolUp() { return connectionPoolUp; } protected static final boolean FORCE_EXPIRY = true; protected static final boolean REQUEST_EXPIRY = false; /** * The time (in milliseconds) that we last refused a connection * @return timeOfLastRefusal */ protected long getTimeOfLastRefusal() { return timeOfLastRefusal; } protected void acquireConnectionStatusWriteLock() { try { // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // LOG.debug("About to acquire connectionStatus write lock", e); // } connectionStatusReadWriteLock.writeLock().acquire(); // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // LOG.debug("Acquired connectionStatus write lock", e); // } } catch (InterruptedException e) { log.error("Couldn't acquire connectionStatus write lock", e); } } protected void releaseConnectionStatusWriteLock() { connectionStatusReadWriteLock.writeLock().release(); // try { // throw new RuntimeException("TRACE ONLY"); // } catch (RuntimeException e) { // LOG.debug("Released connectionStatus write lock", e); // } } protected void acquireConnectionStatusReadLock() { try { connectionStatusReadWriteLock.readLock().acquire(); } catch (InterruptedException e) { log.error("Couldn't acquire connectionStatus read lock", e); } } protected boolean attemptConnectionStatusReadLock(long msecs) { try { return connectionStatusReadWriteLock.readLock().attempt(msecs); } catch (InterruptedException e) { log.error("Couldn't acquire connectionStatus read lock", e); return false; } } protected void releaseConnectionStatusReadLock() { connectionStatusReadWriteLock.readLock().release(); // LOG.debug("Released connectionStatus read lock"); } protected Prototyper getPrototyper() { return prototyper; } public long getConnectionCount() { return getPrototyper().getConnectionCount(); } } /* Revision history: $Log: ConnectionPool.java,v $ Revision 1.86 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.85 2007/01/25 00:10:24 billhorsman New onAboutToDie event for ConnectionListenerIF that gets called if the maximum-active-time is exceeded. Revision 1.84 2006/03/23 11:44:57 billhorsman More information when quickly refusing Revision 1.83 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.82 2005/10/07 08:19:05 billhorsman New sqlCalls gives list of SQL calls rather than just he most recent (for when a connection makes more than one call before being returned to the pool) Revision 1.81 2005/10/02 12:32:02 billhorsman Make connectionCount available to statistics Revision 1.80 2005/09/26 09:54:14 billhorsman Avoid suspected deadlock when getting a detailed snapshot. Only attempt to get the concurrent lock for 10 seconds before giving up. Revision 1.79 2005/05/04 16:26:31 billhorsman Only add a new connection if the definition matches Revision 1.78 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. Revision 1.76 2004/02/23 17:47:32 billhorsman Improved message that gets logged if the state change of a connection fails. Revision 1.75 2004/02/23 17:38:58 billhorsman Improved message that gets logged if you close a connection more than once. Revision 1.74 2004/02/12 13:02:17 billhorsman Catch correct exception when iterating through list. Revision 1.73 2003/12/09 18:54:55 billhorsman Make closure of statement during connection test more robust - credit to John Hume Revision 1.72 2003/11/04 13:52:01 billhorsman Fixed warning message Revision 1.71 2003/10/30 00:11:15 billhorsman Debug info and error logged if unsuccessful attempt to put connection back in pool. Plus connectioninfo comparator changed Revision 1.70 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.69 2003/09/30 07:50:04 billhorsman Smarter throwing of caught SQLExceptions without wrapping them up inside another (and losing the stack trace) Revision 1.68 2003/09/20 17:04:06 billhorsman Fix for incorrect OFFLINE count when house keeper removed a connection if the test SQL failed. This meant that the offline count went negative. The only consequence of that is that the logs look funny. Revision 1.67 2003/08/30 14:54:04 billhorsman Checkstyle Revision 1.66 2003/04/10 08:23:54 billhorsman removed very frequent debug Revision 1.65 2003/03/11 23:58:04 billhorsman fixed deadlock on connection expiry Revision 1.64 2003/03/11 14:51:49 billhorsman more concurrency fixes relating to snapshots Revision 1.63 2003/03/11 01:16:29 billhorsman removed misleasing debug Revision 1.62 2003/03/11 00:32:13 billhorsman fixed negative timeout Revision 1.61 2003/03/10 23:39:51 billhorsman shutdown is now notified when active count reaches zero Revision 1.60 2003/03/10 16:26:35 billhorsman removed debug traces Revision 1.59 2003/03/10 15:26:44 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.58 2003/03/05 18:42:32 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools Revision 1.57 2003/03/03 16:06:44 billhorsman name house keeper and prototyper threads now includes alias Revision 1.56 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.55 2003/02/28 18:08:55 billhorsman OVERLOAD state is now triggered immediately rather than waiting for house keeper Revision 1.54 2003/02/28 10:10:25 billhorsman on death now gets called for connections killed during shutdown Revision 1.53 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.52 2003/02/26 12:57:30 billhorsman added TO DO Revision 1.51 2003/02/19 23:46:10 billhorsman renamed monitor package to admin Revision 1.50 2003/02/19 23:07:46 billhorsman state changes are now only calculated every time the house keeper runs, but it's more accurate Revision 1.49 2003/02/19 22:38:33 billhorsman fatal sql exception causes house keeper to run immediately Revision 1.48 2003/02/18 16:49:59 chr32 Added possibility to remove connection and state listeners. Revision 1.47 2003/02/12 12:27:16 billhorsman log proxy hashcode too Revision 1.46 2003/02/07 17:26:04 billhorsman deprecated removeAllConnectionPools in favour of shutdown (and dropped unreliable finalize() method) Revision 1.45 2003/02/07 14:19:01 billhorsman fixed deprecated use of debugLevel property Revision 1.44 2003/02/07 14:16:46 billhorsman support for StatisticsListenerIF Revision 1.43 2003/02/07 10:27:47 billhorsman change in shutdown procedure to allow re-registration Revision 1.42 2003/02/07 01:48:15 chr32 Started using new composite listeners. Revision 1.41 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.40 2003/02/04 17:18:30 billhorsman move ShutdownHook init code Revision 1.39 2003/02/04 15:59:50 billhorsman finalize now shuts down StatsRoller timer Revision 1.38 2003/02/02 23:35:48 billhorsman removed ReloadMonitor to remove use of System properties Revision 1.37 2003/01/31 16:53:16 billhorsman checkstyle Revision 1.36 2003/01/31 11:49:28 billhorsman use Admin instead of Stats Revision 1.35 2003/01/31 00:20:05 billhorsman statistics is now a string to allow multiple, comma-delimited values (plus better logging of errors during destruction) Revision 1.34 2003/01/30 17:22:21 billhorsman add statistics support Revision 1.33 2003/01/27 18:26:35 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.32 2003/01/15 14:51:40 billhorsman checkstyle Revision 1.31 2003/01/15 12:01:37 billhorsman added getDateStarted() Revision 1.30 2003/01/15 00:07:43 billhorsman now uses FastArrayList instead of Vector for thread safe improvements Revision 1.29 2002/12/18 12:16:22 billhorsman double checking of connection state counts Revision 1.28 2002/12/17 17:15:39 billhorsman Better synchronization of status stuff Revision 1.27 2002/12/17 16:52:51 billhorsman synchronize part of removeProxyConnection to avoid possible bug where connection by status count drifts. Revision 1.26 2002/12/12 12:28:34 billhorsman just in case: changed == 0 to < 1 Revision 1.25 2002/12/12 10:48:47 billhorsman checkstyle Revision 1.24 2002/12/03 12:24:00 billhorsman fixed fatal sql exception Revision 1.23 2002/11/12 20:24:12 billhorsman checkstyle Revision 1.22 2002/11/12 20:18:23 billhorsman Made connection resetter a bit more friendly. Now, if it encounters any problems during reset then that connection is thrown away. This is going to cause you problems if you always close connections in an unstable state (e.g. with transactions open. But then again, it's better to know about that as soon as possible, right? Revision 1.21 2002/11/09 15:48:55 billhorsman new isConnectionListenedTo() to stop unnecessary processing if nobody is listening Revision 1.20 2002/11/08 18:03:50 billhorsman when connections are closed because they have been active for too long then a log message is written of level WARN, and it includes the name of the thread responsible (reminder, name your threads). Revision 1.19 2002/11/07 19:31:25 billhorsman added sanity check against suspected situation where you can make more connections than the maximumConnectionCount Revision 1.18 2002/11/07 19:17:55 billhorsman removed obsolete method Revision 1.17 2002/11/06 20:27:30 billhorsman supports the ConnectionResetter Revision 1.16 2002/11/05 21:24:18 billhorsman cosmetic: changed format of statistics dumped to log to make it less confusing for locales that use a space separator for thousands Revision 1.15 2002/11/02 13:57:33 billhorsman checkstyle Revision 1.14 2002/10/30 21:19:17 billhorsman make use of ProxyFactory Revision 1.13 2002/10/29 23:00:33 billhorsman fixed sign error in prototyper (that meant that protoyping never happened) Revision 1.12 2002/10/29 22:58:22 billhorsman added connection hashcode to debug Revision 1.11 2002/10/28 19:44:03 billhorsman small change to cleanup log Revision 1.10 2002/10/27 13:02:45 billhorsman change to prototyper logic to make it clearer (but no functional change) Revision 1.9 2002/10/27 12:07:45 billhorsman fix bug where prototyper kept making connections up to maximum. Log now gives reason why connection was prototyped. Fix bug where definition with no properties was not allowed (it is now). Revision 1.8 2002/10/25 10:12:52 billhorsman Improvements and fixes to the way connection pools close down. Including new ReloadMonitor to detect when a class is reloaded. Much better logging too. Revision 1.7 2002/10/24 17:25:20 billhorsman cleaned up logging and made it more informative Revision 1.6 2002/10/23 21:04:36 billhorsman checkstyle fixes (reduced max line width and lenient naming convention Revision 1.5 2002/10/16 11:46:23 billhorsman removed obsolete cleanupClob method and made onBirth call failsafe Revision 1.4 2002/09/19 10:33:57 billhorsman added ProxyConnection#toString Revision 1.3 2002/09/18 13:48:56 billhorsman checkstyle and doc Revision 1.2 2002/09/13 12:13:50 billhorsman added debug and fixed ClassCastException during housekeeping Revision 1.1.1.1 2002/09/13 08:12:55 billhorsman new Revision 1.13 2002/08/24 19:57:15 billhorsman checkstyle changes Revision 1.12 2002/08/24 19:44:13 billhorsman fixes for logging Revision 1.11 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.10 2002/07/04 09:05:36 billhorsmaNn Fixes Revision 1.9 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.8 2002/07/02 11:14:26 billhorsman added test (andbug fixes) for FileLogger Revision 1.7 2002/07/02 08:39:55 billhorsman getConnectionInfos now returns a Collection instead of an array. displayStatistics is now available to ProxoolFacade. Prototyper no longer tries to make connections when maximum is reached (stopping unnecessary log messages). bug fix. Revision 1.6 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionPoolDefinition.java0000644000175000017500000014113410730503124032312 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.*; import java.lang.reflect.Modifier; /** * This defines a connection pool: the URL to connect to the database, the * delegate driver to use, and how the pool behaves. * @version $Revision: 1.36 $, $Date: 2007/07/28 10:39:12 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ class ConnectionPoolDefinition implements ConnectionPoolDefinitionIF { // TODO Should we check for defintion reads whilst updating? private static final Log LOG = LogFactory.getLog(ConnectionPoolDefinition.class); /** * This log has a category based on the alias */ private Log poolLog = LOG;; private String alias; // JNDI properties private String jndiName; private String initialContextFactory; private String providerUrl; private String securityAuthentication; private String securityPrincipal; private String securityCredentials; private Properties delegateProperties = new Properties(); private Properties completeInfo = new Properties(); private Properties changedInfo = new Properties(); /** * Whether any of the properties that effect an individual * connection have changed. If they have, we need to kill * all the existing connections. */ private boolean connectionPropertiesChanged; private String url; private String completeUrl; private String driver; private long maximumConnectionLifetime;; private int prototypeCount; private int minimumConnectionCount; private int maximumConnectionCount; private long houseKeepingSleepTime; private int simultaneousBuildThrottle; private long recentlyStartedThreshold; private long overloadWithoutRefusalLifetime; private long maximumActiveTime; private boolean verbose; private boolean trace; private String statistics; private String statisticsLogLevel; private Set fatalSqlExceptions = new HashSet(); /** * A String of all the fatalSqlExceptions delimited by * {@link ConnectionPoolDefinitionIF#FATAL_SQL_EXCEPTIONS_DELIMITER} */ private String fatalSqlExceptionsAsString; private String fatalSqlExceptionWrapper = null; private String houseKeepingTestSql; private boolean testBeforeUse; private boolean testAfterUse; private boolean jmx; private String jmxAgentId; private Class injectableConnectionInterface; private Class injectableStatementInterface; private Class injectablePreparedStatementInterface; private Class injectableCallableStatementInterface; /** * So we can set the values one by one if we want */ public ConnectionPoolDefinition() { } /** * Construct a new definition * @param url the url that defines this pool * @param info additional properties (for Proxool and the delegate * driver) * @param explicitRegister set to true if we are registering a new pool explicitly, or false * if it's just because we are serving a url that we haven't come across before * @throws ProxoolException if anything goes wrong */ protected ConnectionPoolDefinition(String url, Properties info, boolean explicitRegister) throws ProxoolException { this.alias = ProxoolFacade.getAlias(url); poolLog = LogFactory.getLog("org.logicalcobwebs.proxool." + alias); reset(); doChange(url, info, false, !explicitRegister); } /** * Update the definition. All existing properties are retained * and only overwritten if included in the info parameter * @param url the url that defines this pool * @param info additional properties (for Proxool and the delegate * driver) * @throws ProxoolException if anything goes wrong */ protected void update(String url, Properties info) throws ProxoolException { changedInfo.clear(); connectionPropertiesChanged = false; poolLog.debug("Updating definition"); doChange(url, info, false, false); if (connectionPropertiesChanged) { poolLog.info("Mercifully killing all current connections because of definition changes"); ProxoolFacade.killAllConnections(alias, "of definition changes", true); } } /** * Redefine the definition. All existing properties are reset to their * default values * @param url the url that defines this pool * @param info additional properties (for Proxool and the delegate * driver) * @throws ProxoolException if anything goes wrong */ protected void redefine(String url, Properties info) throws ProxoolException { reset(); changedInfo.clear(); connectionPropertiesChanged = false; poolLog.debug("Redefining definition"); doChange(url, info, false, false); // Check for minimum information if (getUrl() == null || getDriver() == null) { throw new ProxoolException("The URL is not defined properly: " + getCompleteUrl()); } if (connectionPropertiesChanged) { LOG.info("Mercifully killing all current connections because of definition changes"); ProxoolFacade.killAllConnections(alias, "definition has changed", true); } } private boolean doChange(String url, Properties info, boolean pretend, boolean implicitRegister) throws ProxoolException { boolean changed = false; try { int endOfPrefix = url.indexOf(':'); int endOfDriver = url.indexOf(':', endOfPrefix + 1); if (endOfPrefix > -1 && endOfDriver > -1) { final String driver = url.substring(endOfPrefix + 1, endOfDriver); if (isChanged(getDriver(), driver)) { changed = true; if (!pretend) { logChange(true, ProxoolConstants.DELEGATE_DRIVER_PROPERTY, driver); setDriver(driver); } } final String delegateUrl = url.substring(endOfDriver + 1); if (isChanged(getUrl(), delegateUrl)) { changed = true; if (!pretend) { logChange(true, ProxoolConstants.DELEGATE_URL_PROPERTY, delegateUrl); setUrl(delegateUrl); } } } else { // Using alias. Nothing to do } } catch (IndexOutOfBoundsException e) { LOG.error("Invalid URL: '" + url + "'", e); throw new ProxoolException("Invalid URL: '" + url + "'"); } if (!pretend) { setCompleteUrl(url); } if (info != null) { Enumeration e = info.propertyNames(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); String value = info.getProperty(key); changed = changed | setAnyProperty(key, value, pretend); if (!pretend) { completeInfo.setProperty(key, value); } } } if (!pretend) { ProxoolFacade.definitionUpdated(getAlias(), this, completeInfo, changedInfo); } if ((getDriver() == null || getUrl() == null) && implicitRegister) { throw new ProxoolException("Attempt to refer to a unregistered pool by its alias '" + getAlias() + "'"); } return changed; } private void logChange(boolean proxoolProperty, String key, String value) { if (poolLog.isDebugEnabled()) { String displayValue = value; if (key.toLowerCase().indexOf("password") > -1) { displayValue = "********"; } poolLog.debug((proxoolProperty ? "Recognised proxool property: " : "Delegating property to driver: ") + key + "=" + displayValue); } } private boolean setAnyProperty(String key, String value, boolean pretend) throws ProxoolException { boolean proxoolProperty = true; boolean changed = false; // These groups of properties have been split off to make this method smaller changed = changed || setHouseKeeperProperty(key, value, pretend); changed = changed || setLoggingProperty(key, value, pretend); changed = changed || setInjectableProperty(key, value, pretend); changed = changed || setJndiProperty(key, value, pretend); if (key.equals(ProxoolConstants.USER_PROPERTY)) { proxoolProperty = false; if (isChanged(getUser(), value)) { changed = true; if (!pretend) { setUser(value); } } } else if (key.equals(ProxoolConstants.PASSWORD_PROPERTY)) { proxoolProperty = false; if (isChanged(getPassword(), value)) { changed = true; if (!pretend) { setPassword(value); } } } else if (key.equals(ProxoolConstants.DELEGATE_DRIVER_PROPERTY)) { if (isChanged(getDriver(), value)) { changed = true; if (!pretend) { setDriver(value); } } } else if (key.equals(ProxoolConstants.DELEGATE_URL_PROPERTY)) { if (isChanged(getUrl(), value)) { changed = true; if (!pretend) { setUrl(value); } } } else if (key.equals(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY)) { if (getMaximumConnectionCount() != getInt(key, value)) { changed = true; if (!pretend) { setMaximumConnectionCount(getInt(key, value)); } } } else if (key.equals(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME_PROPERTY)) { if (getMaximumConnectionLifetime() != getLong(key, value)) { changed = true; if (!pretend) { setMaximumConnectionLifetime(getLong(key, value)); } } } else if (key.equals(ProxoolConstants.MAXIMUM_NEW_CONNECTIONS_PROPERTY)) { poolLog.warn("Use of " + ProxoolConstants.MAXIMUM_NEW_CONNECTIONS_PROPERTY + " is deprecated. Use more descriptive " + ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY + " instead."); if (getSimultaneousBuildThrottle() != getInt(key, value)) { changed = true; if (!pretend) { setSimultaneousBuildThrottle(getInt(key, value)); } } } else if (key.equals(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY)) { if (getSimultaneousBuildThrottle() != getInt(key, value)) { changed = true; setSimultaneousBuildThrottle(getInt(key, value)); } } else if (key.equals(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY)) { if (getMinimumConnectionCount() != getInt(key, value)) { changed = true; if (!pretend) { setMinimumConnectionCount(getInt(key, value)); } } } else if (key.equals(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY)) { if (getPrototypeCount() != getInt(key, value)) { changed = true; if (!pretend) { setPrototypeCount(getInt(key, value)); } } } else if (key.equals(ProxoolConstants.RECENTLY_STARTED_THRESHOLD_PROPERTY)) { if (getRecentlyStartedThreshold() != getLong(key, value)) { changed = true; if (!pretend) { setRecentlyStartedThreshold(getLong(key, value)); } } } else if (key.equals(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY)) { if (getOverloadWithoutRefusalLifetime() != getLong(key, value)) { changed = true; if (!pretend) { setOverloadWithoutRefusalLifetime(getLong(key, value)); } } } else if (key.equals(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY)) { if (getMaximumActiveTime() != getLong(key, value)) { changed = true; if (!pretend) { setMaximumActiveTime(getLong(key, value)); } } } else if (key.equals(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY)) { if (isChanged(fatalSqlExceptionsAsString, value)) { changed = true; if (!pretend) { setFatalSqlExceptionsAsString(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY)) { if (isChanged(fatalSqlExceptionWrapper, value)) { changed = true; if (!pretend) { setFatalSqlExceptionWrapper(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.STATISTICS_PROPERTY)) { if (isChanged(getStatistics(), value)) { changed = true; if (!pretend) { setStatistics(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY)) { if (isChanged(getStatisticsLogLevel(), value)) { changed = true; if (!pretend) { setStatisticsLogLevel(value.length() > 0 ? value : null); } } } if (!key.startsWith(ProxoolConstants.PROPERTY_PREFIX)) { if (isChanged(getDelegateProperty(key), value)) { changed = true; if (!pretend) { setDelegateProperty(key, value); } } proxoolProperty = false; } if (changed && !pretend) { logChange(proxoolProperty, key, value); changedInfo.setProperty(key, value); } return changed; } /** * Subset of {@link #setAnyProperty} to avoid overly long method * @see #setAnyProperty */ private boolean setLoggingProperty(String key, String value, boolean pretend) { boolean changed = false; if (key.equals(ProxoolConstants.DEBUG_LEVEL_PROPERTY)) { if (value != null && value.equals("1")) { poolLog.warn("Use of " + ProxoolConstants.DEBUG_LEVEL_PROPERTY + "=1 is deprecated. Use " + ProxoolConstants.VERBOSE_PROPERTY + "=true instead."); if (!isVerbose()) { changed = true; if (!pretend) { setVerbose(true); } } } else { poolLog.warn("Use of " + ProxoolConstants.DEBUG_LEVEL_PROPERTY + "=0 is deprecated. Use " + ProxoolConstants.VERBOSE_PROPERTY + "=false instead."); if (isVerbose()) { changed = true; if (!pretend) { setVerbose(false); } } } } else if (key.equals(ProxoolConstants.VERBOSE_PROPERTY)) { final boolean valueAsBoolean = Boolean.valueOf(value).booleanValue(); if (isVerbose() != valueAsBoolean) { changed = true; if (!pretend) { setVerbose(valueAsBoolean); } } } else if (key.equals(ProxoolConstants.TRACE_PROPERTY)) { final boolean valueAsBoolean = Boolean.valueOf(value).booleanValue(); if (isTrace() != valueAsBoolean) { changed = true; if (!pretend) { setTrace(valueAsBoolean); } } } return changed; } /** * Subset of {@link #setAnyProperty} to avoid overly long method * @see #setAnyProperty */ private boolean setInjectableProperty(String key, String value, boolean pretend) { boolean changed = false; if (key.equals(ProxoolConstants.INJECTABLE_CONNECTION_INTERFACE_NAME_PROPERTY)) { if (isChanged(getInjectableConnectionInterfaceName(), value)) { changed = true; if (!pretend) { setInjectableConnectionInterfaceName(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.INJECTABLE_STATEMENT_INTERFACE_NAME_PROPERTY)) { if (isChanged(getInjectableStatementInterfaceName(), value)) { changed = true; if (!pretend) { setInjectableStatementInterfaceName(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME_PROPERTY)) { if (isChanged(getInjectablePreparedStatementInterfaceName(), value)) { changed = true; if (!pretend) { setInjectablePreparedStatementInterfaceName(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME_PROPERTY)) { if (isChanged(getInjectableCallableStatememtInterfaceName(), value)) { changed = true; if (!pretend) { setInjectableCallableStatementInterfaceName(value.length() > 0 ? value : null); } } } return changed; } /** * Subset of {@link #setAnyProperty} to avoid overly long method. * @see #setAnyProperty */ private boolean setHouseKeeperProperty(String key, String value, boolean pretend) throws ProxoolException { boolean changed = false; if (key.equals(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY)) { if (getHouseKeepingSleepTime() != getLong(key, value)) { changed = true; if (!pretend) { setHouseKeepingSleepTime(getLong(key, value)); } } } else if (key.equals(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY)) { if (isChanged(getHouseKeepingTestSql(), value)) { changed = true; if (!pretend) { setHouseKeepingTestSql(value.length() > 0 ? value : null); } } } else if (key.equals(ProxoolConstants.TEST_BEFORE_USE_PROPERTY)) { final boolean valueAsBoolean = Boolean.valueOf(value).booleanValue(); if (isTestBeforeUse() != valueAsBoolean) { changed = true; if (!pretend) { setTestBeforeUse(valueAsBoolean); } } } else if (key.equals(ProxoolConstants.TEST_AFTER_USE_PROPERTY)) { final boolean valueAsBoolean = Boolean.valueOf(value).booleanValue(); if (isTestAfterUse() != valueAsBoolean) { changed = true; if (!pretend) { setTestAfterUse(valueAsBoolean); } } } return changed; } /** * Subset of {@link #setAnyProperty} to avoid overly long method * @see #setAnyProperty */ private boolean setJndiProperty(String key, String value, boolean pretend) { boolean changed = false; if (key.equals(ProxoolConstants.JNDI_NAME_PROPERTY)) { if (isChanged(getJndiName(), value)) { changed = true; if (!pretend) { setJndiName(value.length() > 0 ? value : null); } } } else { } return changed; } private int getInt(String key, String value) throws ProxoolException { try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new ProxoolException("'" + key + "' property must be an integer. Found '" + value + "' instead."); } } private long getLong(String key, String value) throws ProxoolException { try { return Long.parseLong(value); } catch (NumberFormatException e) { throw new ProxoolException("'" + key + "' property must be a long. Found '" + value + "' instead."); } } private static boolean isChanged(String oldValue, String newValue) { boolean changed = false; if (oldValue == null) { if (newValue != null) { changed = true; } } else if (newValue == null) { changed = true; } else if (!oldValue.equals(newValue)) { changed = true; } return changed; } /** * Deep clone of definition * @return the new definition * @throws CloneNotSupportedException */ protected Object clone() throws CloneNotSupportedException { ConnectionPoolDefinition clone = new ConnectionPoolDefinition(); clone.setCompleteUrl(completeUrl); clone.setDelegateProperties((Properties) delegateProperties.clone()); clone.setCompleteInfo((Properties) completeInfo.clone()); clone.clearChangedInfo(); clone.setAlias(alias); clone.setUrl(url); clone.setDriver(driver); clone.setMaximumConnectionLifetime(maximumConnectionLifetime); clone.setPrototypeCount(prototypeCount); clone.setMinimumConnectionCount(minimumConnectionCount); clone.setMaximumConnectionCount(maximumConnectionCount); clone.setHouseKeepingSleepTime(houseKeepingSleepTime); clone.setHouseKeepingTestSql(houseKeepingTestSql); clone.setTestAfterUse(testAfterUse); clone.setTestBeforeUse(testBeforeUse); clone.setSimultaneousBuildThrottle(simultaneousBuildThrottle); clone.setRecentlyStartedThreshold(recentlyStartedThreshold); clone.setOverloadWithoutRefusalLifetime(overloadWithoutRefusalLifetime); clone.setMaximumActiveTime(maximumActiveTime); clone.setVerbose(verbose); clone.setTrace(trace); clone.setStatistics(statistics); clone.setStatisticsLogLevel(statisticsLogLevel); clone.setFatalSqlExceptionsAsString(fatalSqlExceptionsAsString); try { clone.setFatalSqlExceptionWrapper(fatalSqlExceptionWrapper); } catch (ProxoolException e) { throw new IllegalArgumentException("Problem cloning fatalSqlExceptionWrapper: " + fatalSqlExceptionWrapper); } return clone; } private void clearChangedInfo() { changedInfo.clear(); } /** * Reset all properties to their default values */ private void reset() { completeUrl = null; delegateProperties.clear(); completeInfo.clear(); changedInfo.clear(); url = null; driver = null; maximumConnectionLifetime = DEFAULT_MAXIMUM_CONNECTION_LIFETIME; prototypeCount = DEFAULT_PROTOTYPE_COUNT; minimumConnectionCount = DEFAULT_MINIMUM_CONNECTION_COUNT; maximumConnectionCount = DEFAULT_MAXIMUM_CONNECTION_COUNT; houseKeepingSleepTime = DEFAULT_HOUSE_KEEPING_SLEEP_TIME; houseKeepingTestSql = null; testAfterUse = false; testBeforeUse = false; simultaneousBuildThrottle = DEFAULT_SIMULTANEOUS_BUILD_THROTTLE; recentlyStartedThreshold = DEFAULT_RECENTLY_STARTED_THRESHOLD; overloadWithoutRefusalLifetime = DEFAULT_OVERLOAD_WITHOUT_REFUSAL_THRESHOLD; maximumActiveTime = DEFAULT_MAXIMUM_ACTIVE_TIME; verbose = false; trace = false; statistics = null; statisticsLogLevel = null; fatalSqlExceptions.clear(); fatalSqlExceptionWrapper = null; } /** * Get all the properties used to define this pool * @return */ protected Properties getCompleteInfo() { return completeInfo; } /** * Overwrite the complete info * @param completeInfo the new properties * @see #getCompleteInfo() */ public void setCompleteInfo(Properties completeInfo) { this.completeInfo = completeInfo; } /** * @see ConnectionPoolDefinitionIF#getUser */ public String getUser() { return getDelegateProperty(USER_PROPERTY); } /** * @see ConnectionPoolDefinitionIF#getUser */ public void setUser(String user) { setDelegateProperty(USER_PROPERTY, user); } /** * @see ConnectionPoolDefinitionIF#getPassword */ public String getPassword() { return getDelegateProperty(PASSWORD_PROPERTY); } /** * @see ConnectionPoolDefinitionIF#getPassword */ public void setPassword(String password) { setDelegateProperty(PASSWORD_PROPERTY, password); } /** * @see ConnectionPoolDefinitionIF#getJdbcDriverVersion */ public String getJdbcDriverVersion() { try { Driver driver = DriverManager.getDriver(getUrl()); return driver.getMajorVersion() + "." + driver.getMinorVersion(); } catch (SQLException e) { return "Trying to locate driver version for '" + getUrl() + "' caused: " + e.toString(); } catch (NullPointerException e) { return "Couldn't locate driver for '" + getUrl() + "'!"; } } /** * @see Object#toString */ public String toString() { return getCompleteUrl(); } /** * @see ConnectionPoolDefinitionIF#getName * @deprecated use {@link #getAlias} */ public String getName() { return alias; } /** * @see ConnectionPoolDefinitionIF#getAlias */ public String getAlias() { return alias; } /** * @see ConnectionPoolDefinitionIF#getAlias */ public void setAlias(String alias) { this.alias = alias; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionLifetime */ public long getMaximumConnectionLifetime() { return maximumConnectionLifetime; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionLifetime */ public void setMaximumConnectionLifetime(long maximumConnectionLifetime) { this.maximumConnectionLifetime = maximumConnectionLifetime; } /** * @see ConnectionPoolDefinitionIF#getPrototypeCount */ public int getPrototypeCount() { return prototypeCount; } /** * @see ConnectionPoolDefinitionIF#getPrototypeCount */ public void setPrototypeCount(int prototypeCount) { this.prototypeCount = prototypeCount; } /** * @see ConnectionPoolDefinitionIF#getMinimumConnectionCount */ public int getMinimumConnectionCount() { return minimumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getMinimumConnectionCount */ public void setMinimumConnectionCount(int minimumConnectionCount) { this.minimumConnectionCount = minimumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionCount */ public int getMaximumConnectionCount() { return maximumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionCount */ public void setMaximumConnectionCount(int maximumConnectionCount) { this.maximumConnectionCount = maximumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime */ public long getHouseKeepingSleepTime() { return houseKeepingSleepTime; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime */ public void setHouseKeepingSleepTime(long houseKeepingSleepTime) { this.houseKeepingSleepTime = houseKeepingSleepTime; } /** * @see ConnectionPoolDefinitionIF#getMaximumNewConnections * @deprecated use more descriptive {@link #getSimultaneousBuildThrottle} instead */ public int getMaximumNewConnections() { return simultaneousBuildThrottle; } /** * @see ConnectionPoolDefinitionIF#getMaximumNewConnections * @deprecated use more descriptive {@link #setSimultaneousBuildThrottle} instead */ public void setMaximumNewConnections(int maximumNewConnections) { this.simultaneousBuildThrottle = maximumNewConnections; } /** * @see ConnectionPoolDefinitionIF#getSimultaneousBuildThrottle */ public int getSimultaneousBuildThrottle() { return simultaneousBuildThrottle; } /** * @see ConnectionPoolDefinitionIF#getSimultaneousBuildThrottle */ public void setSimultaneousBuildThrottle(int simultaneousBuildThrottle) { this.simultaneousBuildThrottle = simultaneousBuildThrottle; } /** * @see ConnectionPoolDefinitionIF#getProperties * @deprecated use less ambiguous {@link #getDelegateProperties} instead */ public Properties getProperties() { return delegateProperties; } /** * @see ConnectionPoolDefinitionIF#getDelegateProperties */ public Properties getDelegateProperties() { return delegateProperties; } /** * Get a property * @param name the name of the property * @return the value of the property */ public String getDelegateProperty(String name) { return getDelegateProperties().getProperty(name); } /** * Set a property * @param name the name of the property * @param value the value of the property * @see ConnectionPoolDefinitionIF#getProperties */ public void setDelegateProperty(String name, String value) { connectionPropertiesChanged = true; getDelegateProperties().setProperty(name, value); } /** * Overwrite the delegate properties * @param delegateProperties the new properties * @see ConnectionPoolDefinitionIF#getProperties */ public void setDelegateProperties(Properties delegateProperties) { this.delegateProperties = delegateProperties; } /** * @see ConnectionPoolDefinitionIF#getUrl */ public String getUrl() { return url; } /** * @see ConnectionPoolDefinitionIF#getUrl */ public void setUrl(String url) { this.url = url; connectionPropertiesChanged = true; } /** * @see ConnectionPoolDefinitionIF#getDriver */ public String getDriver() { return driver; } /** * @see ConnectionPoolDefinitionIF#getDriver */ public void setDriver(String driver) { this.driver = driver; connectionPropertiesChanged = true; } /** * @see ConnectionPoolDefinitionIF#getRecentlyStartedThreshold */ public long getRecentlyStartedThreshold() { return recentlyStartedThreshold; } /** * @see ConnectionPoolDefinitionIF#getRecentlyStartedThreshold */ public void setRecentlyStartedThreshold(long recentlyStartedThreshold) { this.recentlyStartedThreshold = recentlyStartedThreshold; } /** * @see ConnectionPoolDefinitionIF#getOverloadWithoutRefusalLifetime */ public long getOverloadWithoutRefusalLifetime() { return overloadWithoutRefusalLifetime; } /** * @see ConnectionPoolDefinitionIF#getOverloadWithoutRefusalLifetime */ public void setOverloadWithoutRefusalLifetime(long overloadWithoutRefusalLifetime) { this.overloadWithoutRefusalLifetime = overloadWithoutRefusalLifetime; } /** * @see ConnectionPoolDefinitionIF#getMaximumActiveTime */ public long getMaximumActiveTime() { return maximumActiveTime; } /** * @see ConnectionPoolDefinitionIF#getMaximumActiveTime */ public void setMaximumActiveTime(long maximumActiveTime) { this.maximumActiveTime = maximumActiveTime; } /** * @see ConnectionPoolDefinitionIF#getDebugLevel * @deprecated use {@link #isVerbose} instead */ public int getDebugLevel() { return (verbose ? 1 : 0); } /** * @see ConnectionPoolDefinitionIF#isVerbose */ public boolean isVerbose() { return verbose; } /** * @see ConnectionPoolDefinitionIF#isVerbose */ public void setVerbose(boolean verbose) { this.verbose = verbose; } /** * @see ConnectionPoolDefinitionIF#isTrace */ public boolean isTrace() { return trace; } /** * @see ConnectionPoolDefinitionIF#isTrace */ public void setTrace(boolean trace) { this.trace = trace; } /** * @see ConnectionPoolDefinitionIF#getCompleteUrl */ public String getCompleteUrl() { return completeUrl; } /** * @see ConnectionPoolDefinitionIF#getCompleteUrl */ public void setCompleteUrl(String completeUrl) { this.completeUrl = completeUrl; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptions */ public void setFatalSqlExceptionsAsString(String fatalSqlExceptionsAsString) { this.fatalSqlExceptionsAsString = fatalSqlExceptionsAsString; fatalSqlExceptions.clear(); if (fatalSqlExceptionsAsString != null) { StringTokenizer st = new StringTokenizer(fatalSqlExceptionsAsString, FATAL_SQL_EXCEPTIONS_DELIMITER); while (st.hasMoreTokens()) { fatalSqlExceptions.add(st.nextToken().trim()); } } } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptions */ public Set getFatalSqlExceptions() { return fatalSqlExceptions; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptionWrapper */ public String getFatalSqlExceptionWrapper() { return fatalSqlExceptionWrapper; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptionWrapper */ public void setFatalSqlExceptionWrapper(String fatalSqlExceptionWrapper) throws ProxoolException { // Test it out. That's the best way. try { FatalSqlExceptionHelper.throwFatalSQLException(fatalSqlExceptionWrapper, new SQLException("Test")); } catch (SQLException e) { // That's OK, we were expecting one of these } catch (RuntimeException e) { // That's OK, we were expecting one of these } this.fatalSqlExceptionWrapper = fatalSqlExceptionWrapper; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingTestSql */ public String getHouseKeepingTestSql() { return houseKeepingTestSql; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingTestSql */ public void setHouseKeepingTestSql(String houseKeepingTestSql) { this.houseKeepingTestSql = houseKeepingTestSql; } /** * @see ConnectionPoolDefinitionIF#isTestBeforeUse */ public boolean isTestBeforeUse() { return testBeforeUse; } /** * @see ConnectionPoolDefinitionIF#isTestBeforeUse */ public void setTestBeforeUse(boolean testBeforeUse) { this.testBeforeUse = testBeforeUse; } /** * @see ConnectionPoolDefinitionIF#isTestAfterUse */ public boolean isTestAfterUse() { return testAfterUse; } /** * @see ConnectionPoolDefinitionIF#isTestAfterUse */ public void setTestAfterUse(boolean testAfterUse) { this.testAfterUse = testAfterUse; } /** * @see ConnectionPoolDefinitionIF#getStatistics */ public String getStatistics() { return statistics; } /** * @see ConnectionPoolDefinitionIF#getStatistics */ public void setStatistics(String statistics) { this.statistics = statistics; } /** * @see ConnectionPoolDefinitionIF#getStatisticsLogLevel */ public String getStatisticsLogLevel() { return statisticsLogLevel; } /** * @see ConnectionPoolDefinitionIF#getStatisticsLogLevel */ public void setStatisticsLogLevel(String statisticsLogLevel) { this.statisticsLogLevel = statisticsLogLevel; } // Start JNDI public String getJndiName() { return jndiName; } public void setJndiName(String jndiName) { this.jndiName = jndiName; } public String getInitialContextFactory() { return initialContextFactory; } public void setInitialContextFactory(String initialContextFactory) { this.initialContextFactory = initialContextFactory; } public String getProviderUrl() { return providerUrl; } public void setProviderUrl(String providerUrl) { this.providerUrl = providerUrl; } public String getSecurityAuthentication() { return securityAuthentication; } public void setSecurityAuthentication(String securityAuthentication) { this.securityAuthentication = securityAuthentication; } public String getSecurityPrincipal() { return securityPrincipal; } public void setSecurityPrincipal(String securityPrincipal) { this.securityPrincipal = securityPrincipal; } public String getSecurityCredentials() { return securityCredentials; } public void setSecurityCredentials(String securityCredentials) { this.securityCredentials = securityCredentials; } // End JNDI /** * @see ConnectionPoolDefinitionIF#isJmx() */ public boolean isJmx() { return jmx; } /** * @see ConnectionPoolDefinitionIF#isJmx() */ public void setJmx(boolean jmx) { this.jmx = jmx; } /** * @see ConnectionPoolDefinitionIF#getJmxAgentId() */ public String getJmxAgentId() { return jmxAgentId; } /** * @see ConnectionPoolDefinitionIF#getJmxAgentId() */ public void setJmxAgentId(String jmxAgentId) { this.jmxAgentId = jmxAgentId; } /** * @see ConnectionPoolDefinitionIF#getInjectableConnectionInterface() */ public Class getInjectableConnectionInterface() { return injectableConnectionInterface; } /** * @see ConnectionPoolDefinitionIF#getInjectableConnectionInterface() */ public String getInjectableConnectionInterfaceName() { if (getInjectableConnectionInterface() != null) { return getInjectableConnectionInterface().getName(); } else { return null; } } /** * @param injectableConnectionInterfaceName the fully qualified class name * @see ConnectionPoolDefinitionIF#getInjectableConnectionInterface() */ public void setInjectableConnectionInterfaceName(String injectableConnectionInterfaceName) { this.injectableConnectionInterface = getInterface(injectableConnectionInterfaceName); } /** * @see ConnectionPoolDefinitionIF#getInjectableStatementInterface() */ public Class getInjectableStatementInterface() { return injectableStatementInterface; } /** * @see ConnectionPoolDefinitionIF#getInjectableStatementInterface() */ public String getInjectableStatementInterfaceName() { if (getInjectableStatementInterface() != null) { return getInjectableStatementInterface().getName(); } else { return null; } } /** * @param injectableStatementInterfaceName the fully qualified class name * @see ConnectionPoolDefinitionIF#getInjectableStatementInterface() */ public void setInjectableStatementInterfaceName(String injectableStatementInterfaceName) { this.injectableStatementInterface = getInterface(injectableStatementInterfaceName); } /** * @see ConnectionPoolDefinitionIF#getInjectablePreparedStatementInterface() */ public Class getInjectablePreparedStatementInterface() { return injectablePreparedStatementInterface; } /** * @see ConnectionPoolDefinitionIF#getInjectablePreparedStatementInterface() */ public String getInjectablePreparedStatementInterfaceName() { if (getInjectablePreparedStatementInterface() != null) { return getInjectablePreparedStatementInterface().getName(); } else { return null; } } /** * @param injectablePreparedStatementInterfaceName the fully qualified class name * @see ConnectionPoolDefinitionIF#getInjectablePreparedStatementInterface() */ public void setInjectablePreparedStatementInterfaceName(String injectablePreparedStatementInterfaceName) { this.injectablePreparedStatementInterface = getInterface(injectablePreparedStatementInterfaceName); } /** * @see ConnectionPoolDefinitionIF#getInjectableCallableStatementInterface() */ public String getInjectableCallableStatememtInterfaceName() { if (getInjectableCallableStatementInterface() != null) { return getInjectableCallableStatementInterface().getName(); } else { return null; } } /** * @see ConnectionPoolDefinitionIF#getInjectableCallableStatementInterface() */ public Class getInjectableCallableStatementInterface() { return injectableCallableStatementInterface; } /** * @param injectableCallableStatementInterfaceName the fully qualified class name * @see ConnectionPoolDefinitionIF#getInjectableCallableStatementInterface() */ public void setInjectableCallableStatementInterfaceName(String injectableCallableStatementInterfaceName) { this.injectableCallableStatementInterface = getInterface(injectableCallableStatementInterfaceName); } private Class getInterface(String className) { try { Class clazz = null; if (className != null && className.length() > 0) { clazz = Class.forName(className); if (!clazz.isInterface()) { throw new IllegalArgumentException(className + " is a class. It must be an interface."); } if (!Modifier.isPublic(clazz.getModifiers())) { throw new IllegalArgumentException(className + " is a protected interface. It must be public."); } } return clazz; } catch (ClassNotFoundException e) { throw new IllegalArgumentException(className + " couldn't be found"); } } /** * Returns true if {@link #redefine redefining} the pool using * these parameters would not change the definition. You can * use this to decide whether or not to trigger a change * {@link ConfigurationListenerIF#definitionUpdated event}. * * @param url the url (containing alias and possible delegate url and driver) * @param info the properties * @return true if the definition is identical to that that represented by these parameters */ public boolean isEqual(String url, Properties info) { try { return !doChange(url, info, true, false); } catch (ProxoolException e) { LOG.error("Problem checking equality", e); return false; } /* boolean equal = true; if (info == null && completeInfo != null) { equal = false; } else if (info != null && completeInfo == null) { equal = false; } else if (!info.equals(completeInfo)) { equal = false; } else if (!url.equals(completeUrl)) { equal = false; } return equal; */ } } /* Revision history: $Log: ConnectionPoolDefinition.java,v $ Revision 1.36 2007/07/28 10:39:12 billhorsman Use enumeration of property names rather than iteration of keyset so that we make use of any default properties that might be set. Revision 1.35 2007/06/19 11:33:35 billhorsman Changed time (millisecond) properties from int to long: maximumConnectionLifetime, houseKeepingSleepTime, recentlyStartedThreshold, overloadWithoutRefusalLifetime, maximumActiveTime Revision 1.34 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.33 2005/05/04 16:24:59 billhorsman Now supports cloning. Revision 1.32 2004/06/02 20:19:14 billhorsman Added injectable interface properties Revision 1.31 2004/03/18 17:08:14 chr32 Added jmx* properties. Revision 1.30 2004/03/15 02:42:44 chr32 Removed explicit JNDI properties. Going for a generic approach instead. Revision 1.29 2003/10/30 00:13:59 billhorsman Fixed bug where all proxool properties were getting passed onto the delegate driver, and all delegate properties weren't Revision 1.28 2003/10/24 15:22:21 billhorsman Fixed bug where connection pool was being recognised as changed even when it wasn't. (This bug introduced after 0.7.2). Revision 1.27 2003/10/20 11:40:53 billhorsman Smarter handling of null and empty strings. No NPE during unit tests now. Revision 1.26 2003/10/19 13:31:57 billhorsman Setting a property to a zero length String actually sets it to a null Revision 1.25 2003/10/16 18:54:49 billhorsman Fixed javadoc for update() and redefine() methods which were transposed. Also improved exception handling for incomplete pool definitions. Revision 1.24 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.23 2003/09/29 17:48:08 billhorsman New fatal-sql-exception-wrapper-class allows you to define what exception is used as a wrapper. This means that you can make it a RuntimeException if you need to. Revision 1.22 2003/09/05 16:59:42 billhorsman Added wrap-fatal-sql-exceptions property Revision 1.21 2003/08/30 14:54:04 billhorsman Checkstyle Revision 1.20 2003/08/30 11:37:31 billhorsman Trim fatal-sql-exception messages so that whitespace around the comma delimiters does not get used to match against exception message. Revision 1.19 2003/07/23 06:54:48 billhorsman draft JNDI changes (shouldn't effect normal operation) Revision 1.18 2003/04/27 15:42:21 billhorsman fix to condition that meant configuration change was getting sent too often (and sometimes not at all) Revision 1.17 2003/04/19 12:58:41 billhorsman fixed bug where ConfigurationListener's definitionUpdated was getting called too frequently Revision 1.16 2003/04/10 21:50:16 billhorsman empty constructor for use by DataSource Revision 1.15 2003/03/11 14:51:49 billhorsman more concurrency fixes relating to snapshots Revision 1.14 2003/03/10 23:43:09 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.13 2003/03/10 15:26:45 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.12 2003/03/05 23:28:56 billhorsman deprecated maximum-new-connections property in favour of more descriptive simultaneous-build-throttle Revision 1.11 2003/03/05 18:42:32 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools Revision 1.10 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.9 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.8 2003/02/06 15:41:17 billhorsman add statistics-log-level Revision 1.7 2003/01/31 00:17:05 billhorsman statistics is now a string to allow multiple, comma-delimited values Revision 1.6 2003/01/30 17:20:38 billhorsman new statistics property Revision 1.5 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.4 2002/11/09 15:50:15 billhorsman new trace property and better doc Revision 1.3 2002/10/27 13:29:38 billhorsman deprecated debug-level in favour of verbose Revision 1.2 2002/10/17 19:46:02 billhorsman removed redundant reference to logFilename (we now use Jakarta's Commons Logging component Revision 1.1.1.1 2002/09/13 08:13:00 billhorsman new Revision 1.8 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.7 2002/07/04 09:05:36 billhorsman Fixes Revision 1.6 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.5 2002/07/02 08:41:59 billhorsman No longer public - we should be confuring pools with Properties now. Also added completeUrl property so that we can access pool by either alias or full url. Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionPoolDefinitionIF.java0000644000175000017500000003563010730503125032535 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Properties; import java.util.Set; /** * A full definition of everything to do with a connection. You can get one of these * from {@link ProxoolFacade#getConnectionPoolDefinition ProxoolFacade}. * *
     * String alias = "myPool";
     * ConnectionPoolDefinitionIF cpd = ProxoolFacade.getConnectionPoolDefinition(alias);
     * 
    * * If you want to update the definition you should either update the properties * definition next time you * {@link java.sql.Driver#connect ask} for a connection or call * {@link ProxoolFacade#updateConnectionPool Proxool} directly. * * @version $Revision: 1.23 $, $Date: 2007/06/19 11:33:35 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface ConnectionPoolDefinitionIF { /** 4 * 60 * 60 * 1000 (4 hours) */ public static final int DEFAULT_MAXIMUM_CONNECTION_LIFETIME = 4 * 60 * 60 * 1000; // 4 hours /** 300000 (5 minutes) */ public static final int DEFAULT_MAXIMUM_ACTIVE_TIME = 300000; // 5 minutes /** 0 */ public static final int DEFAULT_PROTOTYPE_COUNT = 0; /** 0 */ public static final int DEFAULT_MINIMUM_CONNECTION_COUNT = 0; /** 15 */ public static final int DEFAULT_MAXIMUM_CONNECTION_COUNT = 15; /** 30000 (30 Seconds) */ public static final int DEFAULT_HOUSE_KEEPING_SLEEP_TIME = 30000; /** 10 * @deprecated use {@link #DEFAULT_SIMULTANEOUS_BUILD_THROTTLE} instead */ public static final int DEFAULT_MAXIMUM_NEW_CONNECTIONS = 10; /** 10 */ public static final int DEFAULT_SIMULTANEOUS_BUILD_THROTTLE = 10; /** 60000 */ public static final int DEFAULT_OVERLOAD_WITHOUT_REFUSAL_THRESHOLD = 60000; /** 60000 */ public static final int DEFAULT_RECENTLY_STARTED_THRESHOLD = 60000; public static final int DEBUG_LEVEL_QUIET = 0; public static final int DEBUG_LEVEL_LOUD = 1; public static final String USER_PROPERTY = "user"; public static final String PASSWORD_PROPERTY = "password"; /** * @see #getFatalSqlExceptions */ public static final String FATAL_SQL_EXCEPTIONS_DELIMITER = ","; /** This is the time the house keeping thread sleeps for between checks. (milliseconds) */ long getHouseKeepingSleepTime(); /** The maximum number of connections to the database */ int getMaximumConnectionCount(); /** The maximum amount of time that a connection exists for before it is killed (recycled). (milliseconds) */ long getMaximumConnectionLifetime(); /** * In order to prevent overloading, this is the maximum number of connections that you can have that are in the progress * of being made. That is, ones we have started to make but haven't finished yet. * @deprecated use more descriptive {@link #getSimultaneousBuildThrottle} instead */ int getMaximumNewConnections(); /** * In order to prevent overloading, this is the maximum number of connections that you can have that are in the progress * of being made. That is, ones we have started to make but haven't finished yet. */ int getSimultaneousBuildThrottle(); /** The minimum number of connections we will keep open, regardless of whether anyone needs them or not. */ int getMinimumConnectionCount(); /** @deprecated use {@link #getAlias} instead. */ String getName(); /** The name associated with this connection pool. This is how you identify this pool when you need to use it. */ String getAlias(); /** The password to use to login to the database */ String getPassword(); /** * This is the number of spare connections we will strive to have. So, if we have a prototypeCount of 5 but only 3 spare * connections the prototyper will make an additional 2. This is important because it can take around a seconds to * establish a connection, and if we are being very strict about killing connections when they get too * old it happens a fair bit. */ int getPrototypeCount(); /** This is the URL used to connect to the database. e.g. driver:@host:port:database. */ String getUrl(); /* The user used to login to the database. */ String getUser(); /* Interrogate the JDBC driver for its version (warning: this information is not always correct - be very suspicious if it reports the version as 1.0) */ String getJdbcDriverVersion(); /** * Get all of the properties that are defined on the delegated driver. * @return the delegate properties * @deprecated use less ambiguous {@link #getDelegateProperties} instead */ Properties getProperties(); String getDriver(); /** As long as we have one connection that was started within this threshold then we consider the pool to be up. (That is, not down). This allows us to differentiate between having all the connections frozen and just being really busy. */ long getRecentlyStartedThreshold(); /** This is the time in milliseconds after the last time that we refused a connection that we still consider ourselves to be overloaded. We have to do this because, even when overloaded, it's not impossible for the available connection count to be high and it's possible to be serving a lot of connections. Recognising an overload is easy (we refuse a connection) - it's recognising when we stop being overloaded that is hard. Hence this fudge :) */ long getOverloadWithoutRefusalLifetime(); /** If the housekeeper comes across a thread that has been active for longer than this then it will kill it. So make sure you set this to a number bigger than your slowest expected response! */ long getMaximumActiveTime(); /** * @deprecated use {@link #isVerbose} instead */ int getDebugLevel(); /** * Get the list of fatal SQL exception (Strings) fragments that will * trigger the death of a Connection. * All SQLExceptions are caught and tested for containing this * text fragment. If it matches than this connection is considered useless * and it is discarded. Regardless of what happens the exception * is always thrown back to the user. * @return the list of exception fragments (String) * @see #FATAL_SQL_EXCEPTIONS_DELIMITER */ Set getFatalSqlExceptions(); /** * The test SQL that we perform to see if a connection is alright. * Should be fast and robust. * @return house keeping test SQL */ String getHouseKeepingTestSql(); /** * Whether we test each connection before it is served * @return true if we do the test * @see #getHouseKeepingTestSql */ boolean isTestBeforeUse(); /** * Whether we test each connection after it is closed * (that is, returned to the pool) * @return true if we do the test * @see #getHouseKeepingTestSql */ boolean isTestAfterUse(); /** * The URL that was used to define this pool. For example: * proxool:org.hsqldb.jdbcDriver:jdbc:hsqldb:test * @return the complete url */ String getCompleteUrl(); /** * If this is true then we start logging a lot of stuff everytime we serve a * connection and everytime the house keeper and prototyper run. Be * prepared for a lot of debug! * * @return true if in verbose mode */ boolean isVerbose(); /** * if this is true then we will log each execution. The SQL used and the * execution time. * * @return true if we should log each execution */ boolean isTrace(); /** * The sample length (in seconds) when taking statistical information, * or null to disable statistics. Default is null. You can comma delimit * a series of periods. The suffix for the period is either "s" (seconds), * "m" (minutes), "h" (hours) or "d" (days). For example: "15s,1h" would * give two separate sample rates: every 15 seconds and every hour. * @return statistics definition */ String getStatistics(); /** * Whether statistics are logged as they are produced. * Range: DEBUG, INFO, WARN, ERROR, FATAL. * Default is null (no logging) * @return statisticsLogLevel */ String getStatisticsLogLevel(); /** * Get all of the properties that are defined on the delegated driver. * @return the delegate properties */ Properties getDelegateProperties(); String getDelegateProperty(String name); /** * If this is not-null then any fatal SQLException is wrapped up inside * an instance of this class. If null, then the original exception is * thrown. * Range: any valid class name that is a subclass of SQLException or RuntimeException * Default: null (original exception is thrown) * @return the class name to use for fatal SQL exceptions */ String getFatalSqlExceptionWrapper(); /** * JNDI property * @return the initial context factory */ String getInitialContextFactory(); /** * JNDI property * @return provider URL */ String getProviderUrl(); /** * JNDI property * @return security authentication */ String getSecurityAuthentication(); /** * JNDI property * @return security principal */ String getSecurityPrincipal(); /** * JNDI property * @return security credentials */ String getSecurityCredentials(); /** * JNDI property * @return JNDI name */ String getJndiName(); /** * Indicate wether this pool should be registered with JMX or not. * @return wether this pool should be registered with JMX or not. */ boolean isJmx(); /** * Get a comma separated list of JMX agent ids (as used by * MBeanServerFactory.findMBeanServer(String agentId)) to register the pool to. * @return a comma separated list of JMX agent ids (as used by * MBeanServerFactory.findMBeanServer(String agentId)) to register the pool to. */ String getJmxAgentId(); /** * The class name of an interface that should be injected everytime we make a Connection. * Use this when you want to access methods on a concrete class in the vendor's Connection * object that aren't declared in a public interface. Without this, the connection that * gets served will only give you access to public interfaces (like Connection and any * other vendor provided ones) * @return the interface */ Class getInjectableConnectionInterface(); /** * The class name of an interface that should be injected everytime we make a Statement. * Use this when you want to access methods on a concrete class in the vendor's Statement * object that aren't declared in a public interface. Without this, the statement that * is provided will only give you access to public interfaces (like Statement and any * other vendor provided ones) * @return the interface */ Class getInjectableStatementInterface(); /** * The class name of an interface that should be injected everytime we make a PreparedStatement. * Use this when you want to access methods on a concrete class in the vendor's PreparedStatement * object that aren't declared in a public interface. Without this, the PreparedStatement that * is provided will only give you access to public interfaces (like PreparedStatement and any * other vendor provided ones) * @return the interface */ Class getInjectablePreparedStatementInterface(); /** * The class name of an interface that should be injected everytime we make a CallableStatement. * Use this when you want to access methods on a concrete class in the vendor's CallableStatement * object that aren't declared in a public interface. Without this, the CallableStatement that * is provided will only give you access to public interfaces (like CallableStatement and any * other vendor provided ones) * @return the interface */ Class getInjectableCallableStatementInterface(); } /* Revision history: $Log: ConnectionPoolDefinitionIF.java,v $ Revision 1.23 2007/06/19 11:33:35 billhorsman Changed time (millisecond) properties from int to long: maximumConnectionLifetime, houseKeepingSleepTime, recentlyStartedThreshold, overloadWithoutRefusalLifetime, maximumActiveTime Revision 1.22 2004/06/02 20:19:14 billhorsman Added injectable interface properties Revision 1.21 2004/03/18 17:08:14 chr32 Added jmx* properties. Revision 1.20 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.19 2003/09/29 17:48:08 billhorsman New fatal-sql-exception-wrapper-class allows you to define what exception is used as a wrapper. This means that you can make it a RuntimeException if you need to. Revision 1.18 2003/09/05 16:59:42 billhorsman Added wrap-fatal-sql-exceptions property Revision 1.17 2003/07/23 06:54:48 billhorsman draft JNDI changes (shouldn't effect normal operation) Revision 1.16 2003/03/05 23:28:56 billhorsman deprecated maximum-new-connections property in favour of more descriptive simultaneous-build-throttle Revision 1.15 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.14 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.13 2003/02/06 15:41:17 billhorsman add statistics-log-level Revision 1.12 2003/01/31 00:17:04 billhorsman statistics is now a string to allow multiple, comma-delimited values Revision 1.11 2003/01/30 17:20:37 billhorsman new statistics property Revision 1.10 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.9 2002/12/17 14:20:44 billhorsman doc Revision 1.8 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.7 2002/11/09 15:50:15 billhorsman new trace property and better doc Revision 1.6 2002/10/27 13:29:38 billhorsman deprecated debug-level in favour of verbose Revision 1.5 2002/10/27 12:09:00 billhorsman default minimum connection count changed from 5 to 0 Revision 1.4 2002/10/25 16:00:25 billhorsman added better class javadoc Revision 1.3 2002/10/24 17:29:06 billhorsman prototype count now defaults to zero Revision 1.2 2002/10/17 19:46:02 billhorsman removed redundant reference to logFilename (we now use Jakarta's Commons Logging component Revision 1.1.1.1 2002/09/13 08:13:02 billhorsman new Revision 1.6 2002/07/02 08:44:56 billhorsman Removed all mutators Revision 1.5 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionPoolManager.java0000644000175000017500000001402010730503124031565 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * * @version $Revision: 1.16 $, $Date: 2006/01/18 14:40:01 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ class ConnectionPoolManager { private static final Object LOCK = new Object(); private Map connectionPoolMap = new HashMap(); private Set connectionPools = new HashSet(); private static ConnectionPoolManager connectionPoolManager = null; private static final Log LOG = LogFactory.getLog(ProxoolFacade.class); public static ConnectionPoolManager getInstance() { if (connectionPoolManager == null) { synchronized (LOCK) { if (connectionPoolManager == null) { connectionPoolManager = new ConnectionPoolManager(); } } } return connectionPoolManager; } private ConnectionPoolManager() { } /** * Get the pool by the alias * @param alias identifies the pool * @return the pool * @throws ProxoolException if it couldn't be found */ protected ConnectionPool getConnectionPool(String alias) throws ProxoolException { ConnectionPool cp = (ConnectionPool) connectionPoolMap.get(alias); if (cp == null) { throw new ProxoolException(getKnownPools(alias)); } return cp; } /** * Convenient method for outputing a message explaining that a pool couldn't * be found and listing the ones that could be found. * @param alias identifies the pool * @return a description of the wht the pool couldn't be found */ protected String getKnownPools(String alias) { StringBuffer message = new StringBuffer("Couldn't find a pool called '" + alias + "'. Known pools are: "); Iterator i = connectionPoolMap.keySet().iterator(); while (i.hasNext()) { message.append((String) i.next()); message.append(i.hasNext() ? ", " : "."); } return message.toString(); } /** * Whether the pool is already registered * @param alias how we identify the pool * @return true if it already exists, else false */ protected boolean isPoolExists(String alias) { return connectionPoolMap.containsKey(alias); } /** @return an array of the connection pools */ protected ConnectionPool[] getConnectionPools() { return (ConnectionPool[]) connectionPools.toArray(new ConnectionPool[connectionPools.size()]); } protected ConnectionPool createConnectionPool(ConnectionPoolDefinition connectionPoolDefinition) throws ProxoolException { ConnectionPool connectionPool = new ConnectionPool(connectionPoolDefinition); connectionPools.add(connectionPool); connectionPoolMap.put(connectionPoolDefinition.getAlias(), connectionPool); return connectionPool; } protected void removeConnectionPool(String name) { ConnectionPool cp = (ConnectionPool) connectionPoolMap.get(name); if (cp != null) { connectionPoolMap.remove(cp.getDefinition().getAlias()); connectionPools.remove(cp); } else { LOG.info("Ignored attempt to remove either non-existent or already removed connection pool " + name); } } public String[] getConnectionPoolNames() { return (String[]) connectionPoolMap.keySet().toArray(new String[connectionPoolMap.size()]); } } /* Revision history: $Log: ConnectionPoolManager.java,v $ Revision 1.16 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.15 2003/03/11 14:51:51 billhorsman more concurrency fixes relating to snapshots Revision 1.14 2003/03/10 23:43:09 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.13 2003/03/10 15:26:45 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.12 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.11 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.10 2003/02/28 10:42:59 billhorsman ConnectionPoolManager now passes ProxoolFacade an array of ConnectionPools rather than a Collection to avoid a ConcurrentModificationException during shutdown. Revision 1.9 2003/02/07 10:27:47 billhorsman change in shutdown procedure to allow re-registration Revision 1.8 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.7 2003/01/27 18:26:36 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.6 2003/01/23 11:08:26 billhorsman new setConfiguratorListener method (and remove from optional parameter when registering pool) Revision 1.5 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.4 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.3 2002/11/09 15:49:36 billhorsman add method to get the name of every pool Revision 1.2 2002/10/13 13:39:03 billhorsman fix when removing pools (credit to Dan Milstein) Revision 1.1.1.1 2002/09/13 08:13:04 billhorsman new Revision 1.8 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.7 2002/07/04 09:05:36 billhorsman Fixes Revision 1.6 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.5 2002/07/02 08:47:31 billhorsman you can now access a pool by alias or full url Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionPoolStatisticsIF.java0000644000175000017500000000520510730503125032572 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Date; /** * This provides real time information about the pool. You can get this from * {@link ProxoolFacade#getConnectionPoolStatistics ProxoolFacade}. * *
     * String alias = "myPool";
     * ConnectionPoolStatisticsIF cps = ProxoolFacade.getConnectionPoolStatistics(alias);
     * 
    * * @version $Revision: 1.6 $, $Date: 2005/10/02 12:32:02 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface ConnectionPoolStatisticsIF { /** * The number of connections provided. * @return connectionsServedCount */ long getConnectionsServedCount(); /** * The number of connections refused. Either because there was a problem * connecting to the database, or perhaps because the maximumConnectionCount * was reached. * @return connectionsRefusedCount */ long getConnectionsRefusedCount(); /** * The number of connections currently in use. * @return activeConnectionCount */ int getActiveConnectionCount(); /** * The number of connections that are available for use (doesn't include * active connections). * @return availableConnectionCount */ int getAvailableConnectionCount(); /** * The number of connections that are neither active or available. Probably * because the house keeping thread is checking them. * @return offlineConnectionCount */ int getOfflineConnectionCount(); /** * When this pool was started * @return dateStarted */ Date getDateStarted(); long getConnectionCount(); } /* Revision history: $Log: ConnectionPoolStatisticsIF.java,v $ Revision 1.6 2005/10/02 12:32:02 billhorsman Make connectionCount available to statistics Revision 1.5 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.4 2003/01/15 12:01:21 billhorsman added getDateStarted() plus better doc Revision 1.3 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.2 2002/10/25 16:00:26 billhorsman added better class javadoc Revision 1.1.1.1 2002/09/13 08:13:04 billhorsman new Revision 1.6 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.5 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionResetter.java0000644000175000017500000003663110730503124031172 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.Log; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * Responsible for resetting a Connection to its default state when it is * returned to the pool. It must be initialised by the first Connection that * is made (for each pool) so that we don't make any assumptions about * what the default values are. * * @version $Revision: 1.16 $, $Date: 2006/01/18 14:40:01 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class ConnectionResetter { private Log log; /** * @see #initialise */ private boolean initialised; /** * @see #addReset * @see #reset */ private Map accessorMutatorMap = new HashMap(); /** * @see #addReset * @see #reset */ private Map defaultValues = new HashMap(); /** * We use this to guess if we are changing a property that will need resetting */ protected static final String MUTATOR_PREFIX = "set"; private String driverName; /** * @see #isTriggerResetException() */ protected static boolean triggerResetException; /** * Pass in the log to use * @param log debug information sent here */ protected ConnectionResetter(Log log, String driverName) { this.log = log; this.driverName = driverName; // Map all the reset methods addReset("getCatalog", "setCatalog"); addReset("isReadOnly", "setReadOnly"); addReset("getTransactionIsolation", "setTransactionIsolation"); addReset("getTypeMap", "setTypeMap"); addReset("getHoldability", "setHoldability"); } /** * Add a pair of methods that need resetting each time a connection is * put back in the pool * @param accessorName the name of the "getter" method (e.g. getAutoCommit) * @param mutatorName teh name of the "setter" method (e.g. setAutoCommit) */ private void addReset(String accessorName, String mutatorName) { try { Method accessor = null; Method mutator = null; Method[] methods = Connection.class.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(accessorName)) { if (accessor == null) { accessor = method; } else { log.info("Skipping ambiguous reset method " + accessorName); return; } } if (method.getName().equals(mutatorName)) { if (mutator == null) { mutator = method; } else { log.info("Skipping ambiguous reset method " + mutatorName); return; } } } if (accessor == null) { log.debug("Ignoring attempt to map reset method " + accessorName + " (probably because it isn't implemented in this JDK)"); } else if (mutator == null) { log.debug("Ignoring attempt to map reset method " + mutatorName + " (probably because it isn't implemented in this JDK)"); } else if (accessorMutatorMap.containsKey(accessor)) { log.warn("Ignoring attempt to map duplicate reset method " + accessorName); } else if (accessorMutatorMap.containsValue(mutator)) { log.warn("Ignoring attempt to map duplicate reset method " + mutatorName); } else { if (mutatorName.indexOf(MUTATOR_PREFIX) != 0) { log.warn("Resetter mutator " + mutatorName + " does not start with " + MUTATOR_PREFIX + " as expected. Proxool maynot recognise that a reset is necessary."); } if (accessor.getParameterTypes().length > 0) { log.info("Ignoring attempt to map accessor method " + accessorName + ". It must have no arguments."); } else if (mutator.getParameterTypes().length != 1) { log.info("Ignoring attempt to map mutator method " + mutatorName + ". It must have exactly one argument, not " + mutator.getParameterTypes().length); } else { accessorMutatorMap.put(accessor, mutator); } } } catch (Exception e) { log.error("Problem mapping " + accessorName + " and " + mutatorName, e); } } /** * This gets called every time we make a Connection. Not that often * really, so it's ok to synchronize a bit. * @param connection this will be used to get all the default values */ protected void initialise(Connection connection) { if (!initialised) { synchronized (this) { if (!initialised) { Set accessorsToRemove = new HashSet(); Iterator i = accessorMutatorMap.keySet().iterator(); while (i.hasNext()) { Method accessor = (Method) i.next(); Method mutator = (Method) accessorMutatorMap.get(accessor); Object value = null; try { value = accessor.invoke(connection, null); // It's perfectly ok for the default value to be null, we just // don't want to add it to the map. if (value != null) { defaultValues.put(mutator, value); } if (log.isDebugEnabled()) { log.debug("Remembering default value: " + accessor.getName() + "() = " + value); } } catch (Throwable t) { log.debug(driverName + " does not support " + accessor.getName() + ". Proxool doesn't mind."); // We will remove this later (to avoid ConcurrentModifcation) accessorsToRemove.add(accessor); } // Just test that the mutator works too. Otherwise it's going to fall over // everytime we close a connection try { Object[] args = {value}; mutator.invoke(connection, args); } catch (Throwable t) { log.debug(driverName + " does not support " + mutator.getName() + ". Proxool doesn't mind."); // We will remove this later (to avoid ConcurrentModifcation) accessorsToRemove.add(accessor); } } // Remove all the reset methods that we had trouble configuring Iterator j = accessorsToRemove.iterator(); while (j.hasNext()) { Method accessor = (Method) j.next(); Method mutator = (Method) accessorMutatorMap.get(accessor); accessorMutatorMap.remove(accessor); defaultValues.remove(mutator); } initialised = true; } } } } /** * Reset this connection to its default values. If anything goes wrong, it is logged * as a warning or info but it silently continues. * @param connection to be reset * @param id used in log messages * @return true if the reset was error free, or false if it encountered errors. (in which case it should probably not be reused) */ protected boolean reset(Connection connection, String id) { boolean errorsEncountered = false; try { connection.clearWarnings(); } catch (SQLException e) { errorsEncountered = true; log.warn(id + " - Problem calling connection.clearWarnings()", e); } // Let's see the state of autoCommit. It will help us give better advice in the log messages boolean autoCommit = true; try { autoCommit = connection.getAutoCommit(); } catch (SQLException e) { errorsEncountered = true; log.warn(id + " - Problem calling connection.getAutoCommit()", e); } /* Automatically rollback if autocommit is off. If there are no pending transactions then this will have no effect. From Database Language SQL (Proposed revised text of DIS 9075), July 1992 - http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt "The execution of a may be initiated implicitly by an implementation when it detects unrecoverable errors. When such an error occurs, an exception condition is raised: transaction rollback with an implementation-defined subclass code". */ if (!autoCommit) { try { connection.rollback(); } catch (SQLException e) { log.error("Unexpected exception whilst calling rollback during connection reset", e); } } // Now let's reset each property in turn. With a bit of luck, if there is a // transaction pending then setting one of these properties will throw an // exception (e.g. "operation not possible when transaction is in progress" // or something). We want to know about transactions that are pending. // It doesn't seem like a very good idea to close a connection with // pending transactions. Iterator i = accessorMutatorMap.keySet().iterator(); while (i.hasNext()) { Method accessor = (Method) i.next(); Method mutator = (Method) accessorMutatorMap.get(accessor); Object[] args = {defaultValues.get(mutator)}; try { Object currentValue = accessor.invoke(connection, null); if (currentValue == null && args[0] == null) { // Nothing to do then } else if (currentValue.equals(args[0])) { // Nothing to do here either } else { mutator.invoke(connection, args); if (log.isDebugEnabled()) { log.debug(id + " - Reset: " + mutator.getName() + "(" + args[0] + ") from " + currentValue); } } } catch (Throwable t) { errorsEncountered = true; if (log.isDebugEnabled()) { log.debug(id + " - Problem resetting: " + mutator.getName() + "(" + args[0] + ").", t); } } } // Finally. reset autoCommit. if (!autoCommit) { try { // Setting autoCommit to true might well commit all pending // transactions. But that's beyond our control. connection.setAutoCommit(true); log.debug(id + " - autoCommit reset back to true"); } catch (Throwable t) { errorsEncountered = true; log.warn(id + " - Problem calling connection.commit() or connection.setAutoCommit(true)", t); } } if (isTriggerResetException()) { log.warn("Triggering pretend exception during reset"); errorsEncountered = true; } if (errorsEncountered) { log.warn(id + " - There were some problems resetting the connection (see debug output for details). It will not be used again " + "(just in case). The thread that is responsible is named '" + Thread.currentThread().getName() + "'"); if (!autoCommit) { log.warn(id + " - The connection was closed with autoCommit=false. That is fine, but it might indicate that " + "the problems that happened whilst trying to reset it were because a transaction is still in progress."); } } return !errorsEncountered; } private static boolean isTriggerResetException() { return triggerResetException; } /** * Called by a unit test. * @param triggerResetException true it we should trigger a pretend exception. * @see #isTriggerResetException() */ protected static void setTriggerResetException(boolean triggerResetException) { ConnectionResetter.triggerResetException = triggerResetException; } } /* Revision history: $Log: ConnectionResetter.java,v $ Revision 1.16 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.15 2005/10/07 08:21:53 billhorsman New hook to allow unit tests to trigger a deliberate exception during reset Revision 1.14 2003/03/10 23:43:10 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.13 2003/03/10 15:26:46 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.12 2003/03/03 11:11:57 billhorsman fixed licence Revision 1.11 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.10 2003/01/07 17:21:11 billhorsman If autoCommit is off, all connections are rollbacked. Revision 1.9 2002/11/13 20:53:16 billhorsman now checks to see whether is necessary for each property (better logging) Revision 1.8 2002/11/13 18:27:59 billhorsman rethink. committing automatically is bad. so now we just set autoCommit back to true (which might commit anyway but that's down to the driver). we do the autoCommit last so that some of the other resets might throw an exception if there was a pending transaction. (Throwing an exception is good - pending transactions are bad.) Revision 1.7 2002/11/12 21:12:21 billhorsman automatically calls clearWarnings too Revision 1.6 2002/11/12 21:10:41 billhorsman Hmm. Now commits any pending transactions automatically when you close the connection. I'm still pondering whether this is wise or not. The only other sensible option is to rollback since I can't find a way of determining whether either is necessary. Revision 1.5 2002/11/12 20:24:12 billhorsman checkstyle Revision 1.4 2002/11/12 20:18:23 billhorsman Made connection resetter a bit more friendly. Now, if it encounters any problems during reset then that connection is thrown away. This is going to cause you problems if you always close connections in an unstable state (e.g. with transactions open. But then again, it's better to know about that as soon as possible, right? Revision 1.3 2002/11/07 18:55:40 billhorsman demoted log message from info to debug Revision 1.2 2002/11/07 12:38:04 billhorsman performance improvement - only reset when it might be necessary Revision 1.1 2002/11/06 20:25:08 billhorsman New class responsible for resetting connections when they are returned to the pool. */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ConnectionValidatorIF.java0000644000175000017500000000133610730503125031534 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; /** * @author Bertrand Renuart * */ public interface ConnectionValidatorIF { boolean validate(ConnectionPoolDefinitionIF cpd, Connection connection); } /* Revision history: $Log: ConnectionValidatorIF.java,v $ Revision 1.1 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/DefaultConnectionBuilder.java0000644000175000017500000000261110730503125032260 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * @author Bertrand Renuart * */ public class DefaultConnectionBuilder implements ConnectionBuilderIF { /** * */ public DefaultConnectionBuilder() { super(); } // // -- ConnectionBuilderIF interface implementation ---------------------- // /* (non-Javadoc) * @see org.logicalcobwebs.proxool.ConnectionBuilderIF#buildConnection(org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF) */ public Connection buildConnection(ConnectionPoolDefinitionIF cpd) throws SQLException { Connection realConnection = null; final String url = cpd.getUrl(); Properties info = cpd.getDelegateProperties(); return DriverManager.getConnection(url, info); } } /* Revision history: $Log: DefaultConnectionBuilder.java,v $ Revision 1.1 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/DefaultConnectionValidator.java0000644000175000017500000000522410730503124032621 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.Statement; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author Bertrand Renuart */ public class DefaultConnectionValidator implements ConnectionValidatorIF { /** * */ public DefaultConnectionValidator() { super(); } // // -- ConnectionValidatorIF interface implementation ---------------------- // /* (non-Javadoc) * @see org.logicalcobwebs.proxool.ConnectionValidatorIF#validate(org.logicalcobwebs.proxool.ConnectionPoolDefinition, java.sql.Connection) */ public boolean validate(ConnectionPoolDefinitionIF cpd, Connection connection) { // make sure a test SQL is defined // final String testSql = cpd.getHouseKeepingTestSql(); if (testSql == null || (testSql.length() == 0)) { Log log = getPoolLog(cpd.getAlias()); log.warn("Connection validation requested but house-keeping-test-sql not defined"); return false; } // execute the test statement // Statement st = null; try { st = connection.createStatement(); st.execute(testSql); return true; } catch (Throwable t) { // got an exception while executing the test statement // log the problem and return false Log log = getPoolLog(cpd.getAlias()); if(log.isDebugEnabled()) log.debug("A connection failed the validation test with error: "+t); return false; } finally { if (st != null) { try { st.close(); } catch (Throwable t) { // Ignore return false; } } } } /** * * @param poolAlias * @return */ private Log getPoolLog(String poolAlias) { return LogFactory.getLog("org.logicalcobwebs.proxool." + poolAlias); } } /* Revision history: $Log: DefaultConnectionValidator.java,v $ Revision 1.2 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.1 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/FatalRuntimeException.java0000644000175000017500000000163610730503125031625 0ustar twernertwerner/* * This software is released under the Apache Software Licence. See * package.html for details. The latest version is available at * http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; /** * A type of SQLException that has been defined as fatal. It contains * the {@link #getCause original} plain Exception * just in case you need it. * @version $Revision: 1.1 $, $Date: 2003/09/29 17:48:08 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) * @see ConnectionPoolDefinitionIF#getFatalSqlExceptions */ public class FatalRuntimeException extends RuntimeException { /** * @see #getCause */ private Exception cause; public FatalRuntimeException(Exception cause) { super(cause.getMessage()); this.cause = cause; } /** * @see Throwable#getCause */ public Throwable getCause() { return cause; } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/FatalSQLException.java0000644000175000017500000000314710730503125030640 0ustar twernertwerner/* * This software is released under the Apache Software Licence. See * package.html for details. The latest version is available at * http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.SQLException; /** * A type of SQLException that has been defined as fatal. It contains * the {@link #getOriginalSQLException original} plain SQLException * just in case you need it. * @version $Revision: 1.3 $, $Date: 2003/09/10 22:21:04 $ * @author billhorsman * @author $Author: chr32 $ (current maintainer) * @see ConnectionPoolDefinitionIF#getFatalSqlExceptions */ public class FatalSQLException extends SQLException { /** * @see #getOriginalSQLException */ private SQLException cause; public FatalSQLException(SQLException cause) { this(cause, cause.getMessage(), cause.getSQLState()); } /** * @param cause the SQLException that was detected as being fatal * @param reason see {@link super#SQLException(java.lang.String, java.lang.String)} * @param sqlState see {@link super#SQLException(java.lang.String, java.lang.String)} */ public FatalSQLException(SQLException cause, String reason, String sqlState) { super(reason, sqlState); this.cause = cause; } /** * Same as {@link #getOriginalSQLException} * @see Throwable#getCause */ public Throwable getCause() { return cause; } /** * Get the SQLException that was detected as being fatal * @return the original SQLException */ public SQLException getOriginalSQLException() { return cause; } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/FatalSqlExceptionHelper.java0000644000175000017500000002172610730503125032103 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.Iterator; /** * Will wrap up exceptions in another exception which can be defined at runtime. * @version $Revision: 1.5 $, $Date: 2006/01/18 14:40:01 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ class FatalSqlExceptionHelper { private static final Log LOG = LogFactory.getLog(FatalSqlExceptionHelper.class); /** * Throws a wrapped SQLException if a wrapper is defined * @param className the classname of the wrapping exception (must be either a RuntimeException or * an SQLException). If null, then the original exception is rethrown. * @param originalException the orginal exception * @throws ProxoolException if there is an unexpected error with wrapping the exception * @throws SQLException either the original exception, or a wrapped version of it * @throws RuntimeException a wrapped up version of the orginal */ protected static void throwFatalSQLException(String className, Throwable originalException) throws ProxoolException, SQLException, RuntimeException { if (className != null && className.trim().length() > 0) { Class clazz = null; try { clazz = Class.forName(className); } catch (ClassNotFoundException e) { throw new ProxoolException("Couldn't find class " + className); } if (SQLException.class.isAssignableFrom(clazz)) { // That's OK } else if (RuntimeException.class.isAssignableFrom(clazz)) { // That's OK } else { throw new ProxoolException("Couldn't wrap up using " + clazz.getName() + " because it isn't either a RuntimeException or an SQLException"); } Constructor toUse = null; Object[] args = null; String argDescription = ""; Constructor[] constructors = clazz.getConstructors(); for (int i = 0; i < constructors.length; i++) { Constructor constructor = constructors[i]; Class[] parameterTypes = constructor.getParameterTypes(); if (toUse == null && parameterTypes.length == 0) { toUse = constructor; } if (parameterTypes.length == 1 && Exception.class.isAssignableFrom(parameterTypes[0])) { toUse = constructor; args = new Object[]{originalException}; argDescription = "Exception"; break; } } try { Object exceptionToThrow = toUse.newInstance(args); if (exceptionToThrow instanceof RuntimeException) { LOG.debug("Wrapping up a fatal exception: " + originalException.getMessage(), originalException); throw (RuntimeException) exceptionToThrow; } else if (exceptionToThrow instanceof SQLException) { throw (SQLException) exceptionToThrow; } else { throw new ProxoolException("Couldn't throw " + clazz.getName() + " because it isn't either a RuntimeException or an SQLException"); } } catch (InstantiationException e) { throw new ProxoolException("Couldn't create " + clazz.getName() + "(" + argDescription + ")", e); } catch (IllegalAccessException e) { throw new ProxoolException("Couldn't create " + clazz.getName() + "(" + argDescription + ")", e); } catch (InvocationTargetException e) { throw new ProxoolException("Couldn't create " + clazz.getName() + "(" + argDescription + ")", e); } } else { if (originalException instanceof SQLException) { throw (SQLException) originalException; } else if (originalException instanceof RuntimeException) { throw (RuntimeException) originalException; } else { throw new RuntimeException("Unexpected exception:" + originalException.getMessage()); } } } /** * Test to see if an exception is a fatal one * @param cpd the definition so we can find out what a fatal exception looks like * @param t the exception to test * @return true if it is fatal */ protected static boolean testException(ConnectionPoolDefinitionIF cpd, Throwable t) { return testException(cpd, t, 0); } /** * Test to see if an exception is a fatal one * @param cpd the definition so we can find out what a fatal exception looks like * @param t the exception to test * @param level the recursion level (max 20) * @return true if it is fatal */ protected static boolean testException(ConnectionPoolDefinitionIF cpd, Throwable t, int level) { boolean fatalSqlExceptionDetected = false; Iterator i = cpd.getFatalSqlExceptions().iterator(); while (i.hasNext()) { if (t.getMessage() != null && t.getMessage().indexOf((String) i.next()) > -1) { // This SQL exception indicates a fatal problem with this connection. fatalSqlExceptionDetected = true; } } // If it isn't fatal, then try testing the contained exception if (!fatalSqlExceptionDetected && level < 20) { Throwable cause = getCause(t); if (cause != null) { fatalSqlExceptionDetected = testException(cpd, cause, level + 1); } } return fatalSqlExceptionDetected; } /** * Tries to drill down into an exception to find its cause. Only goes one level deep. * Uses reflection to look at getCause(), getTargetException(), getRootCause() and * finally getOriginalException() methods to see if it can find one. Doesn't throw * an error - it will just log a warning and return a null if nothing was found. * @param t the exception to look inside * @return the original exception or null if none was found. */ protected static Throwable getCause(Throwable t) { Throwable cause = null; Method causeMethod = null; try { // Try a series of likely accessor methods if (causeMethod == null) { causeMethod = getMethod(t, "getCause"); } if (causeMethod == null) { causeMethod = getMethod(t, "getTargetException"); } if (causeMethod == null) { causeMethod = getMethod(t, "getRootCause"); } if (causeMethod == null) { causeMethod = getMethod(t, "getOriginalException"); } // If one was found, invoke it. if (causeMethod != null) { try { cause = (Throwable) causeMethod.invoke(t, null); } catch (IllegalAccessException e) { LOG.warn("Problem invoking " + t.getClass().getName() + "." + causeMethod.getName() + ". Ignoring.", e); } catch (IllegalArgumentException e) { LOG.warn("Problem invoking " + t.getClass().getName() + "." + causeMethod.getName() + ". Ignoring.", e); } catch (InvocationTargetException e) { LOG.warn("Problem invoking " + t.getClass().getName() + "." + causeMethod.getName() + ". Ignoring.", e); } } } catch (Exception e) { LOG.warn("Unexpected exception drilling into exception. Ignoring.", e); } return cause; } private static Method getMethod(Object o, String methodName) { Method m = null; try { m = o.getClass().getMethod(methodName, null); // Reject any method that doesn't return a throwable. if (!Throwable.class.isAssignableFrom(m.getReturnType())) { m = null; } } catch (NoSuchMethodException e) { // That's OK } catch (SecurityException e) { LOG.warn("Problem finding method " + methodName, e); } return m; } } /* Revision history: $Log: FatalSqlExceptionHelper.java,v $ Revision 1.5 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.4 2005/07/01 08:02:50 billhorsman Check for exception message being null Revision 1.3 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.2 2003/09/29 18:12:33 billhorsman Doc */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/FormatHelper.java0000644000175000017500000000312010730503124027730 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.text.DecimalFormat; /** * Formats things as Strings * * @version $Revision: 1.1 $, $Date: 2003/03/05 18:42:33 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class FormatHelper { private static DecimalFormat smallNumberFormat = new DecimalFormat("00"); private static DecimalFormat mediumNumberFormat = new DecimalFormat("0000"); private static DecimalFormat bigCountFormat = new DecimalFormat("###000000"); /** * Format like 00 * @param value to format * @return formatted value */ public static String formatSmallNumber(long value) { return smallNumberFormat.format(value); } /** * Format like 0000 * @param value to format * @return formatted value */ public static String formatMediumNumber(long value) { return mediumNumberFormat.format(value); } /** * Format like ###000000 * @param value to format * @return formatted value */ public static String formatBigNumber(long value) { return bigCountFormat.format(value); } } /* Revision history: $Log: FormatHelper.java,v $ Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/HouseKeeper.java0000644000175000017500000003045510730503124027572 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.Statement; /** * Responisble for house keeping one pool * * @version $Revision: 1.7 $, $Date: 2007/01/25 23:38:24 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ class HouseKeeper { private static final Log LOG = LogFactory.getLog(HouseKeeper.class); private ConnectionPool connectionPool; private long timeLastSwept; public HouseKeeper(ConnectionPool connectionPool) { this.connectionPool = connectionPool; } protected void sweep() throws ProxoolException { ConnectionPoolDefinitionIF definition = connectionPool.getDefinition(); Log log = connectionPool.getLog(); Statement testStatement = null; try { connectionPool.acquirePrimaryReadLock(); // Right, now we know we're the right thread then we can carry on house keeping Connection connection = null; ProxyConnectionIF proxyConnection = null; int recentlyStartedActiveConnectionCountTemp = 0; // sanity check int[] verifiedConnectionCountByState = new int[4]; ProxyConnectionIF[] proxyConnections = connectionPool.getProxyConnections(); for (int i = 0; i < proxyConnections.length; i++) { proxyConnection = proxyConnections[i]; connection = proxyConnection.getConnection(); if (!connectionPool.isConnectionPoolUp()) { break; } // First lets check whether the connection still works. We should only validate // connections that are not is use! SetOffline only succeeds if the connection // is available. if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE)) { try { testStatement = connection.createStatement(); // Some DBs return an object even if DB is shut down if (proxyConnection.isReallyClosed()) { proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL); connectionPool.removeProxyConnection(proxyConnection, ConnectionListenerIF.HOUSE_KEEPER_TEST_FAIL, "it appears to be closed", ConnectionPool.FORCE_EXPIRY, true); } String sql = definition.getHouseKeepingTestSql(); if (sql != null && sql.length() > 0) { // A Test Statement has been provided. Execute it! boolean testResult = false; try { testResult = testStatement.execute(sql); } finally { if (log.isDebugEnabled() && definition.isVerbose()) { log.debug(connectionPool.displayStatistics() + " - Testing connection " + proxyConnection.getId() + (testResult ? ": True" : ": False")); } } } proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_AVAILABLE); } catch (Throwable e) { // There is a problem with this connection. Let's remove it! proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL); connectionPool.removeProxyConnection(proxyConnection, ConnectionListenerIF.HOUSE_KEEPER_TEST_FAIL, "it has problems: " + e, ConnectionPool.REQUEST_EXPIRY, true); } finally { try { testStatement.close(); } catch (Throwable t) { // Never mind. } } } // END if (poolableConnection.setOffline()) // Now to check whether the connection is due for expiry if (proxyConnection.getAge() > definition.getMaximumConnectionLifetime()) { final String reason = "age is " + proxyConnection.getAge() + "ms"; // Check whether we can make it offline if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE)) { if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL)) { // It is. Expire it now . connectionPool.expireProxyConnection(proxyConnection, ConnectionListenerIF.MAXIMUM_CONNECTION_LIFETIME_EXCEEDED, reason, ConnectionPool.REQUEST_EXPIRY); } } else { // Oh no, it's in use. Never mind, we'll mark it for expiry // next time it is available. This will happen in the // putConnection() method. proxyConnection.markForExpiry(reason); if (log.isDebugEnabled()) { log.debug(connectionPool.displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId()) + " marked for expiry."); } } // END if (poolableConnection.setOffline()) } // END if (poolableConnection.getAge() > maximumConnectionLifetime) // Now let's see if this connection has been active for a // suspiciously long time. if (proxyConnection.isActive()) { long activeTime = System.currentTimeMillis() - proxyConnection.getTimeLastStartActive(); if (activeTime < definition.getRecentlyStartedThreshold()) { // This connection hasn't been active for all that long // after all. And as long as we have at least one // connection that is "actively active" then we don't // consider the pool to be down. recentlyStartedActiveConnectionCountTemp++; } if (activeTime > definition.getMaximumActiveTime()) { // This connection has been active for way too long. We're // going to kill it :) connectionPool.removeProxyConnection(proxyConnection, ConnectionListenerIF.MAXIMUM_ACTIVE_TIME_EXPIRED, "it has been active for too long", ConnectionPool.FORCE_EXPIRY, true); String lastSqlCallMsg; if (proxyConnection.getLastSqlCall() != null) { lastSqlCallMsg = ", and the last SQL it performed is '" + proxyConnection.getLastSqlCall() + "'."; } else if (!proxyConnection.getDefinition().isTrace()) { lastSqlCallMsg = ", but the last SQL it performed is unknown because the trace property is not enabled."; } else { lastSqlCallMsg = ", but the last SQL it performed is unknown."; } log.warn("#" + FormatHelper.formatMediumNumber(proxyConnection.getId()) + " was active for " + activeTime + " milliseconds and has been removed automaticaly. The Thread responsible was named '" + proxyConnection.getRequester() + "'" + lastSqlCallMsg); } } // What have we got? verifiedConnectionCountByState[proxyConnection.getStatus()]++; } calculateUpState(recentlyStartedActiveConnectionCountTemp); } catch (Throwable e) { // We don't want the housekeeping thread to fall over! log.error("Housekeeping log.error( :", e); } finally { connectionPool.releasePrimaryReadLock(); timeLastSwept = System.currentTimeMillis(); if (definition.isVerbose()) { if (log.isDebugEnabled()) { log.debug(connectionPool.displayStatistics() + " - House keeping triggerSweep done"); } } } PrototyperController.triggerSweep(definition.getAlias()); } /** * Get the time since the last sweep was completed * @return timeSinceLastSweep (milliseconds) */ private long getTimeSinceLastSweep() { return System.currentTimeMillis() - timeLastSwept; } /** * Should we sleep * @return true if the time since the last sweep was completed is greater * than the {@link ConnectionPoolDefinitionIF#getHouseKeepingSleepTime houseKeepingSleepTime} * property. */ protected boolean isSweepDue() { if (connectionPool.isConnectionPoolUp()) { return (getTimeSinceLastSweep() > connectionPool.getDefinition().getHouseKeepingSleepTime()); } else { LOG.warn("House keeper is still being asked to sweep despite the connection pool being down"); return false; } } private void calculateUpState(int recentlyStartedActiveConnectionCount) { try { int calculatedUpState = StateListenerIF.STATE_QUIET; /* We're up if the last time we tried to make a connection it * was successful */ /* I've changed the way we do this. Just because we failed to create * a connection doesn't mean we're down. As long as we have some * available connections, or the active ones we have aren't locked * up then we should be able to struggle on. The last thing we want * to do is say we're down when we're not! */ // if (this.lastCreateWasSuccessful) { final int availableConnectionCount = connectionPool.getAvailableConnectionCount(); if (availableConnectionCount > 0 || recentlyStartedActiveConnectionCount > 0) { /* Defintion of overloaded is that we refused a connection * (because we were too busy) within the last minute. */ if (connectionPool.getTimeOfLastRefusal() > (System.currentTimeMillis() - connectionPool.getDefinition().getOverloadWithoutRefusalLifetime())) { calculatedUpState = StateListenerIF.STATE_OVERLOADED; } else if (connectionPool.getActiveConnectionCount() > 0) { /* Are we doing anything at all? */ calculatedUpState = StateListenerIF.STATE_BUSY; } } else { calculatedUpState = StateListenerIF.STATE_DOWN; } connectionPool.setUpState(calculatedUpState); } catch (Exception e) { LOG.error(e); } } /** * Identifies the pool we are sweeping * @return alias */ protected String getAlias() { return connectionPool.getDefinition().getAlias(); } } /* Revision history: $Log: HouseKeeper.java,v $ Revision 1.7 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.6 2007/01/25 00:10:25 billhorsman New onAboutToDie event for ConnectionListenerIF that gets called if the maximum-active-time is exceeded. Revision 1.5 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.4 2005/10/02 12:35:06 billhorsman Improve message when closing a connection that has been active for too long Revision 1.3 2003/09/11 23:57:48 billhorsman Test SQL now traps Throwable, not just SQLException. Revision 1.2 2003/03/10 15:26:46 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/HouseKeeperController.java0000644000175000017500000001160710730503124031634 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.util.FastArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Iterator; /** * Schedules when to run the house keeper * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:01 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class HouseKeeperController { private static final Log LOG = LogFactory.getLog(HouseKeeperController.class); private static Map houseKeepers = new HashMap(); private static List houseKeeperList = new FastArrayList(); private static int houseKeeperIndex = 0; private static List houseKeeperThreads = new FastArrayList(); private static final Object LOCK = new Integer(1); private static HouseKeeper getHouseKeeper(String alias) throws ProxoolException { final HouseKeeper houseKeeper = (HouseKeeper) houseKeepers.get(alias); if (houseKeeper == null) { throw new ProxoolException("Tried to use an unregistered house keeper '" + alias + "'"); } return houseKeeper; } /** * Get the next house keeper that needs to be run * @return the house keeper to run, or null if there is nothing to do. */ protected static HouseKeeper getHouseKeeperToRun() { HouseKeeper houseKeeper = null; synchronized (LOCK) { for (int i = 0; i < houseKeeperList.size(); i++) { HouseKeeper hk = null; try { hk = (HouseKeeper) houseKeeperList.get(houseKeeperIndex); if (hk.isSweepDue()) { houseKeeper = hk; break; } houseKeeperIndex++; } catch (IndexOutOfBoundsException e) { houseKeeperIndex = 0; } } } return houseKeeper; } protected static void sweepNow(String alias) { try { getHouseKeeper(alias).sweep(); } catch (ProxoolException e) { LOG.error("Couldn't run house keeper for " + alias, e); } } /** * Schedule a regular triggerSweep * @param connectionPool identifies the pool */ protected static void register(ConnectionPool connectionPool) { String alias = connectionPool.getDefinition().getAlias(); LOG.debug("Registering '" + alias + "' house keeper"); HouseKeeper houseKeeper = new HouseKeeper(connectionPool); synchronized (LOCK) { houseKeepers.put(alias, houseKeeper); houseKeeperList.add(houseKeeper); if (houseKeeperThreads.size() == 0) { HouseKeeperThread hkt = new HouseKeeperThread("HouseKeeper"); LOG.debug("Starting a house keeper thread"); hkt.start(); houseKeeperThreads.add(hkt); } } } /** * Stop all house keeper threads. */ protected static void shutdown() { synchronized(LOCK) { Iterator i = houseKeeperThreads.iterator(); while (i.hasNext()) { HouseKeeperThread hkt = (HouseKeeperThread) i.next(); LOG.info("Stopping " + hkt.getName() + " thread"); hkt.cancel(); } houseKeeperThreads.clear(); } } /** * cancel a house keeper for a pool. This doens't stop the house keeper * thread. * @param alias identifies the pool * @throws ProxoolException if we couldn't find the house keeper (if it had * already been cancelled for instance). */ protected static void cancel(String alias) throws ProxoolException { HouseKeeper hk = getHouseKeeper(alias); houseKeepers.remove(alias); houseKeeperList.remove(hk); } } /* Revision history: $Log: HouseKeeperController.java,v $ Revision 1.6 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2004/06/02 20:38:32 billhorsman More robust round robin of house keepers. Revision 1.4 2004/03/26 15:58:56 billhorsman Fixes to ensure that house keeper and prototyper threads finish after shutdown. Revision 1.3 2003/03/10 23:43:10 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.2 2003/03/10 15:26:46 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/HouseKeeperThread.java0000644000175000017500000000433610730503124030721 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Responsible for running {@link HouseKeeper#sweep sweep} * * @version $Revision: 1.5 $, $Date: 2006/01/18 14:40:01 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class HouseKeeperThread extends Thread { private static final Log LOG = LogFactory.getLog(HouseKeeperThread.class); private boolean stop; public HouseKeeperThread(String name) { setDaemon(true); setName(name); } public void run() { while (!stop) { HouseKeeper hk = HouseKeeperController.getHouseKeeperToRun(); while (hk != null && !stop) { try { // if (LOG.isDebugEnabled()) { // LOG.debug("About to sweep " + hk.getAlias()); // } hk.sweep(); } catch (ProxoolException e) { LOG.error("Couldn't sweep " + hk.getAlias(), e); } hk = HouseKeeperController.getHouseKeeperToRun(); } try { Thread.sleep(5000); } catch (InterruptedException e) { LOG.error("Interrupted", e); } } } protected void cancel() { stop = true; } } /* Revision history: $Log: HouseKeeperThread.java,v $ Revision 1.5 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.4 2004/03/26 15:58:56 billhorsman Fixes to ensure that house keeper and prototyper threads finish after shutdown. Revision 1.3 2003/04/19 12:57:29 billhorsman removed redundant debug Revision 1.2 2003/03/10 15:26:47 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/Prototyper.java0000644000175000017500000003305710730503125027544 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Responsible for prototyping connections for all pools * @version $Revision: 1.14 $, $Date: 2006/03/23 11:44:57 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class Prototyper { private ConnectionPool connectionPool; private Log log = LogFactory.getLog(Prototyper.class); private long connectionCount; private final Object lock = new Integer(1); private boolean sweepNeeded = true; /** This allows us to have a unique ID for each connection */ private long nextConnectionId = 1; /** * Calling {@link #cancel} will set this to true and stop all * current prototyping immediately */ private boolean cancel; /** * The number of connections currently being made (actually in * progress) */ private int connectionsBeingMade; /** * The builder that will create *real* connections for us. * Currently initialized to the default implementation until we fully * support pluggable ConnectionBuilders */ private ConnectionBuilderIF connectionBuilder = new DefaultConnectionBuilder(); public Prototyper(ConnectionPool connectionPool) { this.connectionPool = connectionPool; this.log = connectionPool.getLog(); } protected boolean isSweepNeeded() { return sweepNeeded; } protected void triggerSweep() { sweepNeeded = true; } /** * Trigger prototyping immediately * @return true if something was prototyped */ protected boolean sweep() { boolean somethingDone = false; try { while (!cancel && connectionPool.isConnectionPoolUp()) { // if (log.isDebugEnabled()) { // log.debug("Prototyping"); // } String reason = null; if (connectionCount >= getDefinition().getMaximumConnectionCount()) { // We don't want to make any more that the maximum break; } else if (connectionCount < getDefinition().getMinimumConnectionCount()) { reason = "to achieve minimum of " + getDefinition().getMinimumConnectionCount(); } else if (connectionPool.getAvailableConnectionCount() < getDefinition().getPrototypeCount()) { reason = "to keep " + getDefinition().getPrototypeCount() + " available"; } else { // Nothing to do break; } ProxyConnectionIF freshlyBuiltProxyConnection = null; try { // If it has been shutdown then we should just stop now. if (!connectionPool.isConnectionPoolUp()) { break; } freshlyBuiltProxyConnection = buildConnection(ConnectionInfoIF.STATUS_AVAILABLE, reason); somethingDone = true; } catch (Throwable e) { log.error("Prototype", e); // If there's been an exception, perhaps we should stop // prototyping for a while. Otherwise if the database // has problems we end up trying the connection every 2ms // or so and then the log grows pretty fast. break; // Don't wory, we'll start again the next time the // housekeeping thread runs. } if (freshlyBuiltProxyConnection == null) { // That's strange. No double the buildConnection() method logged the // error, but we should have build a connection here. } } } catch (Throwable t) { log.error("Unexpected error", t); } return somethingDone; } /** * Build a new connection * @param status the initial status it will be created as (this allows us * to create it as {@link ConnectionInfoIF#STATUS_ACTIVE ACTIVE} and avoid * another thread grabbing it before we can) * @param creator for log audit * @return the new connection */ protected ProxyConnection buildConnection(int status, String creator) throws SQLException, ProxoolException { long id = 0; synchronized (lock) { // Check that we are allowed to make another connection if (connectionCount >= getDefinition().getMaximumConnectionCount()) { throw new ProxoolException("ConnectionCount is " + connectionCount + ". Maximum connection count of " + getDefinition().getMaximumConnectionCount() + " cannot be exceeded."); } checkSimultaneousBuildThrottle(); connectionsBeingMade++; connectionCount++; id = nextConnectionId++; } ProxyConnection proxyConnection = null; Connection realConnection = null; try { // get a new *real* connection final ConnectionPoolDefinition definition = connectionPool.getDefinition(); realConnection = connectionBuilder.buildConnection(definition); // build a proxy around it //TODO BRE: the connection builder has made a new connection using the information // supplied in the ConnectionPoolDefinition. That's where it got the URL... // The ProxyConnection is passed the ConnectionPoolDefinition as well so it doesn't // need the url in its constructor... String url = definition.getUrl(); proxyConnection = new ProxyConnection(realConnection, id, url, connectionPool, definition, status); try { connectionPool.onBirth(realConnection); } catch (Exception e) { log.error("Problem during onBirth (ignored)", e); } //TODO BRE: the actual pool of connections is maintained by the ConnectionPool. I'm not // very happy with the idea of letting the Prototyper add the newly build connection // into the pool itself. It should rather be the pool that does it, after it got a new // connection from the Prototyper. This would clearly separate the responsibilities: // ConnectionPool maintains the pool and its integrity, the Prototyper creates new // connections when instructed. boolean added = connectionPool.addProxyConnection(proxyConnection); if (log.isDebugEnabled()) { StringBuffer out = new StringBuffer(connectionPool.displayStatistics()); out.append(" - Connection #"); out.append(proxyConnection.getId()); if (getDefinition().isVerbose()) { out.append(" ("); out.append(Integer.toHexString(proxyConnection.hashCode())); out.append(")"); } out.append(" created "); out.append(creator); out.append(" = "); out.append(ConnectionPool.getStatusDescription(proxyConnection.getStatus())); if (getDefinition().isVerbose()) { out.append(" -> "); out.append(getDefinition().getUrl()); out.append(" ("); out.append(Integer.toHexString(proxyConnection.getConnection().hashCode())); out.append(") by thread "); out.append(Thread.currentThread().getName()); } log.debug(out); if (!added) { out = new StringBuffer(connectionPool.displayStatistics()); out.append(" - Connection #"); out.append(proxyConnection.getId()); out.append(" has been discarded immediately because the definition it was built with is out of date"); log.debug(out); } } if (!added) { proxyConnection.reallyClose(); } } catch (SQLException e) { // log.error(displayStatistics() + " - Couldn't initialise connection #" + proxyConnection.getId() + ": " + e); throw e; } catch (RuntimeException e) { if (log.isDebugEnabled()) { log.debug("Prototyping problem", e); } throw e; } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("Prototyping problem", t); } throw new ProxoolException("Unexpected prototyping problem", t); } finally { synchronized (lock) { if (proxyConnection == null) { // If there has been an exception then we won't be using this one and // we need to decrement the counter connectionCount--; } connectionsBeingMade--; } } return proxyConnection; } /** * This needs to be called _everytime_ a connection is removed. */ protected void connectionRemoved() { connectionCount--; } /** * Checks whether we are currently already building too many connections * @throws SQLException if the throttle has been reached */ protected void checkSimultaneousBuildThrottle() throws SQLException { // Check we aren't making too many simultaneously if (connectionsBeingMade > getDefinition().getSimultaneousBuildThrottle()) { throw new SQLException("We are already in the process of making " + connectionsBeingMade + " connections and the number of simultaneous builds has been throttled to " + getDefinition().getSimultaneousBuildThrottle()); } } /** * The total number of connections, including those being built right * now * @return connectionCount; */ public long getConnectionCount() { return connectionCount; } /** * Utility method * @return definition */ private ConnectionPoolDefinitionIF getDefinition() { return connectionPool.getDefinition(); } /** * Cancel all current prototyping */ public void cancel() { cancel = true; } /** * The alias of the pool we are prototyping for * @return alias */ public String getAlias() { return getDefinition().getAlias(); } /** * Give a quick answer to whether we should attempt to build a connection. This can be quicker * if we are massively overloaded rather than cycling through each connection in the pool to * see if it's free * @throws SQLException if it is a waste of time even trying to get a connaction. Just because this method * doesn't throw an exception it doesn't guarantee that one will be available. There is a slight * risk that we might tell the client to give up when a connection could become available in the next few * milliseconds but our policy is to refuse connections quickly when overloaded. */ public void quickRefuse() throws SQLException { if (connectionCount >= getDefinition().getMaximumConnectionCount() && connectionPool.getAvailableConnectionCount() < 1) { throw new SQLException("Couldn't get connection because we are at maximum connection count (" + connectionCount + "/" + getDefinition().getMaximumConnectionCount() + ") and there are none available"); } } } /* Revision history: $Log: Prototyper.java,v $ Revision 1.14 2006/03/23 11:44:57 billhorsman More information when quickly refusing Revision 1.13 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.12 2006/01/16 23:10:41 billhorsman Doh. /Do/ decrement connectionCount if we didn't make one. Revision 1.11 2005/10/02 12:36:30 billhorsman New quickRefuse() method checks whether we are overloaded without checking whole pool for an available connection. Revision 1.10 2005/05/04 16:27:54 billhorsman Check to see whether a new connection was really added to the pool. Revision 1.9 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. Revision 1.7 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.6 2003/09/11 10:44:54 billhorsman Catch throwable not just exception during creation of connection (this will catch ClassNotFoundError too) Revision 1.5 2003/04/10 08:22:33 billhorsman removed some very frequent debug Revision 1.4 2003/03/11 14:51:52 billhorsman more concurrency fixes relating to snapshots Revision 1.3 2003/03/10 23:43:10 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.2 2003/03/10 15:26:47 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/PrototyperController.java0000644000175000017500000001131210730503125031576 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Iterator; /** * Controls the {@link Prototyper prototypers} * @version $Revision: 1.10 $, $Date: 2006/01/18 14:40:01 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class PrototyperController { private static final Log LOG = LogFactory.getLog(PrototyperController.class); private static PrototyperThread prototyperThread; private static boolean keepSweeping; private static final String LOCK = "LOCK"; private static void startPrototyper() { if (prototyperThread == null) { synchronized(LOCK) { if (prototyperThread == null) { prototyperThread = new PrototyperThread("Prototyper"); prototyperThread.start(); } } } } /** * Trigger prototyping immediately. Runs inside a new Thread so * control returns as quick as possible. You should call this whenever * you suspect that building more connections might be a good idea. * @param alias */ protected static void triggerSweep(String alias) { try { // Ensure that we're not in the process of shutting down the pool ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); try { cp.acquirePrimaryReadLock(); cp.getPrototyper().triggerSweep(); } catch (InterruptedException e) { LOG.error("Couldn't acquire primary read lock", e); } finally { cp.releasePrimaryReadLock(); } } catch (ProxoolException e) { if (LOG.isDebugEnabled()) { LOG.debug("Couldn't trigger prototyper triggerSweep for '" + alias + "' - maybe it's just been shutdown"); } } startPrototyper(); try { // If we are currently sweeping this will cause it to loop through // once more keepSweeping = true; // If we aren't already started then this will start a new sweep if (prototyperThread != null) { prototyperThread.doNotify(); } } catch (IllegalMonitorStateException e) { LOG.debug("Hmm", e); if (Thread.activeCount() > 10 && LOG.isInfoEnabled()) { LOG.info("Suspicious thread count of " + Thread.activeCount()); } } catch (IllegalThreadStateException e) { // Totally expected. Should happen all the time. Just means that // we are already sweeping. if (LOG.isDebugEnabled()) { LOG.debug("Ignoring attempt to prototype whilst already prototyping"); } } } public static boolean isKeepSweeping() { return keepSweeping; } public static void sweepStarted() { keepSweeping = false; } /** * Stop all house keeper threads */ protected static void shutdown() { synchronized(LOCK) { if (prototyperThread != null) { LOG.info("Stopping " + prototyperThread.getName() + " thread"); prototyperThread.cancel(); prototyperThread = null; } } } } /* Revision history: $Log: PrototyperController.java,v $ Revision 1.10 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.9 2004/04/05 22:54:57 billhorsman Check if notify thread has been shutdown before triggering it. Revision 1.8 2004/03/26 15:58:56 billhorsman Fixes to ensure that house keeper and prototyper threads finish after shutdown. Revision 1.7 2004/03/25 22:02:15 brenuart First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF. Include some minor refactoring that lead to deprecation of some PrototyperController methods. Revision 1.5 2003/03/10 23:43:11 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.4 2003/03/10 16:28:02 billhorsman removed debug trace Revision 1.3 2003/03/10 15:26:47 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.2 2003/03/06 12:43:32 billhorsman removed paranoid debug Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/PrototyperThread.java0000644000175000017500000000623010730503124030664 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Responsible for running {@link Prototyper#sweep sweep}. There * could be just one of the objects, or more. * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:01 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class PrototyperThread extends Thread { private static final ThreadGroup PROTOTYPER_THREAD_GROUP = new ThreadGroup("PROTOTYPER_THREAD_GROUP"); private static final Log LOG = LogFactory.getLog(PrototyperThread.class); private boolean stop; public PrototyperThread(String name) { super(PROTOTYPER_THREAD_GROUP, name); setDaemon(true); } public void run() { while (!stop) { int sweptCount = 0; while (PrototyperController.isKeepSweeping() && !stop) { PrototyperController.sweepStarted(); ConnectionPool[] cps = ConnectionPoolManager.getInstance().getConnectionPools(); for (int i = 0; i < cps.length && !stop; i++) { Prototyper p = cps[i].getPrototyper(); try { cps[i].acquirePrimaryReadLock(); if (cps[i].isConnectionPoolUp() && p.isSweepNeeded()) { p.sweep(); sweptCount++; } } catch (InterruptedException e) { LOG.error("Couldn't acquire primary read lock", e); } finally { cps[i].releasePrimaryReadLock(); } } } // if (LOG.isDebugEnabled()) { // LOG.debug("Swept " + sweptCount + " pools"); // } doWait(); } } protected void cancel() { stop = true; doNotify(); } private synchronized void doWait() { try { wait(); } catch (InterruptedException e) { LOG.debug("Expected interruption of sleep"); } } protected synchronized void doNotify() { notifyAll(); } } /* Revision history: $Log: PrototyperThread.java,v $ Revision 1.6 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2004/03/26 15:58:56 billhorsman Fixes to ensure that house keeper and prototyper threads finish after shutdown. Revision 1.4 2003/04/10 08:23:55 billhorsman removed very frequent debug Revision 1.3 2003/03/10 23:43:12 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.2 2003/03/10 15:26:48 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxoolConstants.java0000644000175000017500000003242510730503125030712 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; /** * All constants here please. * * @version $Revision: 1.21 $, $Date: 2004/06/02 20:39:17 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface ProxoolConstants { public final String PROXOOL = "proxool"; /** * The namespace uri associated with namepace aware Proxool xml configurations.
    * Value: The latest version is available at http://proxool.sourceforge.net/xml-namespace */ public final String PROXOOL_XML_NAMESPACE_URI = "The latest version is available at http://proxool.sourceforge.net/xml-namespace"; public final String ALIAS_DELIMITER = "."; public final String PROPERTY_PREFIX = PROXOOL + "."; public final String URL_DELIMITER = ":"; /** Standard JDBC property */ public final String USER_PROPERTY = "user"; /** Standard JDBC property */ public final String PASSWORD_PROPERTY = "password"; /** Used to build up URL */ public final String ALIAS_PROPERTY = PROPERTY_PREFIX + "alias"; /** Instead of defining the driver in the url you can also use this property */ public final String DELEGATE_DRIVER = "driver"; /** @see ProxoolDriver#getPropertyInfo */ public final String DELEGATE_DRIVER_PROPERTY = PROPERTY_PREFIX + DELEGATE_DRIVER; /** @see #HOUSE_KEEPING_SLEEP_TIME_PROPERTY */ public final String DELEGATE_URL = "url"; /** @see ProxoolDriver#getPropertyInfo */ public final String DELEGATE_URL_PROPERTY = PROPERTY_PREFIX + DELEGATE_URL; /** @see #HOUSE_KEEPING_SLEEP_TIME_PROPERTY */ public final String HOUSE_KEEPING_SLEEP_TIME = "house-keeping-sleep-time"; /** @see ProxoolDriver#getPropertyInfo */ public final String HOUSE_KEEPING_SLEEP_TIME_PROPERTY = PROPERTY_PREFIX + HOUSE_KEEPING_SLEEP_TIME; /** @see #HOUSE_KEEPING_TEST_SQL_PROPERTY */ public final String HOUSE_KEEPING_TEST_SQL = "house-keeping-test-sql"; /** @see ProxoolDriver#getPropertyInfo */ public final String HOUSE_KEEPING_TEST_SQL_PROPERTY = PROPERTY_PREFIX + HOUSE_KEEPING_TEST_SQL; /** @see #TEST_BEFORE_USE_PROPERTY */ public final String TEST_BEFORE_USE = "test-before-use"; /** @see ProxoolDriver#getPropertyInfo */ public final String TEST_BEFORE_USE_PROPERTY = PROPERTY_PREFIX + TEST_BEFORE_USE; /** @see #TEST_AFTER_USE_PROPERTY */ public final String TEST_AFTER_USE = "test-after-use"; /** @see ProxoolDriver#getPropertyInfo */ public final String TEST_AFTER_USE_PROPERTY = PROPERTY_PREFIX + TEST_AFTER_USE; /** @see #MAXIMUM_CONNECTION_COUNT_PROPERTY */ public final String MAXIMUM_CONNECTION_COUNT = "maximum-connection-count"; /** @see ProxoolDriver#getPropertyInfo */ public final String MAXIMUM_CONNECTION_COUNT_PROPERTY = PROPERTY_PREFIX + MAXIMUM_CONNECTION_COUNT; /** @see #MAXIMUM_CONNECTION_LIFETIME_PROPERTY */ public final String MAXIMUM_CONNECTION_LIFETIME = "maximum-connection-lifetime"; /** @see ProxoolDriver#getPropertyInfo */ public final String MAXIMUM_CONNECTION_LIFETIME_PROPERTY = PROPERTY_PREFIX + MAXIMUM_CONNECTION_LIFETIME; /** * @deprecated use {@link #SIMULTANEOUS_BUILD_THROTTLE} instead */ public final String MAXIMUM_NEW_CONNECTIONS = "maximum-new-connections"; /** * @deprecated use {@link #SIMULTANEOUS_BUILD_THROTTLE_PROPERTY} instead */ public final String MAXIMUM_NEW_CONNECTIONS_PROPERTY = PROPERTY_PREFIX + MAXIMUM_NEW_CONNECTIONS; /** @see #SIMULTANEOUS_BUILD_THROTTLE_PROPERTY*/ public final String SIMULTANEOUS_BUILD_THROTTLE = "simultaneous-build-throttle"; /** @see ProxoolDriver#getPropertyInfo */ public final String SIMULTANEOUS_BUILD_THROTTLE_PROPERTY = PROPERTY_PREFIX + SIMULTANEOUS_BUILD_THROTTLE; /** @see #MINIMUM_CONNECTION_COUNT_PROPERTY */ public final String MINIMUM_CONNECTION_COUNT = "minimum-connection-count"; /** @see ProxoolDriver#getPropertyInfo */ public final String MINIMUM_CONNECTION_COUNT_PROPERTY = PROPERTY_PREFIX + MINIMUM_CONNECTION_COUNT; /** @see #PROTOTYPE_COUNT_PROPERTY */ public final String PROTOTYPE_COUNT = "prototype-count"; /** @see ProxoolDriver#getPropertyInfo */ public final String PROTOTYPE_COUNT_PROPERTY = PROPERTY_PREFIX + PROTOTYPE_COUNT; /** @see #RECENTLY_STARTED_THRESHOLD_PROPERTY */ public final String RECENTLY_STARTED_THRESHOLD = "recently-started-threshold"; /** @see ProxoolDriver#getPropertyInfo */ public final String RECENTLY_STARTED_THRESHOLD_PROPERTY = PROPERTY_PREFIX + RECENTLY_STARTED_THRESHOLD; /** @see #OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY */ public final String OVERLOAD_WITHOUT_REFUSAL_LIFETIME = "overload-without-refusal-lifetime"; /** @see ProxoolDriver#getPropertyInfo */ public final String OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY = PROPERTY_PREFIX + OVERLOAD_WITHOUT_REFUSAL_LIFETIME; /** @see #MAXIMUM_ACTIVE_TIME_PROPERTY */ public final String MAXIMUM_ACTIVE_TIME = "maximum-active-time"; /** @see ProxoolDriver#getPropertyInfo */ public final String MAXIMUM_ACTIVE_TIME_PROPERTY = PROPERTY_PREFIX + MAXIMUM_ACTIVE_TIME; /** @see #INJECTABLE_CONNECTION_INTERFACE_NAME_PROPERTY */ public final String INJECTABLE_CONNECTION_INTERFACE_NAME = "injectable-connection-interface"; /** @see ProxoolDriver#getPropertyInfo */ public final String INJECTABLE_CONNECTION_INTERFACE_NAME_PROPERTY = PROPERTY_PREFIX + INJECTABLE_CONNECTION_INTERFACE_NAME; /** @see #INJECTABLE_STATEMENT_INTERFACE_NAME_PROPERTY */ public final String INJECTABLE_STATEMENT_INTERFACE_NAME = "injectable-statement-interface"; /** @see ProxoolDriver#getPropertyInfo */ public final String INJECTABLE_STATEMENT_INTERFACE_NAME_PROPERTY = PROPERTY_PREFIX + INJECTABLE_STATEMENT_INTERFACE_NAME; /** @see #INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME_PROPERTY */ public final String INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME = "injectable-prepared-statement-interface"; /** @see ProxoolDriver#getPropertyInfo */ public final String INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME_PROPERTY = PROPERTY_PREFIX + INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME; /** @see #INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME_PROPERTY */ public final String INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME = "injectable-callable-statement-interface"; /** @see ProxoolDriver#getPropertyInfo */ public final String INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME_PROPERTY = PROPERTY_PREFIX + INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME; /** * @deprecated use {@link #VERBOSE_PROPERTY verbose} instead. */ public final String DEBUG_LEVEL_PROPERTY = PROPERTY_PREFIX + "debug-level"; /** @see #VERBOSE_PROPERTY */ public final String VERBOSE = "verbose"; /** @see ProxoolDriver#getPropertyInfo */ public final String VERBOSE_PROPERTY = PROPERTY_PREFIX + VERBOSE; /** @see #TRACE_PROPERTY */ public final String TRACE = "trace"; /** @see ProxoolDriver#getPropertyInfo */ public final String TRACE_PROPERTY = PROPERTY_PREFIX + TRACE; /** @see #FATAL_SQL_EXCEPTION_PROPERTY **/ public final String FATAL_SQL_EXCEPTION = "fatal-sql-exception"; /** @see ProxoolDriver#getPropertyInfo */ public final String FATAL_SQL_EXCEPTION_PROPERTY = PROPERTY_PREFIX + FATAL_SQL_EXCEPTION; /** @see #FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY**/ public final String FATAL_SQL_EXCEPTION_WRAPPER_CLASS = "fatal-sql-exception-wrapper-class"; /** @see ProxoolDriver#getPropertyInfo */ public final String FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY = PROPERTY_PREFIX + FATAL_SQL_EXCEPTION_WRAPPER_CLASS; public static final String STATISTICS = "statistics"; /** @see ProxoolDriver#getPropertyInfo */ public final String STATISTICS_PROPERTY = PROPERTY_PREFIX + STATISTICS; public static final String STATISTICS_LOG_LEVEL = "statistics-log-level"; /** @see ProxoolDriver#getPropertyInfo */ public final String STATISTICS_LOG_LEVEL_PROPERTY = PROPERTY_PREFIX + STATISTICS_LOG_LEVEL; public static final String JNDI_NAME = "jndi-name"; /** Prefix for generic JNDI properties. */ public static final String JNDI_PROPERTY_PREFIX = "jndi-"; /** @see ProxoolDriver#getPropertyInfo */ public final String JNDI_NAME_PROPERTY = PROPERTY_PREFIX + JNDI_NAME; // End JNDI public static final String STATISTICS_LOG_LEVEL_TRACE = "TRACE"; public static final String STATISTICS_LOG_LEVEL_DEBUG = "DEBUG"; public static final String STATISTICS_LOG_LEVEL_INFO = "INFO"; /** * Element name for the container of properties passed directlry to the delegate driver. */ public static final String DRIVER_PROPERTIES = "driver-properties"; /** * Configuration attribute used to indicate that a pool should be registered with JMX. */ public static final String JMX = "jmx"; /** * "proxool." prefixed version of {@link #JMX}. */ public final String JMX_PROPERTY = PROPERTY_PREFIX + JMX; /** * Configuration attribute for a list of jmx agent ids to register a * {@link org.logicalcobwebs.proxool.admin.jmx.ConnectionPoolMBean} to. * The list is comma separated. */ public static final String JMX_AGENT_ID = "jmx-agent-id"; /** * "proxool." prefixed version of {@link #JMX_AGENT_ID}. */ public final String JMX_AGENT_PROPERTY = PROPERTY_PREFIX + JMX_AGENT_ID; /** * Un-prefixed propety name for the Proxool alias configuration property. Value: alias */ public final String ALIAS = "alias"; /** * Un-prefixed propety name for the Proxool driver class configuration property. Value: driver-class */ public final String DRIVER_CLASS = "driver-class"; /** * Prefixed propety name for the Proxool driver class configuration property. Value: proxool.driver-class */ public final String DRIVER_CLASS_PROPERTY = PROPERTY_PREFIX + DRIVER_CLASS;; /** * Un-prefixed propety name for the Proxool driver url configuration property. Value: driver-url */ public final String DRIVER_URL = "driver-url"; /** * Prefixed propety name for the Proxool driver url configuration property. Value: proxool.driver-url */ public final String DRIVER_URL_PROPERTY = PROPERTY_PREFIX + DRIVER_URL; } /* Revision history: $Log: ProxoolConstants.java,v $ Revision 1.21 2004/06/02 20:39:17 billhorsman New injectable interface constants Revision 1.20 2004/03/15 02:43:47 chr32 Removed explicit JNDI properties. Going for a generic approach instead. Added constant for JNDI properties prefix. Revision 1.19 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.18 2003/09/29 17:48:21 billhorsman New fatal-sql-exception-wrapper-class allows you to define what exception is used as a wrapper. This means that you can make it a RuntimeException if you need to. Revision 1.17 2003/09/05 17:00:42 billhorsman New wrap-fatal-sql-exceptions property. Revision 1.16 2003/07/23 06:54:48 billhorsman draft JNDI changes (shouldn't effect normal operation) Revision 1.15 2003/03/05 23:28:56 billhorsman deprecated maximum-new-connections property in favour of more descriptive simultaneous-build-throttle Revision 1.14 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.13 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.12 2003/02/24 18:02:24 chr32 Added JMX related constants. Revision 1.11 2003/02/24 01:16:15 chr32 Added constant for "driver-properties" property. Revision 1.10 2003/02/06 15:41:17 billhorsman add statistics-log-level Revision 1.9 2003/01/30 17:22:03 billhorsman new statistics property Revision 1.8 2003/01/23 10:41:05 billhorsman changed use of pool-name to alias for consistency Revision 1.7 2002/12/26 11:32:22 billhorsman Moved ALIAS, DRIVER_URL and DRIVER_CLASS constants from XMLConfgiurator to ProxoolConstants. Revision 1.6 2002/12/15 19:22:51 chr32 Added constant for proxool xml namespace. Revision 1.5 2002/12/11 01:47:12 billhorsman extracted property names without proxool. prefix for use by XMLConfigurators. Revision 1.4 2002/11/09 15:50:49 billhorsman new trace constant Revision 1.3 2002/10/27 13:29:38 billhorsman deprecated debug-level in favour of verbose Revision 1.2 2002/10/25 15:59:32 billhorsman made non-public where possible Revision 1.1.1.1 2002/09/13 08:13:06 billhorsman new Revision 1.3 2002/08/24 19:57:15 billhorsman checkstyle changes Revision 1.2 2002/07/12 23:03:22 billhorsman added doc headers Revision 1.7 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.6 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.5 2002/07/02 08:27:47 billhorsman bug fix when settiong definition, displayStatistics now available to ProxoolFacade, prototyper no longer attempts to make connections when maximum is reached Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxoolDataSource.java0000644000175000017500000005761310730605700031000 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.naming.spi.ObjectFactory; import javax.naming.Name; import javax.naming.Context; import javax.naming.Reference; import javax.naming.RefAddr; import javax.naming.StringRefAddr; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; import java.util.Hashtable; import java.util.Enumeration; import java.util.Properties; import java.util.StringTokenizer; import java.io.PrintWriter; /** * The Proxool DataSource implementation. Supports three modes of configuration: *
      *
    • pre-configured
    • *
    • bean-configured
    • *
    • factory-configured
    • *
    * * TODO - expand * @version $Revision: 1.11 $, $Date: 2007/12/14 23:03:28 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class ProxoolDataSource implements DataSource, ObjectFactory { private static final Log LOG = LogFactory.getLog(ProxoolDataSource.class); private int loginTimeout; private PrintWriter logWriter; private String alias; private String driver; private String fatalSqlExceptionWrapperClass; private long houseKeepingSleepTime; private String houseKeepingTestSql; private long maximumActiveTime; private int maximumConnectionCount; private long maximumConnectionLifetime;; private int minimumConnectionCount; private long overloadWithoutRefusalLifetime; private String password; private int prototypeCount; private long recentlyStartedThreshold; private int simultaneousBuildThrottle; private String statistics; private String statisticsLogLevel; private boolean trace; private String driverUrl; private String user; private boolean verbose; private boolean jmx; private String jmxAgentId; private boolean testBeforeUse; private boolean testAfterUse; private Properties delegateProperties = new Properties(); /** * A String of all the fatalSqlExceptions delimited by * {@link ConnectionPoolDefinitionIF#FATAL_SQL_EXCEPTIONS_DELIMITER} */ private String fatalSqlExceptionsAsString; public ProxoolDataSource() { reset(); } public ProxoolDataSource (String alias) { this.alias = alias; } /** * @see javax.sql.DataSource#getConnection() */ public Connection getConnection() throws SQLException { ConnectionPool cp = null; try { if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) { registerPool(); } cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); return cp.getConnection(); } catch (ProxoolException e) { LOG.error("Problem getting connection", e); throw new SQLException(e.toString()); } } /** * Register a pool using the properties of this data source. (Check that it * exists first) * @throws ProxoolException if the pool couldn't be registered */ private synchronized void registerPool() throws ProxoolException { if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) { ConnectionPoolDefinition cpd = new ConnectionPoolDefinition(); cpd.setAlias(getAlias()); cpd.setDriver(getDriver()); cpd.setFatalSqlExceptionsAsString(getFatalSqlExceptionsAsString()); cpd.setFatalSqlExceptionWrapper(getFatalSqlExceptionWrapperClass()); cpd.setHouseKeepingSleepTime(getHouseKeepingSleepTime()); cpd.setHouseKeepingTestSql(getHouseKeepingTestSql()); cpd.setMaximumActiveTime(getMaximumActiveTime()); cpd.setMaximumConnectionCount(getMaximumConnectionCount()); cpd.setMaximumConnectionLifetime(getMaximumConnectionLifetime()); cpd.setMinimumConnectionCount(getMinimumConnectionCount()); cpd.setOverloadWithoutRefusalLifetime(getOverloadWithoutRefusalLifetime()); cpd.setPrototypeCount(getPrototypeCount()); cpd.setRecentlyStartedThreshold(getRecentlyStartedThreshold()); cpd.setSimultaneousBuildThrottle(getSimultaneousBuildThrottle()); cpd.setStatistics(getStatistics()); cpd.setStatisticsLogLevel(getStatisticsLogLevel()); cpd.setTrace(isTrace()); cpd.setUrl(getDriverUrl()); cpd.setVerbose(isVerbose()); cpd.setJmx(isJmx()); cpd.setJmxAgentId(getJmxAgentId()); cpd.setTestAfterUse(isTestAfterUse()); cpd.setTestBeforeUse(isTestBeforeUse()); cpd.setDelegateProperties(delegateProperties); // We must setUser and setPassword *after* setDelegateProperties // otherwise the values will be overwritten. Credit Bulent Erdemir. cpd.setUser(getUser()); cpd.setPassword(getPassword()); ProxoolFacade.registerConnectionPool(cpd); } } public Object getObjectInstance(Object refObject, Name name, Context context, Hashtable hashtable) throws Exception { // we only handle references if (!(refObject instanceof Reference)) { return null; } Reference reference = (Reference) refObject; /* Removed because JNDI implementations can not be trusted to implement reference.getFactoryClassName() correctly. // check if this is relevant for us if (!ProxoolDataSource.class.getName().equals(reference.getFactoryClassName())) { return null; } */ // check if we've allready parsed the properties. if (!ConnectionPoolManager.getInstance().isPoolExists(reference.get(ProxoolConstants.ALIAS_PROPERTY).toString())) { populatePropertiesFromReference(reference); } return this; } /** * @see ConnectionPoolDefinitionIF#getAlias */ public String getAlias() { return alias; } /** * @see ConnectionPoolDefinitionIF#getAlias */ public void setAlias(String alias) { this.alias = alias; } /** * @see ConnectionPoolDefinitionIF#getUrl */ public String getDriverUrl() { return driverUrl; } /** * @see ConnectionPoolDefinitionIF#getUrl */ public void setDriverUrl(String url) { this.driverUrl = url; } /** * @see ConnectionPoolDefinitionIF#getDriver */ public String getDriver() { return driver; } /** * @see ConnectionPoolDefinitionIF#getDriver */ public void setDriver(String driver) { this.driver = driver; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionLifetime */ public long getMaximumConnectionLifetime() { return maximumConnectionLifetime; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionLifetime */ public void setMaximumConnectionLifetime(int maximumConnectionLifetime) { this.maximumConnectionLifetime = maximumConnectionLifetime; } /** * @see ConnectionPoolDefinitionIF#getPrototypeCount */ public int getPrototypeCount() { return prototypeCount; } /** * @see ConnectionPoolDefinitionIF#getPrototypeCount */ public void setPrototypeCount(int prototypeCount) { this.prototypeCount = prototypeCount; } /** * @see ConnectionPoolDefinitionIF#getMinimumConnectionCount */ public int getMinimumConnectionCount() { return minimumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getMinimumConnectionCount */ public void setMinimumConnectionCount(int minimumConnectionCount) { this.minimumConnectionCount = minimumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionCount */ public int getMaximumConnectionCount() { return maximumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getMaximumConnectionCount */ public void setMaximumConnectionCount(int maximumConnectionCount) { this.maximumConnectionCount = maximumConnectionCount; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime */ public long getHouseKeepingSleepTime() { return houseKeepingSleepTime; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingSleepTime */ public void setHouseKeepingSleepTime(int houseKeepingSleepTime) { this.houseKeepingSleepTime = houseKeepingSleepTime; } /** * @see ConnectionPoolDefinitionIF#getSimultaneousBuildThrottle */ public int getSimultaneousBuildThrottle() { return simultaneousBuildThrottle; } /** * @see ConnectionPoolDefinitionIF#getSimultaneousBuildThrottle */ public void setSimultaneousBuildThrottle(int simultaneousBuildThrottle) { this.simultaneousBuildThrottle = simultaneousBuildThrottle; } /** * @see ConnectionPoolDefinitionIF#getRecentlyStartedThreshold */ public long getRecentlyStartedThreshold() { return recentlyStartedThreshold; } /** * @see ConnectionPoolDefinitionIF#getRecentlyStartedThreshold */ public void setRecentlyStartedThreshold(int recentlyStartedThreshold) { this.recentlyStartedThreshold = recentlyStartedThreshold; } /** * @see ConnectionPoolDefinitionIF#getOverloadWithoutRefusalLifetime */ public long getOverloadWithoutRefusalLifetime() { return overloadWithoutRefusalLifetime; } /** * @see ConnectionPoolDefinitionIF#getOverloadWithoutRefusalLifetime */ public void setOverloadWithoutRefusalLifetime(int overloadWithoutRefusalLifetime) { this.overloadWithoutRefusalLifetime = overloadWithoutRefusalLifetime; } /** * @see ConnectionPoolDefinitionIF#getMaximumActiveTime */ public long getMaximumActiveTime() { return maximumActiveTime; } /** * @see ConnectionPoolDefinitionIF#getMaximumActiveTime */ public void setMaximumActiveTime(long maximumActiveTime) { this.maximumActiveTime = maximumActiveTime; } /** * @see ConnectionPoolDefinitionIF#isVerbose */ public boolean isVerbose() { return verbose; } /** * @see ConnectionPoolDefinitionIF#isVerbose */ public void setVerbose(boolean verbose) { this.verbose = verbose; } /** * @see ConnectionPoolDefinitionIF#isTrace */ public boolean isTrace() { return trace; } /** * @see ConnectionPoolDefinitionIF#isTrace */ public void setTrace(boolean trace) { this.trace = trace; } /** * @see ConnectionPoolDefinitionIF#getStatistics */ public String getStatistics() { return statistics; } /** * @see ConnectionPoolDefinitionIF#getStatistics */ public void setStatistics(String statistics) { this.statistics = statistics; } /** * @see ConnectionPoolDefinitionIF#getStatisticsLogLevel */ public String getStatisticsLogLevel() { return statisticsLogLevel; } /** * @see ConnectionPoolDefinitionIF#getStatisticsLogLevel */ public void setStatisticsLogLevel(String statisticsLogLevel) { this.statisticsLogLevel = statisticsLogLevel; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptions */ public String getFatalSqlExceptionsAsString() { return fatalSqlExceptionsAsString; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptions */ public void setFatalSqlExceptionsAsString(String fatalSqlExceptionsAsString) { this.fatalSqlExceptionsAsString = fatalSqlExceptionsAsString; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptionWrapper() */ public String getFatalSqlExceptionWrapperClass() { return fatalSqlExceptionWrapperClass; } /** * @see ConnectionPoolDefinitionIF#getFatalSqlExceptionWrapper() */ public void setFatalSqlExceptionWrapperClass(String fatalSqlExceptionWrapperClass) { this.fatalSqlExceptionWrapperClass = fatalSqlExceptionWrapperClass; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingTestSql */ public String getHouseKeepingTestSql() { return houseKeepingTestSql; } /** * @see ConnectionPoolDefinitionIF#getHouseKeepingTestSql */ public void setHouseKeepingTestSql(String houseKeepingTestSql) { this.houseKeepingTestSql = houseKeepingTestSql; } /** * @see ConnectionPoolDefinitionIF#getUser */ public String getUser() { return user; } /** * @see ConnectionPoolDefinitionIF#getUser */ public void setUser(String user) { this.user = user; } /** * @see ConnectionPoolDefinitionIF#getPassword */ public String getPassword() { return password; } /** * @see ConnectionPoolDefinitionIF#getPassword */ public void setPassword(String password) { this.password = password; } /** * @see ConnectionPoolDefinitionIF#isJmx() */ public boolean isJmx() { return jmx; } /** * @see ConnectionPoolDefinitionIF#isJmx() */ public void setJmx(boolean jmx) { this.jmx = jmx; } /** * @see ConnectionPoolDefinitionIF#getJmxAgentId() */ public String getJmxAgentId() { return jmxAgentId; } /** * @see ConnectionPoolDefinitionIF#getJmxAgentId() */ public void setJmxAgentId(String jmxAgentId) { this.jmxAgentId = jmxAgentId; } /** * @see ConnectionPoolDefinitionIF#isTestBeforeUse */ public boolean isTestBeforeUse() { return testBeforeUse; } /** * @see ConnectionPoolDefinitionIF#isTestBeforeUse */ public void setTestBeforeUse(boolean testBeforeUse) { this.testBeforeUse = testBeforeUse; } /** * @see ConnectionPoolDefinitionIF#isTestAfterUse */ public boolean isTestAfterUse() { return testAfterUse; } /** * @see ConnectionPoolDefinitionIF#isTestAfterUse */ public void setTestAfterUse(boolean testAfterUse) { this.testAfterUse = testAfterUse; } /** * Set any property that should be handed to the delegate driver. * E.g. foo=1,bar=true * @param properties a comma delimited list of name=value pairs * @see ConnectionPoolDefinitionIF#getDelegateProperties() */ public void setDelegateProperties(String properties) { StringTokenizer stOuter = new StringTokenizer(properties, ","); while (stOuter.hasMoreTokens()) { StringTokenizer stInner = new StringTokenizer(stOuter.nextToken(), "="); if (stInner.countTokens() == 1) { // Allow blank string to be a valid value delegateProperties.put(stInner.nextToken().trim(), ""); } else if (stInner.countTokens() == 2) { delegateProperties.put(stInner.nextToken().trim(), stInner.nextToken().trim()); } else { throw new IllegalArgumentException("Unexpected delegateProperties value: '" + properties + "'. Expected 'name=value'"); } } } private void populatePropertiesFromReference(Reference reference) { RefAddr property = reference.get(ProxoolConstants.ALIAS_PROPERTY); if (property != null) { setAlias(property.getContent().toString()); } property = reference.get(ProxoolConstants.DRIVER_CLASS_PROPERTY); if (property != null) { setDriver(property.getContent().toString()); } property = reference.get(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY); if (property != null) { setFatalSqlExceptionWrapperClass(property.getContent().toString()); } property = reference.get(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY); if (property != null) { setHouseKeepingSleepTime(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY); if (property != null) { setHouseKeepingTestSql(property.getContent().toString()); } property = reference.get(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY); if (property != null) { setMaximumConnectionCount(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME_PROPERTY); if (property != null) { setMaximumConnectionLifetime(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY); if (property != null) { setMaximumActiveTime(Long.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY); if (property != null) { setMinimumConnectionCount(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY); if (property != null) { setOverloadWithoutRefusalLifetime(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.PASSWORD_PROPERTY); if (property != null) { setPassword(property.getContent().toString()); } property = reference.get(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY); if (property != null) { setPrototypeCount(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.RECENTLY_STARTED_THRESHOLD_PROPERTY); if (property != null) { setRecentlyStartedThreshold(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY); if (property != null) { setSimultaneousBuildThrottle(Integer.valueOf(property.getContent().toString()).intValue()); } property = reference.get(ProxoolConstants.STATISTICS_PROPERTY); if (property != null) { setStatistics(property.getContent().toString()); } property = reference.get(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY); if (property != null) { setStatisticsLogLevel(property.getContent().toString()); } property = reference.get(ProxoolConstants.TRACE_PROPERTY); if (property != null) { setTrace("true".equalsIgnoreCase(property.getContent().toString())); } property = reference.get(ProxoolConstants.DRIVER_URL_PROPERTY); if (property != null) { setDriverUrl(property.getContent().toString()); } property = reference.get(ProxoolConstants.USER_PROPERTY); if (property != null) { setUser(property.getContent().toString()); } property = reference.get(ProxoolConstants.VERBOSE_PROPERTY); if (property != null) { setVerbose("true".equalsIgnoreCase(property.getContent().toString())); } property = reference.get(ProxoolConstants.JMX_PROPERTY); if (property != null) { setJmx("true".equalsIgnoreCase(property.getContent().toString())); } property = reference.get(ProxoolConstants.JMX_AGENT_PROPERTY); if (property != null) { setJmxAgentId(property.getContent().toString()); } property = reference.get(ProxoolConstants.TEST_BEFORE_USE_PROPERTY); if (property != null) { setTestBeforeUse("true".equalsIgnoreCase(property.getContent().toString())); } property = reference.get(ProxoolConstants.TEST_AFTER_USE_PROPERTY); if (property != null) { setTestAfterUse("true".equalsIgnoreCase(property.getContent().toString())); } // Pick up any properties that we don't recognise Enumeration e = reference.getAll(); while (e.hasMoreElements()) { StringRefAddr stringRefAddr = (StringRefAddr) e.nextElement(); String name = stringRefAddr.getType(); String content = stringRefAddr.getContent().toString(); if (name.indexOf(ProxoolConstants.PROPERTY_PREFIX) != 0) { delegateProperties.put(name, content); } } } /** * Reset all properties to their default values */ private void reset() { driverUrl = null; driver = null; maximumConnectionLifetime = ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_CONNECTION_LIFETIME; prototypeCount = ConnectionPoolDefinitionIF.DEFAULT_PROTOTYPE_COUNT; minimumConnectionCount = ConnectionPoolDefinitionIF.DEFAULT_MINIMUM_CONNECTION_COUNT; maximumConnectionCount = ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_CONNECTION_COUNT; houseKeepingSleepTime = ConnectionPoolDefinitionIF.DEFAULT_HOUSE_KEEPING_SLEEP_TIME; houseKeepingTestSql = null; simultaneousBuildThrottle = ConnectionPoolDefinitionIF.DEFAULT_SIMULTANEOUS_BUILD_THROTTLE; recentlyStartedThreshold = ConnectionPoolDefinitionIF.DEFAULT_RECENTLY_STARTED_THRESHOLD; overloadWithoutRefusalLifetime = ConnectionPoolDefinitionIF.DEFAULT_OVERLOAD_WITHOUT_REFUSAL_THRESHOLD; maximumActiveTime = ConnectionPoolDefinitionIF.DEFAULT_MAXIMUM_ACTIVE_TIME; verbose = false; trace = false; statistics = null; statisticsLogLevel = null; delegateProperties.clear(); } public PrintWriter getLogWriter() throws SQLException { return this.logWriter; } public int getLoginTimeout() throws SQLException { return this.loginTimeout; } public void setLogWriter(PrintWriter logWriter) throws SQLException { this.logWriter = logWriter; } public void setLoginTimeout(int loginTimeout) throws SQLException { this.loginTimeout = loginTimeout; } public Connection getConnection(String s, String s1) throws SQLException { throw new UnsupportedOperationException("You should configure the username and password " + "within the proxool configuration and just call getConnection() instead."); } } /* Revision history: $Log: ProxoolDataSource.java,v $ Revision 1.11 2007/12/14 23:03:28 billhorsman Use long consistently for maximum_active_time, not int. Revision 1.10 2007/12/14 13:49:39 billhorsman Allow a blank string to be a valid value for a delegate property Revision 1.9 2007/06/19 11:33:35 billhorsman Changed time (millisecond) properties from int to long: maximumConnectionLifetime, houseKeepingSleepTime, recentlyStartedThreshold, overloadWithoutRefusalLifetime, maximumActiveTime Revision 1.8 2007/05/15 23:10:15 billhorsman We must setUser and setPassword *after* setDelegateProperties otherwise the values will be overwritten. Credit Bulent Erdemir (bug 1716955) Revision 1.7 2006/05/23 21:17:55 billhorsman Add in maximum-active-time. Credit to Paolo Di Tommaso. Revision 1.6 2006/03/23 11:51:23 billhorsman Allow for delegate properties Revision 1.5 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.4 2004/08/19 12:28:28 chr32 Removed factory type test. Revision 1.3 2004/03/18 17:16:58 chr32 Added a timy bit of doc. Revision 1.2 2004/03/18 17:07:25 chr32 Now supports all three modes: pre-configured, bean-configured and factory-configured. Revision 1.1 2004/03/15 23:54:25 chr32 Initail Proxool J2EE-managed DataSource. Not quite complete yet. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxoolDriver.java0000644000175000017500000002751010730503125030170 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.resources.ResourceNamesIF; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.Properties; import java.util.ResourceBundle; /** * This is the Proxool implementation of the java.sql.Driver interface. * @version $Revision: 1.28 $, $Date: 2006/01/18 14:40:01 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class ProxoolDriver implements Driver { private static final Log LOG = LogFactory.getLog(ProxoolDriver.class); static { try { DriverManager.registerDriver(new ProxoolDriver()); } catch (SQLException e) { System.out.println(e.toString()); } } private static final ResourceBundle ATTRIBUTE_DESCRIPTIONS_RESOURCE = createAttributeDescriptionsResource (); private static ResourceBundle createAttributeDescriptionsResource () { try { return ResourceBundle.getBundle (ResourceNamesIF.ATTRIBUTE_DESCRIPTIONS); } catch (Exception e) { LOG.error ("Could not find resource " + ResourceNamesIF.ATTRIBUTE_DESCRIPTIONS, e); } return null; } /** * The url should be of the form: *
         *   proxool:delegate-class:delegate-url
         * 
    * or, *
         *   proxool.name:delegate-class:delegate-url
         * 
    * where
    delegate-class
    is the actual Driver that will be used and *
    delegate-url
    is the url that will be based to that Driver * * By defining
    name
    you are able to define multiple connection pools * even if the delegate url is the same. The entire url (including the proxool.name) is * used to uniquely identify this pool. * */ public Connection connect(String url, Properties info) throws SQLException { if (!url.startsWith("proxool")) { return null; } ConnectionPool cp = null; try { String alias = ProxoolFacade.getAlias(url); if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) { ProxoolFacade.registerConnectionPool(url, info, false); cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); } else if (info != null && info.size() > 0) { // Perhaps we should be redefining the definition? cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); ConnectionPoolDefinition cpd = cp.getDefinition(); if (!cpd.isEqual(url, info)) { cpd.redefine(url, info); } } else { cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); } return cp.getConnection(); } catch (SQLException e) { // We don't log exceptions. Leave that up to the client. // LOG.error("Problem", e); // Check to see if it's fatal. We might need to wrap it up. try { String alias = ProxoolFacade.getAlias(url); cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); if (FatalSqlExceptionHelper.testException(cp.getDefinition(), e)) { FatalSqlExceptionHelper.throwFatalSQLException(cp.getDefinition().getFatalSqlExceptionWrapper(), e); } // This bit isn't reached if throwFatalSQLException() above throws another exception throw e; } catch (ProxoolException e1) { LOG.error("Problem", e); throw new SQLException(e.toString()); } } catch (ProxoolException e) { LOG.error("Problem", e); throw new SQLException(e.toString()); } } /** * @see Driver#acceptsURL */ public boolean acceptsURL(String url) throws SQLException { return (url.startsWith("proxool")); } /** * @see Driver#getPropertyInfo */ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { DriverPropertyInfo[] dpi = new DriverPropertyInfo[18]; ConnectionPool cp = null; try { cp = ConnectionPoolManager.getInstance().getConnectionPool(url); } catch (ProxoolException e) { throw new SQLException(e.toString()); } ConnectionPoolDefinitionIF cpd = cp.getDefinition(); dpi[0] = buildDriverPropertyInfo(ProxoolConstants.DELEGATE_DRIVER_PROPERTY, String.valueOf(cpd.getDriver())); dpi[1] = buildDriverPropertyInfo(ProxoolConstants.DELEGATE_URL_PROPERTY, String.valueOf(cpd.getUrl())); dpi[2] = buildDriverPropertyInfo(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(cpd.getMinimumConnectionCount())); dpi[3] = buildDriverPropertyInfo(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(cpd.getMaximumConnectionCount())); dpi[4] = buildDriverPropertyInfo(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME_PROPERTY, String.valueOf(cpd.getMaximumConnectionLifetime())); dpi[5] = buildDriverPropertyInfo(ProxoolConstants.MAXIMUM_NEW_CONNECTIONS_PROPERTY, String.valueOf(cpd.getMaximumNewConnections())); dpi[6] = buildDriverPropertyInfo(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, String.valueOf(cpd.getPrototypeCount())); dpi[7] = buildDriverPropertyInfo(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, String.valueOf(cpd.getHouseKeepingSleepTime())); dpi[8] = buildDriverPropertyInfo(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, cpd.getHouseKeepingTestSql()); dpi[9] = buildDriverPropertyInfo(ProxoolConstants.RECENTLY_STARTED_THRESHOLD_PROPERTY, String.valueOf(cpd.getRecentlyStartedThreshold())); dpi[10] = buildDriverPropertyInfo(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY, String.valueOf(cpd.getOverloadWithoutRefusalLifetime())); dpi[11] = buildDriverPropertyInfo(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY, String.valueOf(cpd.getMaximumActiveTime())); dpi[12] = buildDriverPropertyInfo(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(cpd.isVerbose())); dpi[13] = buildDriverPropertyInfo(ProxoolConstants.TRACE_PROPERTY, String.valueOf(cpd.isTrace())); dpi[14] = buildDriverPropertyInfo(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, String.valueOf(cpd.getFatalSqlExceptions())); dpi[15] = buildDriverPropertyInfo(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, String.valueOf(cpd.getFatalSqlExceptions())); dpi[16] = buildDriverPropertyInfo(ProxoolConstants.STATISTICS_PROPERTY, String.valueOf(cpd.getStatistics())); dpi[17] = buildDriverPropertyInfo(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, String.valueOf(cpd.getStatisticsLogLevel())); return dpi; } private DriverPropertyInfo buildDriverPropertyInfo(String propertyName, String value) { DriverPropertyInfo dpi = new DriverPropertyInfo(propertyName, ATTRIBUTE_DESCRIPTIONS_RESOURCE.getString (propertyName)); if (value != null) { dpi.value = value; } return dpi; } /** * @see Driver#getMajorVersion */ public int getMajorVersion() { return 1; } /** * @see Driver#getMinorVersion */ public int getMinorVersion() { return 0; } /** * @see Driver#jdbcCompliant */ public boolean jdbcCompliant() { return true; } } /* Revision history: $Log: ProxoolDriver.java,v $ Revision 1.28 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.27 2004/06/02 20:41:13 billhorsman Don't log SQLExceptions. Leave that up to the client. Revision 1.26 2003/10/16 18:53:21 billhorsman When registering a new pool on the fly, indicate that it is implicit (for exception message handling) Revision 1.25 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.24 2003/09/05 16:59:42 billhorsman Added wrap-fatal-sql-exceptions property Revision 1.23 2003/08/15 10:13:24 billhorsman remove finalize() method Revision 1.22 2003/04/19 12:58:40 billhorsman fixed bug where ConfigurationListener's definitionUpdated was getting called too frequently Revision 1.21 2003/03/10 23:43:12 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.20 2003/03/10 15:26:48 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.19 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.18 2003/02/26 23:59:37 billhorsman accept now accepts just proxool not proxool: Revision 1.17 2003/02/26 16:05:52 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.16 2003/02/07 10:12:59 billhorsman changed updatePoolByDriver sig. Revision 1.15 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.14 2003/02/06 15:41:16 billhorsman add statistics-log-level Revision 1.13 2003/01/31 00:28:38 billhorsman updated doc for statistics Revision 1.12 2003/01/30 17:22:01 billhorsman new statistics property Revision 1.11 2003/01/18 15:13:11 billhorsman Signature changes (new ProxoolException thrown) on the ProxoolFacade API. Revision 1.10 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.9 2002/12/11 01:48:41 billhorsman added default values for property info documentation Revision 1.8 2002/12/04 13:19:43 billhorsman draft ConfigurationListenerIF stuff for persistent configuration Revision 1.7 2002/12/03 00:41:56 billhorsman fixed getPropertyInfo() for TRACE property and better explanation of FATAL_SQL_EXCEPTION Revision 1.6 2002/11/09 15:55:42 billhorsman added propertyInfo for verbose Revision 1.5 2002/10/27 13:29:38 billhorsman deprecated debug-level in favour of verbose Revision 1.4 2002/10/23 21:04:36 billhorsman checkstyle fixes (reduced max line width and lenient naming convention Revision 1.3 2002/10/17 15:25:37 billhorsman use the url when updating, not the name Revision 1.2 2002/09/18 13:48:56 billhorsman checkstyle and doc Revision 1.1.1.1 2002/09/13 08:13:09 billhorsman new Revision 1.13 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.12 2002/07/04 09:10:48 billhorsman update definition changes Revision 1.11 2002/07/03 10:16:20 billhorsman autoFlush and configuration for logging Revision 1.10 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.9 2002/07/02 11:14:26 billhorsman added test (andbug fixes) for FileLogger Revision 1.8 2002/07/02 09:05:25 billhorsman All properties now start with "proxool." to avoid possible confusion with delegate driver's properties Revision 1.7 2002/07/02 08:50:33 billhorsman Responsibility for configuring pool is now simplifed and moved to here Revision 1.6 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxoolException.java0000644000175000017500000001552110730503124030671 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.io.PrintStream; import java.io.PrintWriter; /** * Proxool exception class that emulates the behaviour of the new cause * facility in jdk 1.4. It is also known as the chained * exception facility, as the cause can, itself, have a cause, and so on, * leading to a "chain" of exceptions, each caused by another. * *

    A cause can be associated with a throwable in two ways: via a * constructor that takes the cause as an argument, or via the * {@link #initCause(Throwable)} method. New throwable classes that * wish to allow causes to be associated with them should provide constructors * that take a cause and delegate (perhaps indirectly) to one of the * Throwable constructors that takes a cause. * * @version $Revision: 1.2 $, $Date: 2003/03/03 11:11:58 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class ProxoolException extends Exception { /** * The throwable that caused this ProxoolException to get thrown, or null if this * ProxoolException was not caused by another throwable, or if the causative * throwable is unknown. */ private Throwable cause = this; /** * Constructs a new instance with null as its detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. */ public ProxoolException() { super(); } /** * Constructs a new instance with the specified detail message. The * cause is not initialized, and may subsequently be initialized by * a call to {@link #initCause}. * * @param message the detail message. The detail message is saved for * later retrieval by the {@link #getMessage()} method. */ public ProxoolException(String message) { super(message); } /** * Constructs a new instance with the specified detail message and cause. * *

    Note that the detail message associated with * cause is not automatically incorporated in * this throwable's detail message. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public ProxoolException(String message, Throwable cause) { this(message); this.cause = cause; } /** * Constructs a new throwable with the specified cause and a detail * message of (cause==null ? null : cause.toString()) (which * typically contains the class and detail message of cause). * This constructor is useful for throwables that are little more than * wrappers for other throwables. * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public ProxoolException(Throwable cause) { this(cause == null ? null : cause.toString()); this.cause = cause; } /** * Returns the cause of this exception or null if the * cause is nonexistent or unknown. (The cause is the throwable that * caused this exception to get thrown.) * *

    This implementation returns the cause that was supplied via one of * the constructors requiring a Throwable, or that was set after * creation with the {@link #initCause(Throwable)} method. * * @return the cause of this throwable or null if the * cause is nonexistent or unknown. */ public Throwable getCause() { return (cause == this ? null : cause); } /** * Initializes the cause of this exception to the specified value. * (The cause is the throwable that caused this exception to get thrown.) * *

    This method can be called at most once. It is generally called from * within the constructor, or immediately after creating the * throwable. If this throwable was created * with {@link #ProxoolException(Throwable)} or * {@link #ProxoolException(String,Throwable)}, this method cannot be called * even once. * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @return a reference to this ProxoolException instance. */ public synchronized Throwable initCause(Throwable cause) { if (this.cause != this) { throw new IllegalStateException("Can't overwrite cause"); } if (cause == this) { throw new IllegalArgumentException("Self-causation not permitted"); } this.cause = cause; return this; } /** * Prints this ProxoolException and its backtrace to the * standard error stream. * * The backtrace for a ProxoolException with an initialized, non-null cause * should generally include the backtrace for the cause. */ public void printStackTrace() { printStackTrace(System.err); } /** * Prints this ProxoolException and its backtrace to the specified print stream. * * @param stream PrintStream to use for output */ public void printStackTrace(PrintStream stream) { synchronized (stream) { super.printStackTrace(stream); Throwable ourCause = getCause(); if (ourCause != null) { stream.println(); stream.println("Caused by:"); ourCause.printStackTrace(stream); } } } /** * Prints this ProxoolException and its backtrace to the specified * print writer. * * @param writer PrintWriter to use for output */ public void printStackTrace(PrintWriter writer) { synchronized (writer) { super.printStackTrace(writer); Throwable ourCause = getCause(); if (ourCause != null) { writer.println(); writer.println("Caused by:"); ourCause.printStackTrace(writer); } } } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxoolFacade.java0000644000175000017500000013637010622435606030115 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.admin.Admin; import org.logicalcobwebs.proxool.admin.SnapshotIF; import org.logicalcobwebs.proxool.admin.StatisticsIF; import org.logicalcobwebs.proxool.admin.StatisticsListenerIF; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.Statement; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Iterator; import java.util.List; import java.util.ArrayList; /** *

    This provides some nice-to-have features that can't be provided by the * {@link java.sql.Driver} {@link ProxoolDriver implementation} of java.sql.Driver. Like starting up * a pool before you need a connection. And getting statistical information.

    * *

    You need to use this class wisely. It is obviously specfic to proxool so it will * stop you switching to another driver. Consider isolating the code that calls this * class so that you can easily remove it if you have to.

    * * @version $Revision: 1.87 $, $Date: 2007/05/15 23:00:22 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class ProxoolFacade { private static final Log LOG = LogFactory.getLog(ProxoolFacade.class); private static Map configurators = new HashMap(); private static CompositeProxoolListener compositeProxoolListener = new CompositeProxoolListener(); private static boolean versionLogged = false; /** * This is the thread that has been registered with {@link Runtime} as a * shutdownHook. It is removed during shutdown. */ private static Thread shutdownHook; /** * If you setthis to false then it us up to you to call shutdown explicitly * @see #shutdown(String, int) */ private static boolean shutdownHookEnabled = true; /** * Build a ConnectionPool based on this definition and then start it. * @param url defines the delegate driver and delegate url. * @param info the properties used to configure Proxool (and any for the delegate driver too) - optional * @return the alias for this pool (or the full url if no alias is specified) * @throws ProxoolException if anything goes wrong */ public static synchronized String registerConnectionPool(String url, Properties info) throws ProxoolException { return registerConnectionPool(url, info, true); } /** * Build a ConnectionPool based on this definition and then start it. * @param url defines the delegate driver and delegate url. * @param info the properties used to configure Proxool (and any for the delegate driver too) - optional * @param explicitRegister set to true if we are registering a new pool explicitly, or false * if it's just because we are serving a url that we haven't come across before * @return the alias for this pool (or the full url if no alias is specified) * @throws ProxoolException if anything goes wrong */ protected static synchronized String registerConnectionPool(String url, Properties info, boolean explicitRegister) throws ProxoolException { String alias = getAlias(url); if (!versionLogged) { versionLogged = true; LOG.info("Proxool " + Version.getVersion()); } try { Class.forName(ProxoolDriver.class.getName()); } catch (ClassNotFoundException e) { LOG.error("Couldn't load " + ProxoolDriver.class.getName()); } if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) { ConnectionPoolDefinition cpd = new ConnectionPoolDefinition(url, info, explicitRegister); registerConnectionPool(cpd); } else { throw new ProxoolException("Attempt to register duplicate pool called '" + alias + "'"); } return alias; } protected synchronized static void registerConnectionPool(ConnectionPoolDefinition connectionPoolDefinition) throws ProxoolException { // check isPoolExists once more now we are inside synchronized block. if (!ConnectionPoolManager.getInstance().isPoolExists(connectionPoolDefinition.getAlias())) { Properties jndiProperties = extractJndiProperties(connectionPoolDefinition); ConnectionPool connectionPool = ConnectionPoolManager.getInstance().createConnectionPool(connectionPoolDefinition); connectionPool.start(); compositeProxoolListener.onRegistration(connectionPoolDefinition, connectionPoolDefinition.getCompleteInfo()); if (isConfiguredForJMX(connectionPoolDefinition.getCompleteInfo())) { registerForJmx(connectionPoolDefinition.getAlias(), connectionPoolDefinition.getCompleteInfo()); } if (jndiProperties != null) { registerDataSource(connectionPoolDefinition.getAlias(), jndiProperties); } } else { LOG.debug("Ignoring duplicate attempt to register " + connectionPoolDefinition.getAlias() + " pool"); } } /** * With no configurator or properties (using default values) * @see #registerConnectionPool(java.lang.String, java.util.Properties) */ public static void registerConnectionPool(String url) throws ProxoolException { registerConnectionPool(url, null); } /** * Extracts the pool alias from the url: * * proxool.alias:driver:url -> alias * proxool.alias -> alias * * @return the alias defined within the url * @throws ProxoolException if we couldn't find the alias */ protected static String getAlias(String url) throws ProxoolException { String alias = null; final String prefix = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER; // Check that the prefix is there if (url.startsWith(prefix)) { // Check for the alias int endOfPrefix = url.indexOf(ProxoolConstants.URL_DELIMITER); if (endOfPrefix > -1) { alias = url.substring(prefix.length(), endOfPrefix); } else { alias = url.substring(prefix.length()); } } // Check we found it. if (alias == null || alias.length() == 0) { throw new ProxoolException("The URL '" + url + "' is not in the correct form. It should be: 'proxool.alias:driver:url'"); } return alias; } /** * Remove a connection pool. Kills all the connections. Resets everything. * @param finalizer the name of the thread requesting shutdown (for logging) * @param connectionPool the pool to remove * @param delay the time to wait for connections to become inactive before killing it (milliseconds) */ private static void removeConnectionPool(String finalizer, ConnectionPool connectionPool, int delay) { final String alias = connectionPool.getDefinition().getAlias(); if (connectionPool != null) { try { compositeProxoolListener.onShutdown(alias); connectionPool.shutdown(delay, finalizer); } catch (Throwable t) { LOG.error("Problem trying to shutdown '" + alias + "' connection pool", t); } } connectionPool = null; } /** * Remove a connection pool. Kills all the connections. Resets everything. * @param alias the pool to remove * @param delay the time to wait for connections to become inactive before killing it (milliseconds) * @throws ProxoolException if we couldn't find the pool */ public static void removeConnectionPool(String alias, int delay) throws ProxoolException { removeConnectionPool(Thread.currentThread().getName(), ConnectionPoolManager.getInstance().getConnectionPool(alias), delay); } /** * Removes all connection pools. Kills all the connections. Resets everything. * @param delay the time to wait for connections to become inactive before killing it (milliseconds) * @deprecated use the better named {@link #shutdown(int) shutdown()} instead. */ public static void removeAllConnectionPools(int delay) { shutdown(Thread.currentThread().getName(), delay); } /** * Removes all connection pools. Kills all the connections. Resets everything. * Like {@link #shutdown(java.lang.String, int)} but passes the current thread name * and a delay of zero. */ public static void shutdown() { shutdown(Thread.currentThread().getName(), 0); } /** * Removes all connection pools. Kills all the connections. Resets everything. * Like {@link #shutdown(java.lang.String, int)} but passes the current thread name. * @param delay the time to wait for connections to become inactive before killing it (milliseconds) */ public static void shutdown(int delay) { shutdown(Thread.currentThread().getName(), delay); } /** * Removes all connection pools. Kills all the connections. Resets everything. * @param finalizer used to identify who is causing the pools to be removed (helps logging) * @param delay the time to wait for connections to become inactive before killing it (milliseconds) */ protected static void shutdown(String finalizer, int delay) { ConnectionPool[] cps = ConnectionPoolManager.getInstance().getConnectionPools(); for (int i = 0; i < cps.length; i++) { removeConnectionPool(finalizer, cps[i], delay); } // If a shutdown hook was registered then remove it try { if (shutdownHook != null) { ShutdownHook.remove(shutdownHook); } } catch (Throwable t) { if (LOG.isDebugEnabled()) { LOG.debug("Unanticipated error during removal of ShutdownHook. Ignoring it.", t); } } // Stop threads PrototyperController.shutdown(); HouseKeeperController.shutdown(); } /** * If you call this then you'll have to call shutdown explicitly * @see #shutdown(String, int) */ public static void disableShutdownHook() { ProxoolFacade.shutdownHookEnabled = false; } /** * Call this if you change your mind about {@link #disableShutdownHook() disabling} it. * The default behaviour is to have it enabled so unless you have disabled it then * there's nothing to do. */ public static void enableShutdownHook() { ProxoolFacade.shutdownHookEnabled = true; } /** * Whether the {@link ShutdownHook} should do anything. * @see #disableShutdownHook() * @see #enableShutdownHook() * @return true if the shutdown hook should clean up */ public static boolean isShutdownHookEnabled() { return shutdownHookEnabled; } /** * Like {@link #removeConnectionPool(java.lang.String, int)} but uses no delay. (Kills * everything as quickly as possible). * @param alias to identify the pool * @throws ProxoolException if we couldn't find the pool */ public static void removeConnectionPool(String alias) throws ProxoolException { removeConnectionPool(alias, 0); } /** * Get real-time statistical information about how a pool is performing. * @param alias to identify the pool * @return the statistics * @throws ProxoolException if we couldn't find the pool * @deprecated use {@link #getSnapshot} */ public static ConnectionPoolStatisticsIF getConnectionPoolStatistics(String alias) throws ProxoolException { return ConnectionPoolManager.getInstance().getConnectionPool(alias); } /** * Get real-time statistical information about how a pool is performing. * and extract the information piece by piece. * @param alias to identify the pool * @return a horrible string describing the statistics * @throws ProxoolException if we couldn't find the pool * @deprecated use {@link #getSnapshot} */ public static String getConnectionPoolStatisticsDump(String alias) throws ProxoolException { return ConnectionPoolManager.getInstance().getConnectionPool(alias).displayStatistics(); } /** * Get the definition of a pool. * @param alias identifies the pool * @throws ProxoolException if we couldn't find the pool */ public static ConnectionPoolDefinitionIF getConnectionPoolDefinition(String alias) throws ProxoolException { return ConnectionPoolManager.getInstance().getConnectionPool(alias).getDefinition(); } /** * Get details on each connection within the pool. This can tell you which ones are active, how long they have * been active, etc. * @param alias identifies the pool * @return a collection of {@link ConnectionInfoIF ConnectionInfoIFs} * @throws ProxoolException if we couldn't find the pool * @deprecated use {@link #getSnapshot(java.lang.String, boolean) snapshot} instead. */ public static Collection getConnectionInfos(String alias) throws ProxoolException { return ConnectionPoolManager.getInstance().getConnectionPool(alias).getConnectionInfos(); } /** * Kill all connections in a pool. The pool continues to work however, and new connections will be * made as required. * @param alias the pool containing the connection * @param merciful if true will only kill connections that aren't active * @throws ProxoolException if we couldn't find the pool * @deprecated use {@link #killAllConnections(java.lang.String, java.lang.String, boolean) alternative} * to provide better auditing in log */ public static void killAllConnections(String alias, boolean merciful) throws ProxoolException { killAllConnections(alias, "of thread " + Thread.currentThread().getName(), merciful); } /** * Kill all connections in a pool. The pool continues to work however, and new connections will be * made as required. * @param alias the pool containing the connection * @param reason provides audit in log of why connections were killed * @param merciful if true will only kill connections that aren't active * @throws ProxoolException if we couldn't find the pool */ public static void killAllConnections(String alias, String reason, boolean merciful) throws ProxoolException { ConnectionPoolManager.getInstance().getConnectionPool(alias).expireAllConnections(ConnectionListenerIF.MANUAL_EXPIRY, reason, merciful); } /** * Like {@link #killAllConnections} but defaults to merciful. * @param alias to identify the pool * @throws ProxoolException if we couldn't find the pool * @deprecated use {@link #killAllConnections(java.lang.String, java.lang.String) alternative} * to provide better auditing in log */ public static void killAllConnections(String alias) throws ProxoolException { killAllConnections(alias, "of thread " + Thread.currentThread().getName(), MERCIFUL); } /** * Like {@link #killAllConnections} but defaults to merciful. * @param alias to identify the pool * @param reason provides audit in log of why connections were killed * @throws ProxoolException if we couldn't find the pool */ public static void killAllConnections(String alias, String reason) throws ProxoolException { killAllConnections(alias, reason, MERCIFUL); } /** * Kill a single connection * @param alias the pool containing the connection * @param id the id of the specific connection * @param merciful if true will only kill connections that aren't active * @return true if the connection was killed, or false if it couldn't be found. * @throws ProxoolException if we couldn't find the pool */ public static boolean killConnecton(String alias, long id, boolean merciful) throws ProxoolException { // Let's be explicit about what we're doing here boolean forceExpiry = !merciful; return ConnectionPoolManager.getInstance().getConnectionPool(alias).expireConnection(id, forceExpiry); } /** * Kill a single connection * @param connection the connection to kill * @param merciful if true will only kill connections that aren't active * @return true if the connection was killed, or false if it couldn't be found. * @throws ProxoolException if we didn't recognise the connection */ public static boolean killConnecton(Connection connection, boolean merciful) throws ProxoolException { WrappedConnection wrappedConnection = ProxyFactory.getWrappedConnection(connection); if (wrappedConnection != null) { long id = wrappedConnection.getId(); String alias = wrappedConnection.getAlias(); return killConnecton(alias, id, merciful); } else { throw new ProxoolException("Attempt to kill unrecognised exception " + connection); } } /** * Add a listener that gets called everytime a global Proxool event ocours. * @param proxoolListener the listener to add. */ public static void addProxoolListener(ProxoolListenerIF proxoolListener) { compositeProxoolListener.addListener(proxoolListener); } /** * Remove a registered ProxoolListenerIF. * @param proxoolListener the listener to remove. * @return whether the listener was found or removed or not. */ public static boolean removeProxoolListener(ProxoolListenerIF proxoolListener) { return compositeProxoolListener.removeListener(proxoolListener); } /** * @deprecated use {@link #addStateListener(String, StateListenerIF)} instead. */ public static void setStateListener(String alias, StateListenerIF stateListener) throws ProxoolException { addStateListener(alias, stateListener); } /** * Add a listener that monitors the change of state of the pool (quiet, busy, overloaded, or down) * @param alias identifies the pool * @param stateListener the new listener * @throws ProxoolException if we couldn't find the pool */ public static void addStateListener(String alias, StateListenerIF stateListener) throws ProxoolException { ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); cp.addStateListener(stateListener); } /** * Remove a listener that monitors the change of state of the pool (quiet, busy, overloaded, or down) * @param alias identifies the pool * @param stateListener the listener to be removed. * @throws ProxoolException if we couldn't find the pool * @return wether the listnener was found and removed or not. */ public static boolean removeStateListener(String alias, StateListenerIF stateListener) throws ProxoolException { ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); return cp.removeStateListener(stateListener); } /** * @deprecated use {@link #addConnectionListener(String, ConnectionListenerIF)} instead. */ public static void setConnectionListener(String alias, ConnectionListenerIF connectionListener) throws ProxoolException { addConnectionListener(alias, connectionListener); } /** * Add a listener that monitors each time a connection is made or destroyed. * @param alias identifies the pool * @param connectionListener the new listener * @throws ProxoolException if we couldn't find the pool */ public static void addConnectionListener(String alias, ConnectionListenerIF connectionListener) throws ProxoolException { ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); cp.addConnectionListener(connectionListener); } /** * Remove a listener that monitors each time a connection is made or destroyed. * @param alias identifies the pool * @param connectionListener the listener to be removed * @throws ProxoolException if we couldn't find the pool * @return wether the listnener was found and removed or not. */ public static boolean removeConnectionListener(String alias, ConnectionListenerIF connectionListener) throws ProxoolException { ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); return cp.removeConnectionListener(connectionListener); } /** * @deprecated use {@link #addConfigurationListener(String, ConfigurationListenerIF)} instead. */ public static void setConfigurationListener(String alias, ConfigurationListenerIF configurationListener) throws ProxoolException { addConfigurationListener(alias, configurationListener); } /** * Adds a listener that gets called everytime the configuration changes. * @param alias identifies the pool * @param configurationListener the new listener * @throws ProxoolException if we couldn't find the pool */ public static void addConfigurationListener(String alias, ConfigurationListenerIF configurationListener) throws ProxoolException { if (ConnectionPoolManager.getInstance().isPoolExists(alias)) { CompositeConfigurationListener compositeConfigurationListener = (CompositeConfigurationListener) configurators.get(alias); if (compositeConfigurationListener == null) { compositeConfigurationListener = new CompositeConfigurationListener(); configurators.put(alias, compositeConfigurationListener); } compositeConfigurationListener.addListener(configurationListener); } else { throw new ProxoolException(ConnectionPoolManager.getInstance().getKnownPools(alias)); } } /** * Broadcast a configuration change * @param alias identifies the pool * @param connectionPoolDefinition the definition * @param completeInfo all properties * @param changedInfo only changed properties (since the last * time this method was called) */ protected static void definitionUpdated(String alias, ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo) { CompositeConfigurationListener ccl = (CompositeConfigurationListener) configurators.get(alias); if (ccl != null) { ccl.definitionUpdated(connectionPoolDefinition, completeInfo, changedInfo); } } /** * Remove a listener that gets called everytime the configuration changes. * @param alias identifies the pool. * @param configurationListener the listener to be removed. * @throws ProxoolException if we couldn't find the pool * @return wether the listnener was found and removed or not. * */ public static boolean removeConfigurationListener(String alias, ConfigurationListenerIF configurationListener) throws ProxoolException { boolean removed = false; if (ConnectionPoolManager.getInstance().isPoolExists(alias)) { CompositeConfigurationListener compositeConfigurationListener = (CompositeConfigurationListener) configurators.get(alias); if (compositeConfigurationListener != null) { removed = compositeConfigurationListener.removeListener(configurationListener); } } else { throw new ProxoolException(ConnectionPoolManager.getInstance().getKnownPools(alias)); } return removed; } /** * @see #killAllConnections(java.lang.String) */ private static final boolean MERCIFUL = true; /** * Redefine the behaviour of the pool. All existing properties (for Proxool * and the delegate driver are reset to their default) and reapplied * based on the parameters sent here. * * @param url the url that defines the pool (or the abbreviated ""proxool.alias") * @param info the new properties * @see #updateConnectionPool */ public static void redefineConnectionPool(String url, Properties info) throws ProxoolException { String alias = getAlias(url); ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); try { // Clone the old one ConnectionPoolDefinition cpd = (ConnectionPoolDefinition) cp.getDefinition().clone(); cpd.redefine(url, info); cp.setDefinition(cpd); } catch (CloneNotSupportedException e) { throw new ProxoolException("Funny, why couldn't we clone a definition?", e); } } /** * Update the behaviour of the pool. Only properties that are defined here are overwritten. That is, properties * that were defined before but are not mentioned here are retained. * * @param url the url that defines the pool (or the abbreviated ""proxool.alias") * @param info the new properties * @see #redefineConnectionPool */ public static void updateConnectionPool(String url, Properties info) throws ProxoolException { String alias = getAlias(url); ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); try { // Clone the old one ConnectionPoolDefinition cpd = (ConnectionPoolDefinition) cp.getDefinition().clone(); cpd.update(url, info); cp.setDefinition(cpd); } catch (CloneNotSupportedException e) { throw new ProxoolException("Funny, why couldn't we clone a definition?", e); } } protected void finalize() throws Throwable { super.finalize(); LOG.debug("Finalising"); } /** * Returns the driver provided statement that Proxool wraps up before it gives it to you. * @return delegate statement * @deprecated Just cast the statement that you are given into the driver specific one. */ public static Statement getDelegateStatement(Statement statement) throws ProxoolException { try { return ProxyFactory.getDelegateStatement(statement); } catch (IllegalArgumentException e) { throw new ProxoolException("Statement argument is not one provided by Proxool (it's a " + statement.getClass() + ")"); } } /** * Returns the driver provided connection that Proxool wraps up before it gives it to you. * @return delegate connection * @deprecated Just cast the connection that you are given into the driver specific one. */ public static Connection getDelegateConnection(Connection connection) throws ProxoolException { try { return ProxyFactory.getDelegateConnection(connection); } catch (IllegalArgumentException e) { throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); } } /** * Get the connection ID for a connection * @param connection the connection that was served * @return the ID * @throws ProxoolException if the connection wasn't recognised. */ public static long getId(Connection connection) throws ProxoolException { try { return ProxyFactory.getWrappedConnection(connection).getId(); } catch (NullPointerException e) { throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); } catch (IllegalArgumentException e) { throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); } } /** * Get the alias for the connection pool that served a connection * @param connection the connection that was served * @return the alias * @throws ProxoolException if the connection wasn't recognised. */ public static String getAlias(Connection connection) throws ProxoolException { try { return ProxyFactory.getWrappedConnection(connection).getAlias(); } catch (NullPointerException e) { throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); } catch (IllegalArgumentException e) { throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); } } /** * Get a list of all the registered pools * @return an array of aliases * @since Proxool 0.7 */ public static String[] getAliases() { return ConnectionPoolManager.getInstance().getConnectionPoolNames(); } /** * Get a particular set of performance statistics for this pool * @param alias identifies the pool * @param token identifies which set, as defined in the configuration (see {@link ConnectionPoolDefinitionIF#getStatistics definition}) * @return a sample containing the statistics * @throws ProxoolException if we couldn't find the pool */ public static StatisticsIF getStatistics(String alias, String token) throws ProxoolException { return ConnectionPoolManager.getInstance().getConnectionPool(alias).getAdmin().getStatistics(token); } /** * Get all the lastest performance statistics for this pool * @param alias identifies the pool * @return a sample containing the statistics, or a zero length array if there none * @throws ProxoolException if we couldn't find the pool */ public static StatisticsIF[] getStatistics(String alias) throws ProxoolException { final Admin monitor = ConnectionPoolManager.getInstance().getConnectionPool(alias).getAdmin(); if (monitor != null) { return monitor.getStatistics(); } else { return new StatisticsIF[0]; } } /** * Add a listener that receives statistics as they are produced * @param statisticsListener the new listener * @throws ProxoolException if the pool couldn't be found */ public static void addStatisticsListener(String alias, StatisticsListenerIF statisticsListener) throws ProxoolException { // TODO investigate what happens if we add a statistics monitor after we register a listener final Admin monitor = ConnectionPoolManager.getInstance().getConnectionPool(alias).getAdmin(); if (monitor != null) { monitor.addStatisticsListener(statisticsListener); } else { throw new ProxoolException("Statistics are switched off, your can't add a listener"); } } /** * Gives a snapshot of what the pool is doing * @param alias identifies the pool * @param detail if true then include detail of each connection. Note it you ask for * detail then the pool must necessarily be locked for the duration it takes to gather * the information (which isn't very long). You probably shouldn't do it that often (like * not every second or something). Being locked means that connections cannot be * served or returned (it doesn't mean that they can't be active). * @return the current status of the pool * @throws ProxoolException if we couldn't find the pool */ public static SnapshotIF getSnapshot(String alias, boolean detail) throws ProxoolException { SnapshotIF snapshot = null; ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); if (detail) { try { // Only try for 10 seconds! long start = System.currentTimeMillis(); if (cp.attemptConnectionStatusReadLock(10000)) { snapshot = Admin.getSnapshot(cp, cp.getDefinition(), cp.getConnectionInfos()); } else { LOG.warn("Give up waiting for detailed snapshot after " + (System.currentTimeMillis() - start) + " milliseconds. Serving standard snapshot instead."); } } finally { cp.releaseConnectionStatusReadLock(); } } if (snapshot == null) { snapshot = Admin.getSnapshot(cp, cp.getDefinition(), null); } return snapshot; } /** * Calls {@link #getSnapshot(java.lang.String, boolean) getSnapshot} * using false for the detail parameter. * @see #getSnapshot(java.lang.String, boolean) */ public static SnapshotIF getSnapshot(String alias) throws ProxoolException { return getSnapshot(alias, false); } // all jmx operations are done through reflection // to avoid making the facade dependant on the JMX classes private static boolean registerForJmx(String alias, Properties properties) { boolean success = false; try { Class jmxHelperClass = Class.forName("org.logicalcobwebs.proxool.admin.jmx.ProxoolJMXHelper"); Method registerMethod = jmxHelperClass.getDeclaredMethod("registerPool", new Class[]{String.class, Properties.class}); registerMethod.invoke(null, new Object[]{alias, properties}); success = true; } catch (Exception e) { LOG.error("JMX registration of " + alias + " pool failed.", e); } return success; } // all JNDI operations are done through reflection // to avoid making the facade dependant on the JNDI classes private static boolean registerDataSource(String alias, Properties jndiProperties) { boolean success = false; try { Class jndiHelperClass = Class.forName("org.logicalcobwebs.proxool.admin.jndi.ProxoolJNDIHelper"); Method registerMethod = jndiHelperClass.getDeclaredMethod("registerDatasource", new Class[]{String.class, Properties.class}); registerMethod.invoke(null, new Object[]{alias, jndiProperties}); success = true; } catch (Exception e) { LOG.error("JNDI DataSource binding of " + alias + " pool failed.", e); } return success; } /** * Get the JNDI properties for the given pool definition if it is configured for JNDI registration. * Will remove generic JNDI properties from the delegate properties so that they will not be passed to the * delegate driver. * @param connectionPoolDefinition the pool definition to get the eventual JNDI configuration from. * @return the JNDI properties, or null if the given definition was not configured for JNDI. */ private static Properties extractJndiProperties(ConnectionPoolDefinition connectionPoolDefinition) { if (connectionPoolDefinition.getJndiName() == null) { return null; } Properties jndiProperties = new Properties(); jndiProperties.setProperty(ProxoolConstants.JNDI_NAME, connectionPoolDefinition.getJndiName()); if (connectionPoolDefinition.getDelegateProperties() != null) { Properties delegateProperties = connectionPoolDefinition.getDelegateProperties(); // we must retrieve all the relevant property names before removing them from // the given properties to avoid ConcurrentModificationException String propertyName = null; List propertyNamesList = new ArrayList(10); Iterator keySetIterator = delegateProperties.keySet().iterator(); while (keySetIterator.hasNext()) { propertyName = (String) keySetIterator.next(); if (propertyName.startsWith(ProxoolConstants.JNDI_PROPERTY_PREFIX)) { propertyNamesList.add(propertyName); } } for (int i = 0; i < propertyNamesList.size(); i++) { propertyName = (String) propertyNamesList.get(i); if (propertyName.startsWith(ProxoolConstants.JNDI_PROPERTY_PREFIX)) { jndiProperties.setProperty(propertyName.substring(ProxoolConstants.JNDI_PROPERTY_PREFIX.length()), (String) delegateProperties.getProperty(propertyName)); delegateProperties.remove(propertyName); } } } return jndiProperties; } /** * Get wether the given pool properties contains configuration for JMX instrumentation of the pool. * @param poolProperties the properties to check for JMX configuration. * @return wether the given pool properties contains configuration for JMX instrumentation or not. */ private static boolean isConfiguredForJMX(Properties poolProperties) { final String jmxProperty = poolProperties.getProperty(ProxoolConstants.JMX_PROPERTY); if (jmxProperty != null && jmxProperty.equalsIgnoreCase("true")) { return true; } else { return false; } } /** * By remembering the most recent {@link ShutdownHook} ProxoolFacade * will know to disable it when it is {@link #shutdown}. It will gracefully * cope with the fact that it may be shutting down by the request of the * sutdownHook. If you don't do this and do several "hot deploys" then you * end up with a series of shutdown hooks. We only every want one. * @param t the thread that will be run as a shutdown hook * @see ShutdownHook */ protected static void setShutdownHook(Thread t) { shutdownHook = t; } } /* Revision history: $Log: ProxoolFacade.java,v $ Revision 1.87 2007/05/15 23:00:22 billhorsman Made removeStateListener() static like the other removeFooListener() methods. Credit to gazzamop@hotmail.com (bug 1716868). Revision 1.86 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.85 2006/11/02 10:00:34 billhorsman Added ProxoolFacade.disableShutdownHook. Revision 1.84 2006/01/18 14:40:01 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.83 2005/09/26 09:54:14 billhorsman Avoid suspected deadlock when getting a detailed snapshot. Only attempt to get the concurrent lock for 10 seconds before giving up. Revision 1.82 2005/05/04 16:32:31 billhorsman Clone the definition when redefining or updating the pool. Revision 1.81 2004/09/29 15:43:25 billhorsman Recheck isPoolExists inside synchronized registerConnectionPool method. Credit Juergen Hoeller. Revision 1.80 2004/06/02 20:47:05 billhorsman Override shutdown with a zero-parameter version for Spring integration. Revision 1.79 2004/03/26 15:58:56 billhorsman Fixes to ensure that house keeper and prototyper threads finish after shutdown. Revision 1.78 2004/03/23 21:25:54 billhorsman Added getAlias() call. Revision 1.77 2004/03/23 21:19:45 billhorsman Added disposable wrapper to proxied connection. And made proxied objects implement delegate interfaces too. Revision 1.76 2004/03/15 02:45:19 chr32 Added handling of Proxool managed JNDI DataSources. Revision 1.75 2004/02/12 12:54:49 billhorsman Fix merciful/forceExpiry confusion Revision 1.74 2003/10/30 00:16:13 billhorsman Throw a friendlier exception if you try and add a statistics listener to a pool with no statistics Revision 1.73 2003/10/16 18:52:35 billhorsman Fixed a bug: the redefine() method was actually calling the update() method. Also, added checks to make the "Attempt to use a pool with incomplete definition" exception a bit more descriptive. It's often because you are referring to an unregistered pool simply by using an alias. Revision 1.72 2003/09/07 22:09:21 billhorsman Remove any registered ShutdownHooks during shutdown. Revision 1.71 2003/08/30 14:54:04 billhorsman Checkstyle Revision 1.70 2003/08/28 10:55:49 billhorsman comment out JNDI stuff for now Revision 1.69 2003/08/27 18:03:20 billhorsman added new getDelegateConnection() method Revision 1.68 2003/07/23 12:38:50 billhorsman some fixes, but more to come Revision 1.67 2003/07/23 06:54:48 billhorsman draft JNDI changes (shouldn't effect normal operation) Revision 1.66 2003/04/10 21:49:34 billhorsman refactored registration slightly to allow DataSource access Revision 1.65 2003/03/11 14:51:53 billhorsman more concurrency fixes relating to snapshots Revision 1.64 2003/03/10 15:26:49 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.63 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.62 2003/02/28 10:42:59 billhorsman ConnectionPoolManager now passes ProxoolFacade an array of ConnectionPools rather than a Collection to avoid a ConcurrentModificationException during shutdown. Revision 1.61 2003/02/27 17:19:18 billhorsman new overloaded getSnapshot method Revision 1.60 2003/02/26 16:05:53 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.59 2003/02/24 18:03:24 chr32 Added JMX operations. Revision 1.58 2003/02/24 01:15:33 chr32 Added support for ProxoolListenerIF. Revision 1.57 2003/02/19 23:46:10 billhorsman renamed monitor package to admin Revision 1.56 2003/02/19 13:48:28 chr32 Added 'removeConfigurationListener' method. Revision 1.55 2003/02/18 16:50:00 chr32 Added possibility to remove connection and state listeners. Revision 1.54 2003/02/14 14:19:42 billhorsman automatically load ProxoolDriver Revision 1.53 2003/02/14 13:26:23 billhorsman better exception for incorrect url Revision 1.52 2003/02/12 12:28:27 billhorsman added url, proxyHashcode and delegateHashcode to ConnectionInfoIF Revision 1.51 2003/02/07 17:26:05 billhorsman deprecated removeAllConnectionPools in favour of shutdown (and dropped unreliable finalize() method) Revision 1.50 2003/02/07 15:12:41 billhorsman fix statisticsLogLevel property recognition again Revision 1.49 2003/02/07 14:45:40 billhorsman fix statisticsLogLevel property recognition Revision 1.48 2003/02/07 14:16:46 billhorsman support for StatisticsListenerIF Revision 1.47 2003/02/07 10:27:47 billhorsman change in shutdown procedure to allow re-registration Revision 1.46 2003/02/07 01:48:15 chr32 Started using new composite listeners. Revision 1.45 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.44 2003/02/06 15:46:43 billhorsman checkstyle Revision 1.43 2003/02/06 15:41:16 billhorsman add statistics-log-level Revision 1.42 2003/02/05 17:05:02 billhorsman registerConnectionPool is now synchronized Revision 1.41 2003/02/05 00:20:01 billhorsman copes with pools with no statistics Revision 1.40 2003/02/04 17:18:29 billhorsman move ShutdownHook init code Revision 1.39 2003/02/04 15:04:17 billhorsman New ShutdownHook Revision 1.38 2003/01/31 16:53:17 billhorsman checkstyle Revision 1.37 2003/01/31 11:50:39 billhorsman changes for snapshot improvements Revision 1.36 2003/01/31 00:18:27 billhorsman statistics is now a string to allow multiple, comma-delimited values (plus allow access to all statistics) Revision 1.35 2003/01/30 17:50:28 billhorsman spelling Revision 1.34 2003/01/30 17:48:50 billhorsman configuration listener now linked to alias not url Revision 1.33 2003/01/30 17:22:23 billhorsman add statistics support Revision 1.32 2003/01/27 18:26:36 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.31 2003/01/23 11:08:26 billhorsman new setConfiguratorListener method (and remove from optional parameter when registering pool) Revision 1.30 2003/01/19 15:21:07 billhorsman doc Revision 1.29 2003/01/18 15:13:12 billhorsman Signature changes (new ProxoolException thrown) on the ProxoolFacade API. Revision 1.28 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.27 2003/01/15 14:51:40 billhorsman checkstyle Revision 1.26 2003/01/15 12:20:06 billhorsman deprecated getConnectionPoolStatisticsDump Revision 1.25 2003/01/14 23:50:58 billhorsman logs version Revision 1.24 2002/12/16 17:15:03 billhorsman fix for url Revision 1.23 2002/12/16 16:47:22 billhorsman fix for updating properties with zero length strings Revision 1.22 2002/12/16 16:42:30 billhorsman allow URL updates to pool Revision 1.21 2002/12/16 11:46:00 billhorsman send properties to definitionUpdated Revision 1.20 2002/12/16 11:16:51 billhorsman checkstyle Revision 1.19 2002/12/16 11:15:19 billhorsman fixed getDelegateStatement Revision 1.18 2002/12/16 10:57:48 billhorsman add getDelegateStatement to allow access to the delegate JDBC driver's Statement Revision 1.17 2002/12/12 10:49:43 billhorsman now includes properties in definitionChanged event Revision 1.16 2002/12/04 13:19:43 billhorsman draft ConfigurationListenerIF stuff for persistent configuration Revision 1.15 2002/11/13 19:12:24 billhorsman fix where update properties weren't being recognised when the properties object was the same as the original Revision 1.14 2002/11/13 11:28:38 billhorsman trace property wasn't being configured Revision 1.13 2002/11/09 15:56:31 billhorsman log if serConnectionListener couldn't find pool Revision 1.12 2002/11/03 10:46:57 billhorsman hide passwords in log Revision 1.11 2002/11/02 13:57:33 billhorsman checkstyle Revision 1.10 2002/10/29 08:54:45 billhorsman fix to getAlias so that it correctly extracts alias from "proxool.alias" form Revision 1.9 2002/10/28 19:43:30 billhorsman configuring of pool now gets logged to that pool's logger (rather than general log) Revision 1.8 2002/10/27 13:29:38 billhorsman deprecated debug-level in favour of verbose Revision 1.7 2002/10/27 13:01:23 billhorsman layout Revision 1.6 2002/10/25 15:59:32 billhorsman made non-public where possible Revision 1.5 2002/10/25 10:12:52 billhorsman Improvements and fixes to the way connection pools close down. Including new ReloadMonitor to detect when a class is reloaded. Much better logging too. Revision 1.4 2002/10/24 17:40:31 billhorsman Fixed recognition of existing pool (which was resulting in an extra configuration step - but which didn't cause any problems) Revision 1.3 2002/10/23 21:04:36 billhorsman checkstyle fixes (reduced max line width and lenient naming convention Revision 1.2 2002/10/17 15:27:31 billhorsman better reporting of property settings Revision 1.1.1.1 2002/09/13 08:13:19 billhorsman new Revision 1.11 2002/08/24 20:07:28 billhorsman removed debug to stdout Revision 1.10 2002/08/24 19:44:13 billhorsman fixes for logging Revision 1.9 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.8 2002/07/05 13:24:32 billhorsman doc Revision 1.7 2002/07/04 09:04:20 billhorsman Now throws an SQLException if you ask for a ConnectionPoolDefinition, ConnectionPoolStatistics that doesn't exist. This makes it easier to show the list of possible ones you can choose. Revision 1.6 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.5 2002/07/02 11:14:26 billhorsman added test (andbug fixes) for FileLogger Revision 1.4 2002/07/02 09:13:08 billhorsman removed redundant import Revision 1.3 2002/07/02 08:52:42 billhorsman Added lots more methods and moved configuration stuff here Revision 1.2 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxoolListenerIF.java0000644000175000017500000000250210730503125030733 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Properties; /** * Listener for global Proxool events. * @version $Revision: 1.2 $, $Date: 2003/03/03 11:11:58 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public interface ProxoolListenerIF { /** * Notify that a new connection pool has been registered. Gets called *after* the registered. * @param connectionPoolDefinition the new definition. * @param completeInfo the properties that could be used to create this definition. */ void onRegistration(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo); /** * Notify that a connection pool will be shutdown. Gets called just *before* * the pool is shut down. * @param alias the alias of the pool about to be shut down. */ void onShutdown(String alias); } /* Revision history: $Log: ProxoolListenerIF.java,v $ Revision 1.2 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.1 2003/02/24 01:15:05 chr32 Init rev. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxyConnection.java0000644000175000017500000003561610730503125030521 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.logicalcobwebs.concurrent.WriterPreferenceReadWriteLock; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.util.FastArrayList; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Date; import java.util.Set; import java.util.HashSet; import java.util.List; import java.text.DecimalFormat; /** * Manages a connection. This is wrapped up inside a... * * @version $Revision: 1.40 $, $Date: 2007/05/15 23:17:21 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.10 */ public class ProxyConnection implements ProxyConnectionIF { static final int STATUS_FORCE = -1; private WriterPreferenceReadWriteLock statusReadWriteLock = new WriterPreferenceReadWriteLock(); private static final Log LOG = LogFactory.getLog(ProxyConnection.class); private Connection connection; private String delegateUrl; private int mark; private String reasonForMark; private int status; private long id; private Date birthDate; private long timeLastStartActive; private long timeLastStopActive; private ConnectionPool connectionPool; private ConnectionPoolDefinitionIF definition; private String requester; private Set openStatements = new HashSet(); private DecimalFormat idFormat = new DecimalFormat("0000"); private List sqlCalls = new FastArrayList(); /** * Whether we have invoked a method that requires us to reset */ private boolean needToReset = false; /** * * @param connection the real connection that is used * @param id unique ID * @param delegateUrl * @param connectionPool the pool it is a member of * @param definition the definition that was used to build it (could possibly be different from * the one held in the connectionPool) * @param status {@link #STATUS_ACTIVE}, {@link #STATUS_AVAILABLE}, {@link #STATUS_FORCE}, {@link #STATUS_NULL}, or {@link #STATUS_OFFLINE} * @throws SQLException */ protected ProxyConnection(Connection connection, long id, String delegateUrl, ConnectionPool connectionPool, ConnectionPoolDefinitionIF definition, int status) throws SQLException { this.connection = connection; this.delegateUrl = delegateUrl; setId(id); this.connectionPool = connectionPool; this.definition = definition; setBirthTime(System.currentTimeMillis()); this.status = status; if (status == STATUS_ACTIVE) { setTimeLastStartActive(System.currentTimeMillis()); } // We only need to call this for the first connection we make. But it returns really // quickly and we don't call it that often so we shouldn't worry. connectionPool.initialiseConnectionResetter(connection); if (connection == null) { throw new SQLException("Unable to create new connection"); } } /** * Whether the underlying connections are equal * @param obj the object (probably another connection) that we * are being compared to * @return whether they are the same */ public boolean equals(Object obj) { if (obj != null) { if (obj instanceof ProxyConnection) { return connection.hashCode() == ((ProxyConnection) obj).getConnection().hashCode(); } else if (obj instanceof Connection) { return connection.hashCode() == obj.hashCode(); } else { return super.equals(obj); } } else { return false; } } /** * Whether this connection is available. (When you close the connection * it doesn't really close, it just becomes available for others to use). * @return true if the connection is not active */ public boolean isClosed() { return (getStatus() != STATUS_ACTIVE); } /** * The subclass should call this to indicate that a change has been made to * the connection that might mean it needs to be reset (like setting autoCommit * to false or something). We don't reset unless this has been called to avoid * the overhead of unnecessary resetting. * * @param needToReset true if the connection might need resetting. */ protected void setNeedToReset(boolean needToReset) { this.needToReset = needToReset; } /** * The ConnectionPool that this connection belongs to * @return connectionPool */ protected ConnectionPool getConnectionPool() { return connectionPool; } /** * Get the definition that was used to create this connection * @return definition */ public ConnectionPoolDefinitionIF getDefinition() { return definition; } /** * By calling this we can keep track of any statements that are * left open when this connection is returned to the pool. * @param statement the statement that we have just opened/created. * @see #registerClosedStatement */ protected void addOpenStatement(Statement statement) { openStatements.add(statement); } /** * @see ProxyConnectionIF#registerClosedStatement */ public void registerClosedStatement(Statement statement) { if (openStatements.contains(statement)) { openStatements.remove(statement); } else { connectionPool.getLog().warn(connectionPool.displayStatistics() + " - #" + getId() + " registered a statement as closed which wasn't known to be open. This could happen if you close a statement twice."); } } /** * Close the connection for real * @throws java.sql.SQLException if anything goes wrong */ public void reallyClose() throws SQLException { try { connectionPool.registerRemovedConnection(getStatus()); // Clean up the actual connection connection.close(); } catch (Throwable t) { connectionPool.getLog().error("#" + idFormat.format(getId()) + " encountered errors during destruction: ", t); } } /** * @see ProxyConnectionIF#isReallyClosed */ public boolean isReallyClosed() throws SQLException { if (connection == null) { return true; } else { return connection.isClosed(); } } /** * @see ProxyConnectionIF#close */ public void close() throws SQLException { try { boolean removed = false; if (isMarkedForExpiry()) { if (connectionPool.getLog().isDebugEnabled()) { connectionPool.getLog().debug("Closing connection quickly (without reset) because it's marked for expiry anyway"); } } else { // Close any open statements, as specified in JDBC Statement[] statements = (Statement[]) openStatements.toArray(new Statement[openStatements.size()]); for (int j = 0; j < statements.length; j++) { Statement statement = statements[j]; statement.close(); if (connectionPool.getLog().isDebugEnabled()) { connectionPool.getLog().debug("Closing statement " + Integer.toHexString(statement.hashCode()) + " (belonging to connection " + getId() + ") automatically"); } } openStatements.clear(); if (needToReset) { // This call should be as quick as possible. Should we consider only // calling it if values have changed? The trouble with that is that it // means keeping track when they change and that might be even // slower if (!connectionPool.resetConnection(connection, "#" + getId())) { connectionPool.removeProxyConnection(this, ConnectionListenerIF.RESET_FAIL, "it couldn't be reset", true, true); removed = true; } needToReset = false; } } // If we removed it above then putting it back will only cause a confusing log event later when // it is unable to be changed from ACTIVE to AVAILABLE. if (!removed) { connectionPool.putConnection(this); } } catch (Throwable t) { connectionPool.getLog().error("#" + idFormat.format(getId()) + " encountered errors during closure: ", t); } } /** * This gets called /just/ before a connection is served. You can use it to reset some of the attributes. * The lifecycle is: {@link #open()} then {@link #close()} */ protected void open() { sqlCalls.clear(); } public int getMark() { return mark; } public int getStatus() { return status; } /** * @see ProxyConnectionIF#setStatus(int) */ public boolean setStatus(int newStatus) { return setStatus(STATUS_FORCE, newStatus); } /** * @see ProxyConnectionIF#setStatus(int, int) */ public boolean setStatus(int oldStatus, int newStatus) { boolean success = false; try { statusReadWriteLock.writeLock().acquire(); connectionPool.acquireConnectionStatusWriteLock(); if (this.status == oldStatus || oldStatus == STATUS_FORCE) { connectionPool.changeStatus(this.status, newStatus); this.status = newStatus; success = true; if (newStatus == oldStatus) { LOG.warn("Unexpected attempt to change status from " + oldStatus + " to " + newStatus + ". Why would you want to do that?"); } else if (newStatus == STATUS_ACTIVE) { setTimeLastStartActive(System.currentTimeMillis()); } else if (oldStatus == STATUS_ACTIVE) { setTimeLastStopActive(System.currentTimeMillis()); } } } catch (InterruptedException e) { LOG.error("Unable to acquire write lock for status"); } finally { connectionPool.releaseConnectionStatusWriteLock(); statusReadWriteLock.writeLock().release(); } return success; } public long getId() { return id; } public void setId(long id) { this.id = id; } /** * @see ConnectionInfoIF#getBirthTime */ public long getBirthTime() { return birthDate.getTime(); } /** * @see ConnectionInfoIF#getBirthDate */ public Date getBirthDate() { return birthDate; } /** * @see ConnectionInfoIF#getAge */ public long getAge() { return System.currentTimeMillis() - getBirthTime(); } /** * @see ConnectionInfoIF#getBirthTime */ public void setBirthTime(long birthTime) { birthDate = new Date(birthTime); } /** * @see ConnectionInfoIF#getTimeLastStartActive */ public long getTimeLastStartActive() { return timeLastStartActive; } /** * @see ConnectionInfoIF#getTimeLastStartActive */ public void setTimeLastStartActive(long timeLastStartActive) { this.timeLastStartActive = timeLastStartActive; setTimeLastStopActive(0); } /** * @see ConnectionInfoIF#getTimeLastStopActive */ public long getTimeLastStopActive() { return timeLastStopActive; } /** * @see ConnectionInfoIF#getTimeLastStopActive */ public void setTimeLastStopActive(long timeLastStopActive) { this.timeLastStopActive = timeLastStopActive; } /** * @see ConnectionInfoIF#getRequester */ public String getRequester() { return requester; } /** * @see ConnectionInfoIF#getRequester */ public void setRequester(String requester) { this.requester = requester; } /** * @see ProxyConnectionIF#isNull */ public boolean isNull() { return getStatus() == STATUS_NULL; } /** * @see ProxyConnectionIF#isAvailable */ public boolean isAvailable() { return getStatus() == STATUS_AVAILABLE; } /** * @see ProxyConnectionIF#isActive */ public boolean isActive() { return getStatus() == STATUS_ACTIVE; } /** * @see ProxyConnectionIF#isOffline */ public boolean isOffline() { return getStatus() == STATUS_OFFLINE; } /** * @see ProxyConnectionIF#markForExpiry */ public void markForExpiry(String reason) { mark = MARK_FOR_EXPIRY; reasonForMark = reason; } /** * @see ProxyConnectionIF#isMarkedForExpiry */ public boolean isMarkedForExpiry() { return getMark() == MARK_FOR_EXPIRY; } /** * @see ProxyConnectionIF#getReasonForMark */ public String getReasonForMark() { return reasonForMark; } /** * @see ProxyConnectionIF#getConnection */ public Connection getConnection() { return connection; } /** * @see Object#toString */ public String toString() { return getId() + " is " + ConnectionPool.getStatusDescription(getStatus()); } /** * @see ConnectionInfoIF#getDelegateUrl */ public String getDelegateUrl() { return delegateUrl; } /** * @see ConnectionInfoIF#getProxyHashcode */ public String getProxyHashcode() { return Integer.toHexString(hashCode()); } /** * @see ConnectionInfoIF#getDelegateHashcode */ public String getDelegateHashcode() { if (connection != null) { return Integer.toHexString(connection.hashCode()); } else { return null; } } /** * Compares using {@link #getId()} * @param o must be another {@link ConnectionInfoIF} implementation * @return the comparison * @see Comparable#compareTo(Object) */ public int compareTo(Object o) { return new Long(((ConnectionInfoIF) o).getId()).compareTo(new Long(getId())); } public String[] getSqlCalls() { return (String[]) sqlCalls.toArray(new String[0]); } public String getLastSqlCall() { if (sqlCalls != null && sqlCalls.size() > 0) { return (String) sqlCalls.get(sqlCalls.size() - 1); } else { return null; } } public int getReasonCode() { return 0; //To change body of implemented methods use File | Settings | File Templates. } public void addSqlCall(String sqlCall) { this.sqlCalls.add(sqlCall); } } libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxyConnectionIF.java0000644000175000017500000001340610730503125030731 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; /** * Contains most of the functionality that we require to manipilate the * connection. The subclass of this defines how we delegate to the * real connection. * @version $Revision: 1.8 $, $Date: 2007/01/25 23:38:24 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public interface ProxyConnectionIF extends ConnectionInfoIF { /** * Changes the status and lets the ConnectionPool know so that it * can keep count of how many connections are at each status. * This method obtains a write lock. * @param oldStatus the expected existing status. if the existing * status is not this value then no change is made and false is returned. * @param newStatus the status to change to * @return true if status changed successfully, or false if no change made * (because of unexpected existing status). */ boolean setStatus(int oldStatus, int newStatus); /** * Forces the new status regardless of the old state * @param newStatus the status to change to * @return true if status changed successfully, or false if no change made (should * always return true) * @see #setStatus(int, int) */ boolean setStatus(int newStatus); /** * Mark this connection for expiry (destruction) as soon as it stops * being active. * @param reason why we are marking this connection * @see #isMarkedForExpiry */ void markForExpiry(String reason); /** * Whether this connection is due for expiry * @return true if it is due for expiry * @see #markForExpiry */ boolean isMarkedForExpiry(); /** * Why this connection is marked (for instance, if a thread has * marked it for expiry then it's nice to know why) * @return reasonForMark */ String getReasonForMark(); /** * The real, delegate connection that we are using * @return connection */ Connection getConnection(); /** * @return true if the status is null */ boolean isNull(); /** * @return true if the status is available */ boolean isAvailable(); /** * @return true if the status is active */ boolean isActive(); /** * @return true if the status is offline */ boolean isOffline(); /** * Really close the connection, as opposed to just putting it back * in the pool. */ void reallyClose() throws SQLException; /** * @see ConnectionInfoIF#getRequester */ void setRequester(String requester); /** * Doesn't really close the connection, just puts it back in the pool. And tries to * reset all the methods that need resetting. * @see Connection#close */ void close() throws SQLException; /** * Notify that a statement has been closed and won't need closing * when the connection is returned to the poo. * @param statement the statement that has just been closed */ void registerClosedStatement(Statement statement); /** * Find out if the delegated connection is close. Just calling isClosed() on the * proxied connection will only indicate whether it is in the pool or not. * @return true if the connection is really closed, or if the connection is null * @throws java.sql.SQLException if anything went wrong */ boolean isReallyClosed() throws SQLException; ConnectionPoolDefinitionIF getDefinition(); /** * Get the most recent of all the {@link #getSqlCalls()} * @return the SQL (could be a batch of SQLs) */ String getLastSqlCall(); /** * Get the reason why this connection is {@link #getMark() marked} * @return {@link org.logicalcobwebs.proxool.ConnectionListenerIF#MAXIMUM_ACTIVE_TIME_EXPIRED}, * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#HOUSE_KEEPER_TEST_FAIL}, * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#FATAL_SQL_EXCEPTION_DETECTED}, * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#MANUAL_EXPIRY}, * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#MAXIMUM_CONNECTION_LIFETIME_EXCEEDED}, * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#RESET_FAIL}, * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#SHUTDOWN}, or * {@link org.logicalcobwebs.proxool.ConnectionListenerIF#VALIDATION_FAIL} */ int getReasonCode(); } /* Revision history: $Log: ProxyConnectionIF.java,v $ Revision 1.8 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.7 2005/10/07 08:18:24 billhorsman New sqlCalls gives list of SQL calls rather than just he most recent (for when a connection makes more than one call before being returned to the pool) Revision 1.6 2005/09/26 10:01:31 billhorsman Added lastSqlCall when trace is on. Revision 1.5 2005/05/04 16:24:13 billhorsman include a reference to the definition so we can spot it changing. Revision 1.4 2003/03/10 15:26:49 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.3 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.2 2003/02/26 16:05:53 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.1 2003/01/27 18:26:39 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxyDatabaseMetaData.java0000644000175000017500000001545510730503124031525 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.cglib.proxy.MethodInterceptor; import org.logicalcobwebs.cglib.proxy.MethodProxy; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DatabaseMetaData; /** * Delegates to a normal Coonection for everything but the close() * method (when it puts itself back into the pool instead). * @version $Revision: 1.9 $, $Date: 2006/01/18 14:40:02 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ class ProxyDatabaseMetaData implements MethodInterceptor { private static final Log LOG = LogFactory.getLog(ProxyDatabaseMetaData.class); private static final String GET_CONNECTION_METHOD = "getConnection"; private static final String EQUALS_METHOD = "equals"; private static final String FINALIZE_METHOD = "finalize"; private DatabaseMetaData databaseMetaData; private Connection wrappedConnection; /** * @param databaseMetaData the meta data we use to delegate all calls to (except getConnection()) * @param wrappedConnection the connection we return if asked for the connection */ public ProxyDatabaseMetaData(DatabaseMetaData databaseMetaData, Connection wrappedConnection) { this.databaseMetaData = databaseMetaData; this.wrappedConnection = wrappedConnection; } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object result = null; int argCount = args != null ? args.length : 0; try { if (method.getName().equals(GET_CONNECTION_METHOD)) { result = getConnection(); } else if (method.getName().equals(EQUALS_METHOD) && argCount == 1) { result = new Boolean(equals(args[0])); } else if (method.getName().equals(FINALIZE_METHOD)) { super.finalize(); } else { result = method.invoke(getDatabaseMetaData(), args); } } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (Exception e) { LOG.error("Unexpected invocation exception", e); throw new RuntimeException("Unexpected invocation exception: " + e.getMessage()); } return result; } /** * Whether the underlying databaseMetaData are equal * @param obj the object (probably another databaseMetaData) that we * are being compared to * @return whether they are the same */ public boolean equals(Object obj) { return databaseMetaData.hashCode() == obj.hashCode(); } /** * We don't want to ask the DatabaseMetaData object for the * connection or we will get the delegate instead of the Proxool * one. * @see DatabaseMetaData#getConnection */ public Connection getConnection() { return wrappedConnection; } /** * Get the DatabaseMetaData from the connection * @return databaseMetaData */ protected DatabaseMetaData getDatabaseMetaData() { return databaseMetaData; } /** * @see Object#toString */ public String toString() { return databaseMetaData.toString(); } } /* Revision history: $Log: ProxyDatabaseMetaData.java,v $ Revision 1.9 2006/01/18 14:40:02 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.8 2004/06/02 20:50:47 billhorsman Dropped obsolete InvocationHandler reference and injectable interface stuff. Revision 1.7 2004/03/23 21:19:45 billhorsman Added disposable wrapper to proxied connection. And made proxied objects implement delegate interfaces too. Revision 1.6 2003/12/12 19:29:47 billhorsman Now uses Cglib 2.0 Revision 1.5 2003/09/10 22:21:04 chr32 Removing > jdk 1.2 dependencies. Revision 1.4 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.3 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.2 2003/01/31 16:53:18 billhorsman checkstyle Revision 1.1 2003/01/31 14:33:18 billhorsman fix for DatabaseMetaData Revision 1.21 2003/01/27 18:26:38 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.20 2002/12/19 00:08:36 billhorsman automatic closure of statements when a connection is closed Revision 1.19 2002/12/17 17:15:39 billhorsman Better synchronization of status stuff Revision 1.18 2002/12/03 12:24:00 billhorsman fixed fatal sql exception Revision 1.17 2002/11/12 20:24:12 billhorsman checkstyle Revision 1.16 2002/11/12 20:18:23 billhorsman Made connection resetter a bit more friendly. Now, if it encounters any problems during reset then that connection is thrown away. This is going to cause you problems if you always close connections in an unstable state (e.g. with transactions open. But then again, it's better to know about that as soon as possible, right? Revision 1.15 2002/11/07 18:56:22 billhorsman fixed NullPointerException introduced yesterday on isClose() method Revision 1.14 2002/11/07 12:38:04 billhorsman performance improvement - only reset when it might be necessary Revision 1.13 2002/11/06 20:26:49 billhorsman improved doc, added connection resetting, and made isClosed() work correctly Revision 1.12 2002/11/02 13:57:33 billhorsman checkstyle Revision 1.11 2002/10/30 21:25:09 billhorsman move createStatement into ProxyFactory Revision 1.10 2002/10/30 21:19:17 billhorsman make use of ProxyFactory Revision 1.9 2002/10/28 19:51:34 billhorsman Fixed NullPointerException when calling connection.createProxyStatement() Revision 1.8 2002/10/28 19:28:25 billhorsman checkstyle Revision 1.7 2002/10/28 08:20:23 billhorsman draft sql dump stuff Revision 1.6 2002/10/25 15:59:32 billhorsman made non-public where possible Revision 1.5 2002/10/24 18:15:09 billhorsman removed unnecessary debug Revision 1.4 2002/10/17 15:29:18 billhorsman fixes so that equals() works Revision 1.3 2002/09/19 10:33:57 billhorsman added ProxyConnection#toString Revision 1.2 2002/09/18 13:48:56 billhorsman checkstyle and doc Revision 1.1.1.1 2002/09/13 08:13:30 billhorsman new Revision 1.10 2002/08/24 19:57:15 billhorsman checkstyle changes Revision 1.9 2002/08/24 19:42:26 billhorsman new proxy stuff to work with JDK 1.4 Revision 1.6 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.5 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxyFactory.java0000644000175000017500000003624310730503125030026 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.logicalcobwebs.cglib.proxy.Enhancer; import org.logicalcobwebs.cglib.proxy.Factory; import org.logicalcobwebs.cglib.proxy.Callback; import org.logicalcobwebs.cglib.core.NamingPolicy; import org.logicalcobwebs.cglib.core.Predicate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Statement; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.util.HashSet; import java.util.Set; import java.util.Map; import java.util.HashMap; import java.lang.reflect.Modifier; /** * A central place to build proxy objects. It will also provide the original * object given a proxy. * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.33 $, $Date: 2006/04/09 21:08:43 $ * @since Proxool 0.5 */ class ProxyFactory { private static final Log LOG = LogFactory.getLog(ProxyFactory.class); private static Map interfaceMap = new HashMap(); /** * This naming policy stops conflicts with other Cglib instances that are running * (Even ones in different packages). Without using our own naming policy we end * up with exceptions like: *
         * java.lang.LinkageError: duplicate class definition:
         *   $java/lang/Object$$FastClassByCGLIB$$3f697993
         * 
    */ private static NamingPolicy NAMING_POLICY = new NamingPolicy() { public String getClassName(String prefix, String source, Object key, Predicate names) { StringBuffer sb = new StringBuffer(); sb.append( (prefix != null) ? ( prefix.startsWith("java") ? "$" + prefix : prefix ) : "net.sf.cglib.empty.Object" ); sb.append("$$"); sb.append(source.substring(source.lastIndexOf('.') + 1)); sb.append("ByProxool$$"); sb.append(Integer.toHexString(key.hashCode())); String base = sb.toString(); String attempt = base; int index = 2; while (names.evaluate(attempt)) { attempt = base + "_" + index++; } return attempt; } }; /** * Wraps up a proxyConnection inside a {@link WrappedConnection} and then proxies it as a * simple {@link Connection}. You should call this immediately before the connection is served * to the user. The WrappedConnection is disposable (it is thrown away when the connection * is returned to the pool). * @param proxyConnection the pooled connection we are wrapping up * @return the Connection for use */ protected static Connection getWrappedConnection(ProxyConnection proxyConnection) { return (Connection) getProxy(proxyConnection.getConnection(), new WrappedConnection(proxyConnection), proxyConnection.getDefinition()); } /** * Proxies a statement inside a {@link ProxyStatement}. * @param delegate the real statement * @param connectionPool the pool it belongs to * @param proxyConnection the connection it was built from * @param sqlStatement Can be null? * @return the proxied statement */ protected static Statement getStatement(Statement delegate, ConnectionPool connectionPool, ProxyConnectionIF proxyConnection, String sqlStatement) { return (Statement) getProxy(delegate, new ProxyStatement(delegate, connectionPool, proxyConnection, sqlStatement), proxyConnection.getDefinition()); } /** * Create a new DatabaseMetaData from a connection * @param databaseMetaData the meta data we use to delegate all calls to (except getConnection()) * @param wrappedConnection the connection we return if asked for the connection * @return databaseMetaData */ protected static DatabaseMetaData getDatabaseMetaData(DatabaseMetaData databaseMetaData, Connection wrappedConnection) { return (DatabaseMetaData) getProxy(databaseMetaData, new ProxyDatabaseMetaData(databaseMetaData, wrappedConnection), null); } private static Object getProxy(Object delegate, Callback callback, ConnectionPoolDefinitionIF def) { Enhancer e = new Enhancer(); e.setNamingPolicy(NAMING_POLICY); e.setInterfaces(getInterfaces(delegate.getClass(), def)); e.setCallback(callback); e.setClassLoader(ProxyFactory.class.getClassLoader()); return e.create(); } /** * Gets the real Statement that we got from the delegate driver. This is no longer * necessary and only provided for backwards compatability. * @param statement proxy statement * @return delegate statement * @see ProxoolFacade#getDelegateStatement(java.sql.Statement) */ protected static Statement getDelegateStatement(Statement statement) { Statement ds = statement; ProxyStatement ps = (ProxyStatement) ((Factory)statement).getCallback(0); ds = ps.getDelegateStatement(); return ds; } /** * Gets the real Connection that we got from the delegate driver. This is no longer * necessary and only provided for backwards compatability. * @param connection proxy connection * @return deletgate connection * @see ProxoolFacade#getDelegateConnection(java.sql.Connection) */ protected static Connection getDelegateConnection(Connection connection) { WrappedConnection wc = (WrappedConnection) ((Factory)connection).getCallback(0); return wc.getProxyConnection().getConnection(); } /** * Get all the interfaces that a class implements. Drills down into super interfaces too * and super classes too. * The results are cached so it's very fast second time round. * @param clazz the class to examine. * @return an array of classes (all interfaces) that this class implements. */ private static Class[] getInterfaces(Class clazz, ConnectionPoolDefinitionIF cpd) { Class[] interfaceArray = (Class[]) interfaceMap.get(clazz); if (interfaceArray == null) { Set interfaces = new HashSet(); traverseInterfacesRecursively(interfaces, clazz); if (cpd != null) { // Work out which interface we should be injecting (if it has been configured). Make sure // we check CallableStatement then PreparedStatement then Statement or all three will get // caught by Statement if (Connection.class.isAssignableFrom(clazz)) { Class injectableClass = cpd.getInjectableConnectionInterface(); // Inject it if it was configured. if (injectableClass != null) { interfaces.add(injectableClass); if (LOG.isDebugEnabled()) { LOG.debug("Injecting " + injectableClass + " into " + clazz); } } } if (CallableStatement.class.isAssignableFrom(clazz)) { if (LOG.isDebugEnabled()) { LOG.debug("Getting injectableCallableStatementInterface"); } Class injectableClass = cpd.getInjectableCallableStatementInterface(); // Inject it if it was configured. if (injectableClass != null) { interfaces.add(injectableClass); if (LOG.isDebugEnabled()) { LOG.debug("Injecting " + injectableClass + " into " + clazz); } } } if (PreparedStatement.class.isAssignableFrom(clazz)) { Class injectableClass = cpd.getInjectablePreparedStatementInterface(); // Inject it if it was configured. if (injectableClass != null) { interfaces.add(injectableClass); if (LOG.isDebugEnabled()) { LOG.debug("Injecting " + injectableClass + " into " + clazz); } } } if (Statement.class.isAssignableFrom(clazz)) { Class injectableClass = cpd.getInjectableStatementInterface(); // Inject it if it was configured. if (injectableClass != null) { interfaces.add(injectableClass); if (LOG.isDebugEnabled()) { LOG.debug("Injecting " + injectableClass + " into " + clazz); } } } } interfaceArray = (Class[]) interfaces.toArray(new Class[interfaces.size()]); if (LOG.isDebugEnabled()) { for (int i = 0; i < interfaceArray.length; i++) { Class aClass = interfaceArray[i]; LOG.debug("Implementing " + aClass); } } interfaceMap.put(clazz, interfaceArray); /* } else { if (LOG.isDebugEnabled()) { LOG.debug("Reusing " + interfaceArray.length + " interfaces already looked up for " + clazz); } */ } return interfaceArray; } /** * Recursively looks at all interfaces for a class. Also looks at interfaces implemented * by the super class (and its super class, etc.) Quite a lot of processing involved * so you shouldn't call it too often. * @param interfaces this set is populated with all interfaceMap it finds * @param clazz the base class to analyze */ private static void traverseInterfacesRecursively(Set interfaces, Class clazz) { // Check for circular reference (avoid endless recursion) if (interfaces.contains(clazz)) { // Skip it, we've already been here. /* if (LOG.isDebugEnabled()) { LOG.debug("Skipping " + clazz + " because we've already traversed it"); } */ } else { /* if (LOG.isDebugEnabled()) { LOG.debug("Analyzing " + clazz); } */ Class[] interfaceArray = clazz.getInterfaces(); for (int i = 0; i < interfaceArray.length; i++) { /* if (LOG.isDebugEnabled()) { LOG.debug("Adding " + interfaceArray[i]); } */ traverseInterfacesRecursively(interfaces, interfaceArray[i]); // We're only interested in public interfaces. In fact, including // non-public interfaces will give IllegalAccessExceptions. if (Modifier.isPublic(interfaceArray[i].getModifiers())) { interfaces.add(interfaceArray[i]); } } Class superClazz = clazz.getSuperclass(); if (superClazz != null) { traverseInterfacesRecursively(interfaces, superClazz); } /* if (LOG.isDebugEnabled()) { LOG.debug("Found " + interfaceArray.length + " interfaceMap for " + clazz); } */ } } /** * Get the WrappedConnection behind this proxy connection. * @param connection the connection that was served * @return the wrapped connection or null if it couldn't be found */ public static WrappedConnection getWrappedConnection(Connection connection) { return (WrappedConnection) ((Factory)connection).getCallback(0); } } /* Revision history: $Log: ProxyFactory.java,v $ Revision 1.33 2006/04/09 21:08:43 billhorsman Use our own naming policy for Cglib to avoid duplicate class definition exceptions. Revision 1.32 2006/01/18 14:40:02 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.31 2005/09/26 09:59:22 billhorsman Explicitly use the ProxyFactory class loader when using Cglib's Enhancer to avoid class loading issues. Revision 1.30 2005/05/04 16:31:41 billhorsman Use the definition referenced by the proxy connection rather than the pool instead. Revision 1.29 2004/07/27 21:44:15 billhorsman Remove insane amount of debug logging. Revision 1.28 2004/06/17 21:58:36 billhorsman Injectable interface fixes. Revision 1.27 2004/06/02 20:50:47 billhorsman Dropped obsolete InvocationHandler reference and injectable interface stuff. Revision 1.26 2004/03/23 21:19:45 billhorsman Added disposable wrapper to proxied connection. And made proxied objects implement delegate interfaces too. Revision 1.25 2003/12/12 19:29:47 billhorsman Now uses Cglib 2.0 Revision 1.24 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.23 2003/09/10 22:21:04 chr32 Removing > jdk 1.2 dependencies. Revision 1.22 2003/09/07 22:11:31 billhorsman Remove very persistent debug message Revision 1.21 2003/08/27 18:03:20 billhorsman added new getDelegateConnection() method Revision 1.20 2003/03/11 14:51:54 billhorsman more concurrency fixes relating to snapshots Revision 1.19 2003/03/10 23:43:13 billhorsman reapplied checkstyle that i'd inadvertently let IntelliJ change... Revision 1.18 2003/03/10 15:26:49 billhorsman refactoringn of concurrency stuff (and some import optimisation) Revision 1.17 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools Revision 1.16 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.15 2003/02/19 15:14:32 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.14 2003/02/12 12:28:27 billhorsman added url, proxyHashcode and delegateHashcode to ConnectionInfoIF Revision 1.13 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.12 2003/01/31 14:33:18 billhorsman fix for DatabaseMetaData Revision 1.11 2003/01/27 18:26:39 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.10 2002/12/16 11:15:19 billhorsman fixed getDelegateStatement Revision 1.9 2002/12/16 10:57:47 billhorsman add getDelegateStatement to allow access to the delegate JDBC driver's Statement Revision 1.8 2002/12/12 10:48:25 billhorsman checkstyle Revision 1.7 2002/12/08 22:17:35 billhorsman debug for proxying statement interfaces Revision 1.6 2002/12/06 15:57:08 billhorsman fix for proxied statement where Statement interface is not directly implemented. Revision 1.5 2002/12/03 12:24:00 billhorsman fixed fatal sql exception Revision 1.4 2002/11/09 15:56:52 billhorsman fix doc Revision 1.3 2002/11/02 14:22:15 billhorsman Documentation Revision 1.2 2002/10/30 21:25:08 billhorsman move createStatement into ProxyFactory Revision 1.1 2002/10/30 21:19:16 billhorsman make use of ProxyFactory */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ProxyStatement.java0000644000175000017500000002574110730503125030364 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.cglib.proxy.MethodInterceptor; import org.logicalcobwebs.cglib.proxy.MethodProxy; import org.logicalcobwebs.cglib.proxy.InvocationHandler; import org.logicalcobwebs.proxool.proxy.InvokerFacade; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Statement; import java.sql.Connection; /** * Delegates to Statement for all calls. But also, for all execute methods, it * checks the SQLException and compares it to the fatalSqlException list in the * ConnectionPoolDefinition. If it detects a fatal exception it will destroy the * Connection so that it isn't used again. * @version $Revision: 1.32 $, $Date: 2006/03/03 09:58:26 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ class ProxyStatement extends AbstractProxyStatement implements MethodInterceptor { private static final Log LOG = LogFactory.getLog(ProxyStatement.class); private static final String EXECUTE_FRAGMENT = "execute"; private static final String EXECUTE_BATCH_METHOD = "executeBatch"; private static final String ADD_BATCH_METHOD = "addBatch"; private static final String EQUALS_METHOD = "equals"; private static final String CLOSE_METHOD = "close"; private static final String GET_CONNECTION_METHOD = "getConnection"; private static final String FINALIZE_METHOD = "finalize"; private static final String SET_NULL_METHOD = "setNull"; private static final String SET_PREFIX = "set"; public ProxyStatement(Statement statement, ConnectionPool connectionPool, ProxyConnectionIF proxyConnection, String sqlStatement) { super(statement, connectionPool, proxyConnection, sqlStatement); } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return invoke(proxy, method, args); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; long startTime = System.currentTimeMillis(); final int argCount = args != null ? args.length : 0; Method concreteMethod = InvokerFacade.getConcreteMethod(getStatement().getClass(), method); // This gets called /before/ the method has run if (concreteMethod.getName().equals(ADD_BATCH_METHOD)) { // If we have just added a batch call then we need to update the sql log if (argCount > 0 && args[0] instanceof String) { setSqlStatementIfNull((String) args[0]); } appendToSqlLog(); } else if (concreteMethod.getName().equals(EXECUTE_BATCH_METHOD)) { // executing a batch should do a trace startExecute(); } else if (concreteMethod.getName().startsWith(EXECUTE_FRAGMENT)) { // executing should update the log and do a trace if (argCount > 0 && args[0] instanceof String) { setSqlStatementIfNull((String) args[0]); } appendToSqlLog(); startExecute(); } // We need to remember an exceptions that get thrown so that we can optionally // pass them to the onExecute() call below Exception exception = null; try { if (concreteMethod.getName().equals(EQUALS_METHOD) && argCount == 1) { result = (equals(args[0])) ? Boolean.TRUE : Boolean.FALSE; } else if (concreteMethod.getName().equals(CLOSE_METHOD) && argCount == 0) { close(); } else if (concreteMethod.getName().equals(GET_CONNECTION_METHOD) && argCount == 0) { result = getConnection(); } else if (concreteMethod.getName().equals(FINALIZE_METHOD) && argCount == 0) { finalize(); } else { try { result = concreteMethod.invoke(getStatement(), args); } catch (IllegalAccessException e) { // This is probably because we are trying to access a non-public concrete class. But don't worry, // we can always use the proxy supplied method. This will only fail if we try to use an injectable // method on a method in a class that isn't public and for a method that isn't declared in an interface - // but if that is the case then that method is inaccessible by any means (even by bypassing Proxool and // using the vendor's driver directly). LOG.debug("Ignoring IllegalAccessException whilst invoking the " + concreteMethod + " concrete method and trying the " + method + " method directly."); // By overriding the method cached in the InvokerFacade we ensure that we only log this message once, and // we speed up subsequent usages by not calling the method that fails first. InvokerFacade.overrideConcreteMethod(getStatement().getClass(), method, method); result = method.invoke(getStatement(), args); } } // We only dump sql calls if we are in verbose mode and debug is enabled if (isTrace()) { try { // What sort of method is it if (concreteMethod.getName().equals(SET_NULL_METHOD) && argCount > 0 && args[0] instanceof Integer) { int index = ((Integer) args[0]).intValue(); putParameter(index, null); } else if (concreteMethod.getName().startsWith(SET_PREFIX) && argCount > 1 && args[0] instanceof Integer) { int index = ((Integer) args[0]).intValue(); putParameter(index, args[1]); } } catch (Exception e) { // We don't want an error during dump screwing up the transaction LOG.error("Ignoring error during dump", e); } } } catch (InvocationTargetException e) { if (e.getTargetException() instanceof Exception) { exception = (Exception) e.getTargetException(); } else { exception = e; } if (testException(e.getTargetException())) { // This is really a fatal one FatalSqlExceptionHelper.throwFatalSQLException(getConnectionPool().getDefinition().getFatalSqlExceptionWrapper(), e.getTargetException()); } throw e.getTargetException(); } catch (Exception e) { exception = e; if (testException(e)) { // This is really a fatal one FatalSqlExceptionHelper.throwFatalSQLException(getConnectionPool().getDefinition().getFatalSqlExceptionWrapper(), e); } throw e; } finally { // This gets called /after/ the method has run if (concreteMethod.getName().equals(EXECUTE_BATCH_METHOD) || concreteMethod.getName().startsWith(EXECUTE_FRAGMENT)) { trace(startTime, exception); } } return result; } } /* Revision history: $Log: ProxyStatement.java,v $ Revision 1.32 2006/03/03 09:58:26 billhorsman Fix for statement.getConnection(). See bug 1149834. Revision 1.31 2006/01/18 14:40:02 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.30 2006/01/16 23:09:28 billhorsman Call concrete finalize() method Revision 1.29 2005/10/07 08:15:00 billhorsman Update sqlCalls /before/ we execute so that we can see what slow calls are doing before they finish. Revision 1.28 2004/07/13 21:06:18 billhorsman Fix problem using injectable interfaces on methods that are declared in non-public classes. Revision 1.27 2004/06/17 21:56:53 billhorsman Use MethodMapper for concrete methods. Revision 1.26 2004/06/02 20:48:14 billhorsman Dropped obsolete InvocationHandler reference. Revision 1.25 2003/12/12 19:29:47 billhorsman Now uses Cglib 2.0 Revision 1.24 2003/10/19 09:50:33 billhorsman Drill down into InvocationTargetException during execution debug. Revision 1.23 2003/10/18 20:44:48 billhorsman Better SQL logging (embed parameter values within SQL call) and works properly with batched statements now. Revision 1.22 2003/09/30 18:39:08 billhorsman New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties. Revision 1.21 2003/09/29 17:48:49 billhorsman New fatal-sql-exception-wrapper-class allows you to define what exception is used as a wrapper. This means that you can make it a RuntimeException if you need to. Revision 1.20 2003/09/10 22:21:04 chr32 Removing > jdk 1.2 dependencies. Revision 1.19 2003/09/05 17:01:00 billhorsman Trap and throw FatalSQLExceptions. Revision 1.18 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.17 2003/02/13 17:06:42 billhorsman allow for sqlStatement in execute() method Revision 1.16 2003/02/06 17:41:04 billhorsman now uses imported logging Revision 1.15 2003/01/31 16:53:19 billhorsman checkstyle Revision 1.14 2003/01/28 11:47:08 billhorsman new isTrace() and made close() public Revision 1.13 2003/01/27 18:26:40 billhorsman refactoring of ProxyConnection and ProxyStatement to make it easier to write JDK 1.2 patch Revision 1.12 2002/12/19 00:08:36 billhorsman automatic closure of statements when a connection is closed Revision 1.11 2002/12/16 10:57:48 billhorsman add getDelegateStatement to allow access to the delegate JDBC driver's Statement Revision 1.10 2002/12/03 12:24:00 billhorsman fixed fatal sql exception Revision 1.9 2002/11/13 18:22:04 billhorsman fix for trace output Revision 1.8 2002/11/13 12:32:38 billhorsman now correctly logs trace messages even with verbose off Revision 1.7 2002/11/09 15:57:33 billhorsman finished off execute logging and listening Revision 1.6 2002/10/29 23:20:55 billhorsman logs execute time when debug is enabled and verbose is true Revision 1.5 2002/10/28 19:28:25 billhorsman checkstyle Revision 1.4 2002/10/28 08:20:23 billhorsman draft sql dump stuff Revision 1.3 2002/10/25 15:59:32 billhorsman made non-public where possible Revision 1.2 2002/10/17 15:29:18 billhorsman fixes so that equals() works Revision 1.1.1.1 2002/09/13 08:13:30 billhorsman new Revision 1.8 2002/08/24 19:57:15 billhorsman checkstyle changes Revision 1.7 2002/08/24 19:42:26 billhorsman new proxy stuff to work with JDK 1.4 Revision 1.6 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.5 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/ShutdownHook.java0000644000175000017500000001266010730503125030006 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; /** * This is instantiated statically by ProxoolFacade. It will automatically * close down all the connections when the JVM stops. * @version $Revision: 1.13 $, $Date: 2006/11/02 10:00:34 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ class ShutdownHook implements Runnable { private static final Log LOG = LogFactory.getLog(ShutdownHook.class); private static boolean registered; protected static void init() { if (!registered) { registered = true; new ShutdownHook(); } } protected static void remove(Thread t) { Runtime runtime = Runtime.getRuntime(); try { final Method removeShutdownHookMethod = Runtime.class.getMethod("removeShutdownHook", new Class[] {Thread.class}); removeShutdownHookMethod.invoke(runtime, new Object[] {t}); if (LOG.isDebugEnabled()) { LOG.debug("Removed shutdownHook"); } } catch (NoSuchMethodException e) { LOG.warn("Proxool will have to be shutdown manually with ProxoolFacade.shutdown() because this version of the JDK does not support Runtime.getRuntime().addShutdownHook()"); } catch (SecurityException e) { LOG.error("Problem removing shutdownHook", e); } catch (IllegalAccessException e) { LOG.error("Problem removing shutdownHook", e); } catch (InvocationTargetException e) { // Use getTargetException() because getCause() is only supported in JDK 1.4 and later Throwable cause = ((InvocationTargetException) e).getTargetException(); if (cause instanceof IllegalStateException) { // This is probably because a shutdown is in progress. We can // safely ignore that. } else { LOG.error("Problem removing shutdownHook", e); } } } /** * Registers this ShutdownHook with Runtime */ private ShutdownHook() { Thread t = new Thread(this); t.setName("ShutdownHook"); Runtime runtime = Runtime.getRuntime(); try { Method addShutdownHookMethod = Runtime.class.getMethod("addShutdownHook", new Class[] {Thread.class}); addShutdownHookMethod.invoke(runtime, new Object[] {t}); ProxoolFacade.setShutdownHook(t); if (LOG.isDebugEnabled()) { LOG.debug("Registered shutdownHook"); } } catch (NoSuchMethodException e) { LOG.warn("Proxool will have to be shutdown manually with ProxoolFacade.shutdown() because this version of the JDK does not support Runtime.getRuntime().addShutdownHook()"); } catch (SecurityException e) { LOG.error("Problem registering shutdownHook", e); } catch (IllegalAccessException e) { LOG.error("Problem registering shutdownHook", e); } catch (InvocationTargetException e) { LOG.error("Problem registering shutdownHook", e); } } /** * Remove all connection pools without delay. Only runs if the * shutdown hook is {@link org.logicalcobwebs.proxool.ProxoolFacade#isShutdownHookEnabled() enabled}. * @see ProxoolFacade#removeAllConnectionPools */ public void run() { if (ProxoolFacade.isShutdownHookEnabled()) { LOG.debug("Running ShutdownHook"); Thread.currentThread().setName("Shutdown Hook"); ProxoolFacade.shutdown(0); } else { LOG.debug("Skipping ShutdownHook because it's been disabled"); } } } /* Revision history: $Log: ShutdownHook.java,v $ Revision 1.13 2006/11/02 10:00:34 billhorsman Added ProxoolFacade.disableShutdownHook. Revision 1.12 2006/01/18 14:40:02 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2003/12/16 09:09:32 billhorsman Switched from getCause() to getTargetException() so that we can trap the IllegalStateException in all JDKs. Revision 1.10 2003/11/16 18:19:14 chr32 Started calling to Exception.getCause() via refletion to maintain compilability with < jdk 1.4 compilers. Revision 1.9 2003/10/27 12:32:06 billhorsman Fixed typos and silently ignore IllegalStateException during shutdownHook removal (it's probably because the JVM is shutting down). Revision 1.8 2003/09/07 22:05:15 billhorsman Now uses reflection to add ShutdownHook to Runtime so that it is JDK independent. Using JDK1.2 will disable the shutdownHook and simply log a warning message that Proxool must be shutdown explicitly. Revision 1.7 2003/03/03 17:07:58 billhorsman name thread Revision 1.6 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.5 2003/02/26 11:20:59 billhorsman removed debug Revision 1.4 2003/02/10 15:13:57 billhorsman fixed deprecated call Revision 1.3 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.2 2003/02/04 17:19:11 billhorsman ShutdownHook now initialises Revision 1.1 2003/02/04 15:04:17 billhorsman New ShutdownHook */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/StateListenerIF.java0000644000175000017500000000314310730503125030353 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; /** * Monitors the state of the pool so you can see whether it is * quiet, busy, overloaded, or down. * *
     * String alias = "myPool";
     * StateListenerIF myStateListener = new MyStateListener();
     * ProxoolFacade.{@link ProxoolFacade#addStateListener addStateListenerIF}(alias, myStateListener);
     * 
    * * @version $Revision: 1.5 $, $Date: 2003/03/03 11:11:58 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface StateListenerIF { public final int STATE_QUIET = 0; public final int STATE_BUSY = 1; public final int STATE_OVERLOADED = 2; public final int STATE_DOWN = 3; void upStateChanged(int upState); } /* Revision history: $Log: StateListenerIF.java,v $ Revision 1.5 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.4 2003/02/08 00:35:30 billhorsman doc Revision 1.3 2002/12/15 19:21:42 chr32 Changed @linkplain to @link (to preserve JavaDoc for 1.2/1.3 users). Revision 1.2 2002/10/25 16:00:27 billhorsman added better class javadoc Revision 1.1.1.1 2002/09/13 08:13:30 billhorsman new Revision 1.5 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.4 2002/06/28 11:19:47 billhorsman improved doc Revision 1.3 2002/06/28 11:15:41 billhorsman didn't really need ListenerIF */ libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/Version.java0000644000175000017500000000723411053760610027003 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Tells you the version. You can tell what sort of release it is * from the version. For instance: * * 1.0.0 (1 January) * A proper released binary file at version 1.0. * * 1.0.0+ * Built from the source based on version 1.0 (but there is no * way of knowing whether the source has been altered). * * 1.0.1 (2 January) * A bug fix release built on January 2nd. * * @version $Revision: 1.23 $, $Date: 2008/08/23 10:08:08 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class Version { private static final Log LOG = LogFactory.getLog(Version.class); /** * This is changed by the Ant script when you build from the * source code. */ private static final String VERSION = null; private static final String BUILD_DATE = null; private static final String CVS = "0.9.1+"; public static String getVersion() { StringBuffer version = new StringBuffer(); if (VERSION != null) { version.append(VERSION); } else { /** * This means that we haven't used the Ant script so this * is just our best guess at the version. */ version.append(CVS); } if (BUILD_DATE != null) { version.append(" ("); version.append(BUILD_DATE); version.append(")"); } return version.toString(); } /** * Convenient way of verifying version * @param args none required (any sent are ignored) */ public static void main(String[] args) { LOG.info("Version " + getVersion()); } } /* Revision history: $Log: Version.java,v $ Revision 1.23 2008/08/23 10:08:08 billhorsman Version 0.9.1 - packaging of Cglib Revision 1.22 2008/08/19 19:17:11 billhorsman Version 0.9.0 Revision 1.21 2007/01/10 09:24:35 billhorsman 0.9.0RC3 Revision 1.20 2006/01/18 14:40:02 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.19 2005/09/26 21:47:46 billhorsman no message Revision 1.18 2003/12/13 12:21:54 billhorsman Release 0.8.3 Revision 1.17 2003/11/05 00:19:48 billhorsman new revision Revision 1.16 2003/10/27 13:13:58 billhorsman new version Revision 1.15 2003/10/26 15:23:30 billhorsman 0.8.0 Revision 1.14 2003/10/01 19:31:26 billhorsman 0.8.0RC2 Revision 1.13 2003/09/11 11:17:52 billhorsman *** empty log message *** Revision 1.12 2003/08/30 11:43:32 billhorsman Update for next release. Revision 1.11 2003/07/23 06:54:48 billhorsman draft JNDI changes (shouldn't effect normal operation) Revision 1.10 2003/06/18 10:04:47 billhorsman versioning Revision 1.9 2003/03/12 15:59:53 billhorsman *** empty log message *** Revision 1.8 2003/03/03 11:11:58 billhorsman fixed licence Revision 1.7 2003/02/21 15:19:09 billhorsman update version Revision 1.6 2003/02/12 00:50:34 billhorsman change the CVS version to be x.y+ (a bit more informative) Revision 1.5 2003/02/06 17:41:05 billhorsman now uses imported logging Revision 1.4 2003/01/21 10:56:40 billhorsman new version approach Revision 1.3 2003/01/16 11:45:02 billhorsman changed format from x.y+ to x.y.* Revision 1.2 2003/01/16 11:22:00 billhorsman new version Revision 1.1 2003/01/14 23:50:59 billhorsman keeps track of version */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/WrappedConnection.java0000644000175000017500000003224110730503125030771 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.logicalcobwebs.cglib.proxy.InvocationHandler; import org.logicalcobwebs.cglib.proxy.MethodInterceptor; import org.logicalcobwebs.cglib.proxy.MethodProxy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.proxy.InvokerFacade; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.sql.Statement; import java.sql.SQLException; import java.sql.Connection; /** * Wraps up a {@link ProxyConnection}. It is proxied as a {@link java.sql.Connection} * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:02 $ * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class WrappedConnection implements MethodInterceptor { private static final Log LOG = LogFactory.getLog(WrappedConnection.class); private static final String CLOSE_METHOD = "close"; private static final String IS_CLOSED_METHOD = "isClosed"; private static final String EQUALS_METHOD = "equals"; private static final String GET_META_DATA_METHOD = "getMetaData"; private static final String FINALIZE_METHOD = "finalize"; private static final String HASH_CODE_METHOD = "hashCode"; private static final String TO_STRING_METHOD = "toString"; /** * The wrapped object. We should protect this and not expose it. We have to make sure that * if we pass the proxyConnection to another WrappedConnection then this one can no longer * manipulate it. */ private ProxyConnection proxyConnection; private long id; private String alias; /** * This gets set if the close() method is explicitly called. The {@link #getProxyConnection() proxyConnection} * could still be {@link org.logicalcobwebs.proxool.ProxyConnectionIF#isReallyClosed() really closed} without * this wrapper knowing about it yet. */ private boolean manuallyClosed; /** * Construct this wrapper around the proxy connection * @param proxyConnection to wrap */ public WrappedConnection(ProxyConnection proxyConnection) { this.proxyConnection = proxyConnection; this.id = proxyConnection.getId(); this.alias= proxyConnection.getDefinition().getAlias(); } /** * Get the encapsulated proxy connection * @return the proxy connection */ public ProxyConnection getProxyConnection() { return proxyConnection; } /** * Delegates to {@link #invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) invoke} * @see MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], org.logicalcobwebs.cglib.proxy.MethodProxy) */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return invoke(proxy, method, args); } /** * Delegates all operations to the encapsulated {@link ProxyConnection} except for: *
      *
    • close()
    • *
    • equals()
    • *
    • hashCode()
    • *
    • isClosed()
    • *
    • getMetaData()
    • *
    • finalize()
    • *
    * It also spots mutators and remembers that the property has been changed so that it can * be {@link ConnectionResetter reset}. And any statements that are returned are remembered * so that we can track whether all statements have been closed properly when the connection * is returned to the pool. * @see InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; int argCount = args != null ? args.length : 0; Method concreteMethod = method; if (proxyConnection != null && proxyConnection.getConnection() != null) { concreteMethod = InvokerFacade.getConcreteMethod(proxyConnection.getConnection().getClass(), method); } try { if (proxyConnection != null && proxyConnection.isReallyClosed()) { // The user is trying to do something to this connection and it's been closed. if (concreteMethod.getName().equals(IS_CLOSED_METHOD)) { // That's cool. No problem checking as many times as you like. } else if (concreteMethod.getName().equals(CLOSE_METHOD)) { // That's cool. You can call close as often as you like. } else if (manuallyClosed) { // We've already manually closed this connection yet we trying to do something // to it that isn't another close(). That is bad client coding :) throw new SQLException("You can't perform any operations on a connection after you've called close()"); } else { // The connection has been closed automatically. The client probably wasn't expecting // that. Still, throw an exception so that they know it's all gone pear shaped. throw new SQLException("You can't perform any operations on this connection. It has been automatically closed by Proxool for some reason (see logs)."); } } if (concreteMethod.getName().equals(CLOSE_METHOD)) { // It's okay to close a connection twice. Only we ignore the // second time. if (proxyConnection != null && !proxyConnection.isReallyClosed()) { proxyConnection.close(); // Set it to null so that we can't do anything else to it. proxyConnection = null; manuallyClosed = true; } } else if (concreteMethod.getName().equals(EQUALS_METHOD) && argCount == 1) { result = equals(args[0]) ? Boolean.TRUE : Boolean.FALSE; } else if (concreteMethod.getName().equals(HASH_CODE_METHOD) && argCount == 0) { result = new Integer(hashCode()); } else if (concreteMethod.getName().equals(IS_CLOSED_METHOD) && argCount == 0) { result = (proxyConnection == null || proxyConnection.isClosed()) ? Boolean.TRUE : Boolean.FALSE; } else if (concreteMethod.getName().equals(GET_META_DATA_METHOD) && argCount == 0) { if (proxyConnection != null) { Connection connection = ProxyFactory.getWrappedConnection(proxyConnection); result = ProxyFactory.getDatabaseMetaData(proxyConnection.getConnection().getMetaData(), connection); } else { throw new SQLException("You can't perform a " + concreteMethod.getName() + " operation after the connection has been closed"); } } else if (concreteMethod.getName().equals(FINALIZE_METHOD)) { super.finalize(); } else if (concreteMethod.getName().equals(TO_STRING_METHOD)) { result = toString(); } else { if (proxyConnection != null) { if (concreteMethod.getName().startsWith(ConnectionResetter.MUTATOR_PREFIX)) { proxyConnection.setNeedToReset(true); } try { result = concreteMethod.invoke(proxyConnection.getConnection(), args); } catch (IllegalAccessException e) { // This is probably because we are trying to access a non-public concrete class. But don't worry, // we can always use the proxy supplied method. This will only fail if we try to use an injectable // method on a method in a class that isn't public and for a method that isn't declared in an interface - // but if that is the case then that method is inaccessible by any means (even by bypassing Proxool and // using the vendor's driver directly). LOG.debug("Ignoring IllegalAccessException whilst invoking the " + concreteMethod + " concrete method and trying the " + method + " method directly."); // By overriding the method cached in the InvokerFacade we ensure that we only log this message once, and // we speed up subsequent usages by not calling the method that fails first. InvokerFacade.overrideConcreteMethod(proxyConnection.getConnection().getClass(), method, method); result = method.invoke(proxyConnection.getConnection(), args); } } else { throw new SQLException("You can't perform a " + concreteMethod.getName() + " operation after the connection has been closed"); } } // If we have just made some sort of Statement then we should rather return // a proxy instead. if (result instanceof Statement) { // Work out whether we were passed the sql statement during the // call to get the statement object. Sometimes you do, sometimes // you don't: // connection.prepareCall(sql); // connection.createProxyStatement(); String sqlStatement = null; if (argCount > 0 && args[0] instanceof String) { sqlStatement = (String) args[0]; } // We keep a track of all open statements proxyConnection.addOpenStatement((Statement) result); result = ProxyFactory.getStatement((Statement) result, proxyConnection.getConnectionPool(), proxyConnection, sqlStatement); } } catch (InvocationTargetException e) { // We might get a fatal exception here. Let's test for it. if (FatalSqlExceptionHelper.testException(proxyConnection.getDefinition(), e.getTargetException())) { FatalSqlExceptionHelper.throwFatalSQLException(proxyConnection.getDefinition().getFatalSqlExceptionWrapper(), e.getTargetException()); } throw e.getTargetException(); } catch (SQLException e) { throw new SQLException("Couldn't perform the operation " + concreteMethod.getName() + ": " + e.getMessage()); } catch (Exception e) { LOG.error("Unexpected invocation exception", e); if (FatalSqlExceptionHelper.testException(proxyConnection.getDefinition(), e)) { FatalSqlExceptionHelper.throwFatalSQLException(proxyConnection.getDefinition().getFatalSqlExceptionWrapper(), e); } throw new RuntimeException("Unexpected invocation exception: " + e.getMessage()); } return result; } /** * The ID for the encapsulated {@link ProxyConnection}. This will still * return the correct value after the connection is closed. * @return the ID */ public long getId() { return id; } /** * Get the alias of the connection pool this connection belongs to * @return {@link ConnectionPoolDefinitionIF#getAlias() alias} */ public String getAlias() { return alias; } /** * If the object passed to this method is actually a proxied version of this * class then compare the real class with this one. * @param obj the object to compare * @return true if the object is a proxy of "this" */ public boolean equals(Object obj) { if (obj instanceof Connection) { final WrappedConnection wc = ProxyFactory.getWrappedConnection((Connection) obj); if (wc != null && wc.getId() > 0 && getId() > 0) { return wc.getId() == getId(); } else { return false; } } else { return false; } } /** * @see Object#toString() */ public String toString() { if (proxyConnection != null) { return hashCode() + "(" + proxyConnection.getConnection().toString() + ")"; } else { return hashCode() + "(out of scope)"; } } } /* Revision history: $Log: WrappedConnection.java,v $ Revision 1.6 2006/01/18 14:40:02 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2005/10/02 12:32:58 billhorsman Improve the trapping of operations after a wrapped connection is closed. Revision 1.4 2005/05/04 16:31:41 billhorsman Use the definition referenced by the proxy connection rather than the pool instead. Revision 1.3 2004/07/13 21:06:21 billhorsman Fix problem using injectable interfaces on methods that are declared in non-public classes. Revision 1.2 2004/06/02 20:50:47 billhorsman Dropped obsolete InvocationHandler reference and injectable interface stuff. Revision 1.1 2004/03/23 21:19:45 billhorsman Added disposable wrapper to proxied connection. And made proxied objects implement delegate interfaces too. */libproxool-java-0.9.1.orig/src/java/org/logicalcobwebs/proxool/package.html0000644000175000017500000000630010730503125026762 0ustar twernertwerner

    A Java SQL Driver that provides a connection pool wrapper around another Driver of your choice. Very simple to migrate existing code. Fully configurable. Fast, mature and robust. Transparently adds connection pooling to your existing JDBC driver.

    I want to add some better documentation right here. But in the meantime you should find comprehensive information on our web site

    The latest version of this code is available from Sourceforge.

    The majority of the work on Proxool (as of May 2002) was funded by Telenor Media AS


    Proxool's Licence

    Copyright (c) 2002 - 2003 Proxool. All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

    3. All advertising materials mentioning features or use of this software must display the following acknowledgment:

    "This product includes software developed by the Proxool project (The latest version is available at http://proxool.sourceforge.net/)."

    4. The name "Proxool" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact bill@logicalcobwebs.co.uk.

    5. Products derived from this software may not be called "Proxool" nor may "Proxool" appear in their names without prior written permission of the Proxool Project.

    6. Redistributions of any form whatsoever must retain the following acknowledgment:

    "This product includes software developed by the Proxool project (The latest version is available at http://proxool.sourceforge.net/)."

    THIS SOFTWARE IS PROVIDED BY THE PROXOOL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROXOOL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


    This software consists of voluntary contributions made by many individuals on behalf of the Proxool Project. For more information on the Proxool Project please see The latest version is available at http://proxool.sourceforge.net.

    libproxool-java-0.9.1.orig/src/java-examples/0000755000175000017500000000000011053761073021055 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-examples/org/0000755000175000017500000000000011053761073021644 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-examples/org/logicalcobwebs/0000755000175000017500000000000011053761073024623 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-examples/org/logicalcobwebs/proxool/0000755000175000017500000000000011053761073026325 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-examples/org/logicalcobwebs/proxool/examples/0000755000175000017500000000000011054125603030135 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-examples/org/logicalcobwebs/proxool/examples/Simple.java0000644000175000017500000000771710730503126032245 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.examples; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * The simplest example of all. Just gets a Connection. * * @version $Revision: 1.7 $, $Date: 2006/01/18 14:40:03 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class Simple { private static final Log LOG = LogFactory.getLog(Simple.class); private static void withoutProxool() { Connection connection = null; try { Class.forName("org.hsqldb.jdbcDriver"); try { connection = DriverManager.getConnection("jdbc:hsqldb:test"); } catch (SQLException e) { LOG.error("Problem getting connection", e); } if (connection != null) { LOG.info("Got connection :)"); } else { LOG.error("Didn't get connection, which probably means that no Driver accepted the URL"); } } catch (ClassNotFoundException e) { LOG.error("Couldn't find driver", e); } finally { try { // Check to see we actually got a connection before we // attempt to close it. if (connection != null) { connection.close(); } } catch (SQLException e) { LOG.error("Problem closing connection", e); } } } private static void withProxool() { Connection connection = null; try { // NOTE THIS LINE Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); try { // NOTE THIS LINE connection = DriverManager.getConnection("proxool.example:org.hsqldb.jdbcDriver:jdbc:hsqldb:test"); } catch (SQLException e) { LOG.error("Problem getting connection", e); } if (connection != null) { LOG.info("Got connection :)"); } else { LOG.error("Didn't get connection, which probably means that no Driver accepted the URL"); } } catch (ClassNotFoundException e) { LOG.error("Couldn't find driver", e); } finally { try { // Check to see we actually got a connection before we // attempt to close it. if (connection != null) { connection.close(); } } catch (SQLException e) { LOG.error("Problem closing connection", e); } } } /** * Tests getting a connection with and without Proxool */ public static void main(String[] args) { withoutProxool(); withProxool(); } } /* Revision history: $Log: Simple.java,v $ Revision 1.7 2006/01/18 14:40:03 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.6 2003/03/03 11:12:02 billhorsman fixed licence Revision 1.5 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.4 2003/02/06 15:42:48 billhorsman updated (overdue!) Revision 1.3 2002/12/03 10:54:04 billhorsman use hypersonic driver Revision 1.2 2002/09/19 10:01:37 billhorsman improved error handling and logging Revision 1.1 2002/09/19 08:51:09 billhorsman created new examples package Revision 1.1.1.1 2002/09/13 08:14:27 billhorsman new Revision 1.4 2002/07/10 16:14:47 billhorsman widespread layout changes and move constants into ProxoolConstants Revision 1.3 2002/07/02 11:19:08 billhorsman layout code and imports Revision 1.2 2002/06/28 11:19:47 billhorsman improved doc */ libproxool-java-0.9.1.orig/src/java-sandbox/0000755000175000017500000000000011053761073020675 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-sandbox/org/0000755000175000017500000000000011053761073021464 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-sandbox/org/logicalcobwebs/0000755000175000017500000000000011053761073024443 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-sandbox/org/logicalcobwebs/proxool/0000755000175000017500000000000011054125603026137 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-sandbox/org/logicalcobwebs/proxool/VirtoolDriver.java0000644000175000017500000000555310730503132031621 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.Properties; /** * This class acts as a virtual pool. When you ask it for a connection it * delegates to one of the designated real pools. Some assumptions: * * Getting a connection needs to be very fast. * * Switching pools can be relatively slow (but just to get that in perspective, * > 100ms) * * We should detect pools that don't respond (timeout), throw certain * SQLExceptions, or are unacceptably slow. * * We should also allow simple load balancing between pools that are * up. * * @version $Revision: 1.2 $, $Date: 2003/03/03 11:12:02 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class VirtoolDriver implements Driver { private static final String VIRTOOL = "virtool"; private String[] activePools; private int nextPool; public Connection connect(String url, Properties info) throws SQLException { String alias = activePools[nextPool]; // Now we need to move to the next pool. This code isn't ThreadSafe and // we don't want to make it so because it would have a performance // impact. return null; } public boolean acceptsURL(String url) throws SQLException { return (url.startsWith(VIRTOOL)); } public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { return new DriverPropertyInfo[0]; } public int getMajorVersion() { throw new UnsupportedOperationException("This virtual driver doesn't support this operation."); } public int getMinorVersion() { throw new UnsupportedOperationException("This virtual driver doesn't support this operation."); } public boolean jdbcCompliant() { throw new UnsupportedOperationException("This virtual driver doesn't support this operation."); } static { try { DriverManager.registerDriver(new VirtoolDriver()); } catch (SQLException e) { System.out.println(e.toString()); } } } /* Revision history: $Log: VirtoolDriver.java,v $ Revision 1.2 2003/03/03 11:12:02 billhorsman fixed licence Revision 1.1 2002/12/15 19:00:32 chr32 Moved over from 'ext' source tree. Revision 1.3 2002/11/12 20:19:18 billhorsman added some doc Revision 1.2 2002/10/27 13:05:01 billhorsman checkstyle Revision 1.1 2002/10/27 12:05:39 billhorsman early, early draft */ libproxool-java-0.9.1.orig/src/java-test/0000755000175000017500000000000011053761073020216 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/0000755000175000017500000000000011053761073021005 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/0000755000175000017500000000000011053761073023764 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/cglib/0000755000175000017500000000000011054125603025036 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/cglib/EnhancerTest.java0000644000175000017500000000310710730503131030261 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.cglib; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.cglib.proxy.Enhancer; /** * A test test class (!) to help me understand the Enhancer. It fails. Or at least, * it would do if I uncommented the assert. But that fines. It's a learning process. * @version $Revision: 1.2 $, $Date: 2004/06/02 20:55:54 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class EnhancerTest extends AbstractProxoolTest { public EnhancerTest(String alias) { super(alias); } public void testConcreteClassEnhancer() { MyInterfaceIF mi = (MyInterfaceIF) Enhancer.create( null, new Class[] {MyInterfaceIF.class}, new MyProxy(new MyConcreteClass())); mi.bar(); try { MyConcreteClass mcc = (MyConcreteClass) mi; } catch (ClassCastException e) { // Expected this :( } // This fails // assertEquals("foo()", "proxiedFoo", mcc.foo()); } } /* Revision history: $Log: EnhancerTest.java,v $ Revision 1.2 2004/06/02 20:55:54 billhorsman Make sure test doesn't throw a ClassCastException Revision 1.1 2004/06/02 20:54:57 billhorsman Learning test class for Enhancer. It fails (or would if the assert was uncommented). Left in for knowledge. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/cglib/MyConcreteClass.java0000644000175000017500000000225510730503131030737 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.cglib; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * See {@link EnhancerTest} * @version $Revision: 1.3 $, $Date: 2006/01/18 14:40:03 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class MyConcreteClass implements MyInterfaceIF { private static final Log LOG = LogFactory.getLog(MyConcreteClass.class); MyConcreteClass() { LOG.debug("MyConcreteClass.init"); } public String foo() { return "foo"; } public void bar() {} } /* Revision history: $Log: MyConcreteClass.java,v $ Revision 1.3 2006/01/18 14:40:03 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.2 2004/06/17 21:40:06 billhorsman Log message should be debug not error Revision 1.1 2004/06/02 20:54:57 billhorsman Learning test class for Enhancer. It fails (or would if the assert was uncommented). Left in for knowledge. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/cglib/MyInterfaceIF.java0000644000175000017500000000130110730503131030315 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.cglib; /** * See {@link EnhancerTest} * @version $Revision: 1.1 $, $Date: 2004/06/02 20:54:57 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public interface MyInterfaceIF { public void bar(); } /* Revision history: $Log: MyInterfaceIF.java,v $ Revision 1.1 2004/06/02 20:54:57 billhorsman Learning test class for Enhancer. It fails (or would if the assert was uncommented). Left in for knowledge. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/cglib/MyProxy.java0000644000175000017500000000236310730503131027330 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.cglib; import org.logicalcobwebs.cglib.proxy.MethodInterceptor; import org.logicalcobwebs.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * See {@link EnhancerTest} * @version $Revision: 1.1 $, $Date: 2004/06/02 20:54:57 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) */ public class MyProxy implements MethodInterceptor { private MyConcreteClass myConcreteClass; public MyProxy(MyConcreteClass myConcreteClass) { this.myConcreteClass = myConcreteClass; } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if (method.getName().equals("foo")) { return "proxiedFoo"; } else { return method.invoke(myConcreteClass, args); } } } /* Revision history: $Log: MyProxy.java,v $ Revision 1.1 2004/06/02 20:54:57 billhorsman Learning test class for Enhancer. It fails (or would if the assert was uncommented). Left in for knowledge. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/0000755000175000017500000000000011054125603025570 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/Command.java0000644000175000017500000001003410730503127030010 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * An SQL command that isrun by a {@link Script}. If {@link #getLoad load} * or {@link #getLoops loops} are configured then it might run more than * once. * * @version $Revision: 1.9 $, $Date: 2006/01/18 14:40:04 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ class Command implements CommandIF { private static final Log LOG = LogFactory.getLog(Command.class); private String name; private String sql; private int load = 1; private int loops = 1; private String exception; /** * If this command encounters an exception it will stop executing (and if * it is in a loop it will break out of the loop) */ protected static final String EXCEPTION_STOP = "stop"; /** * If this command encounters an exception it will log it at DEBUG * level and continue */ protected static final String EXCEPTION_LOG = "log"; /** * If this command encounters an exception it will silently ignore the * exception and continue. But it still calls the */ protected static final String EXCEPTION_IGNORE = "ignore"; /** * @see CommandIF#getSql */ public String getSql() { return sql; } /** * @see #getSql */ protected void setSql(String sql) { this.sql = sql; } /** * @see CommandIF#getLoad */ public int getLoad() { return load; } /** * @see #getLoad */ protected void setLoad(int load) { this.load = load; } /** * @see CommandIF#getLoops */ public int getLoops() { return loops; } /** * @see #getLoops */ protected void setLoops(int loops) { this.loops = loops; } /** * @see CommandIF#isIgnoreException */ public boolean isIgnoreException() { return exception != null && exception.equals(EXCEPTION_IGNORE); } /** * @see CommandIF#isIgnoreException */ public boolean isLogException() { return exception != null && exception.equals(EXCEPTION_LOG); } /** * @see #isIgnoreException */ public void setException(String exception) { if (exception == null) { this.exception = EXCEPTION_STOP; LOG.debug("Setting exception to default " + EXCEPTION_STOP); } else if (exception.equals(EXCEPTION_IGNORE) || exception.equals(EXCEPTION_LOG) || exception.equals(EXCEPTION_STOP)) { this.exception = exception; LOG.debug("Setting exception to " + exception); } else { throw new RuntimeException("Unknown exception value: " + exception); } } /** * @see CommandIF#getName */ public String getName() { return name; } /** * @see #getName */ public void setName(String name) { this.name = name; } } /* Revision history: $Log: Command.java,v $ Revision 1.9 2006/01/18 14:40:04 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.8 2003/03/03 11:12:02 billhorsman fixed licence Revision 1.7 2003/02/19 15:14:18 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.6 2003/02/06 17:41:01 billhorsman now uses imported logging Revision 1.5 2002/11/09 15:58:12 billhorsman fix doc Revision 1.4 2002/11/09 14:45:07 billhorsman now threaded and better exception handling Revision 1.3 2002/11/06 21:07:03 billhorsman Now supports the CommandIF interface Revision 1.2 2002/11/02 14:22:16 billhorsman Documentation Revision 1.1 2002/11/02 11:29:53 billhorsman new script runner for testing */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/CommandFilterIF.java0000644000175000017500000000456710730503127031413 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import java.sql.Connection; import java.sql.SQLException; /** * Allows you to perform tasks just {@link #beforeCommand before} and just * {@link #afterCommand after} a {@link CommandIF command} is executed. * You can also {@link #catchException catch} exceptions that happen. * * @version $Revision: 1.5 $, $Date: 2003/03/03 11:12:03 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public interface CommandFilterIF { /** * Implement this if you want to do something special before each command is run. * @param connection the connection being used * @param command the command about to be run * @return true if the command should be executed, or false to skip the command * @throws SQLException if anything goes wrong. This will terminate the script. */ boolean beforeCommand(Connection connection, CommandIF command) throws SQLException; /** * Implement this if you want to do something special after each command is run * but before the connection is closed * @param connection the connection being used * @param command the command that was run * @throws SQLException if anything goes wrong. This will terminate the script. */ void afterCommand(Connection connection, CommandIF command) throws SQLException; /** * Any SQLException will be passed to this method. * @param e the exception * @return true if execution should continue, false if it should stop (including any remaining executions in the loop) */ boolean catchException(CommandIF command, SQLException e); } /* Revision history: $Log: CommandFilterIF.java,v $ Revision 1.5 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.4 2003/02/19 15:14:19 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.3 2002/11/09 15:58:37 billhorsman fix and added doc Revision 1.2 2002/11/09 14:45:07 billhorsman now threaded and better exception handling Revision 1.1 2002/11/06 21:07:42 billhorsman New interfaces to allow filtering of commands */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/CommandIF.java0000644000175000017500000000412410730503127030232 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; /** * An SQL command to run. * * @version $Revision: 1.5 $, $Date: 2003/03/03 11:12:03 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public interface CommandIF { /** * The SQL statement to run * @return sql */ String getSql(); /** * How many "threads" to simulate. See {@link org.logicalcobwebs.dbscript.Script} to see how * it actually implements thread-like behaviour. * @return load */ int getLoad(); /** * The number of loops to perform. Each loop will run the {@link #getSql sql} * {@link #getLoad load} times. * @return loops */ int getLoops(); /** * If true then errors that occur during this command are ignored silently * and do not stop the {@link org.logicalcobwebs.dbscript.Script script} running. * @return true if exceptions should be ignored */ boolean isIgnoreException(); /** * If true then errors that occur during this command are logged as debug * messages but do not stop the {@link org.logicalcobwebs.dbscript.Script script} running. * @return true if exceptions should be logged */ boolean isLogException(); /** * A convenient name to call this command to help logging. * @return name */ String getName(); } /* Revision history: $Log: CommandIF.java,v $ Revision 1.5 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.4 2003/02/19 15:14:19 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.3 2002/11/09 15:58:54 billhorsman fix and added doc Revision 1.2 2002/11/09 14:45:07 billhorsman now threaded and better exception handling Revision 1.1 2002/11/06 21:07:42 billhorsman New interfaces to allow filtering of commands */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/Commander.java0000644000175000017500000001123710730503127030345 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; /** * A thread that can run a single command many times. * * @version $Revision: 1.7 $, $Date: 2006/01/18 14:40:05 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ class Commander implements Runnable { private static final Log LOG = LogFactory.getLog(Commander.class); private ConnectionAdapterIF adapter; private CommandIF command; private CommandFilterIF commandFilter; private boolean finished = false; public Commander(ConnectionAdapterIF adapter, CommandIF commandIF, CommandFilterIF commandFilter) { this.adapter = adapter; this.command = commandIF; this.commandFilter = commandFilter; } public void run() { try { boolean keepGoing = true; for (int i = 0; i < command.getLoops(); i++) { Connection connection = null; try { connection = adapter.getConnection(); boolean executeCommand = true; if (commandFilter != null) { executeCommand = commandFilter.beforeCommand(connection, command); } if (executeCommand) { execute(connection, command.getSql()); } if (commandFilter != null) { commandFilter.afterCommand(connection, command); } } catch (SQLException e) { if (commandFilter != null && !commandFilter.catchException(command, e)) { keepGoing = false; } if (command.isIgnoreException()) { // Silent } else if (command.isLogException()) { LOG.debug("Ignoring exception in " + command.getName(), e); } else { LOG.error("Stopping command " + command.getName(), e); keepGoing = false; } } finally { try { adapter.closeConnection(connection); } catch (SQLException e) { LOG.error("Closing connection for " + Thread.currentThread().getName(), e); } } if (!keepGoing) { break; } // Give other threads a chance. (Hoping this will increase the chances // of some sort of conflict) Thread.yield(); } } finally { finished = true; } } /** * Is the thread running * @return true if it's finished, else false */ protected boolean isFinished() { return finished; } /** * Execute and SQL statement * @param connection used to execute statement * @param sql the SQL to perform * @throws java.sql.SQLException if anything goes wrong */ private static final void execute(Connection connection, String sql) throws SQLException { Statement statement = null; try { statement = connection.createStatement(); statement.execute(sql); } finally { if (statement != null) { try { if (statement != null) { statement.close(); } } catch (SQLException e) { LOG.error("Couldn't close statement", e); } } } } } /* Revision history: $Log: Commander.java,v $ Revision 1.7 2006/01/18 14:40:05 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.6 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.5 2003/02/19 15:14:20 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.4 2003/02/06 17:41:02 billhorsman now uses imported logging Revision 1.3 2003/01/15 00:08:15 billhorsman check for commandFilter existence to avoid unnecessary log clutter Revision 1.2 2002/11/09 15:59:18 billhorsman fix doc Revision 1.1 2002/11/09 14:45:07 billhorsman now threaded and better exception handling */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/ConnectionAdapterIF.java0000644000175000017500000000547210730503127032263 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import org.logicalcobwebs.proxool.ProxoolException; import java.util.Properties; import java.sql.SQLException; import java.sql.Connection; /** * An interface that will provide connections. It differs from a real * {@link java.sql.Driver Driver} because it has {@link #setup} and * {@link #tearDown} methods. * * @version $Revision: 1.8 $, $Date: 2003/03/03 11:12:03 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public interface ConnectionAdapterIF { /** * Setup the adapter. Define the connection. Prototype any connections * as necessary. * * @param driver the name of the class * @param url the url to pass to the driver * @param info the properties to pass to the driver * @throws SQLException if anything goes wrong */ void setup(String driver, String url, Properties info) throws SQLException, ProxoolException; /** * Simply get a connection (using the definitions defined in {@link #setup} * @return the connection * @throws SQLException if anything goes wrong */ Connection getConnection() throws SQLException; /** * This gives the adapter the flexibilty of closing the connection for real * or just putting it back in a pool. * @param connection the connection to "close" * @throws SQLException if anything goes wrong */ void closeConnection(Connection connection) throws SQLException; /** * Reclaim resources used by the adapter (for instance, close any * open connections) */ void tearDown() throws ProxoolException; /** * Convenient name so we can identify this adapter in logs. * @return name */ String getName(); } /* Revision history: $Log: ConnectionAdapterIF.java,v $ Revision 1.8 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.7 2003/02/19 15:14:21 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.6 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.5 2002/11/13 20:23:34 billhorsman change method name, throw exceptions differently, trivial changes Revision 1.4 2002/11/09 15:59:34 billhorsman fix doc Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 12:46:42 billhorsman improved debug Revision 1.1 2002/11/02 11:29:53 billhorsman new script runner for testing */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/Script.java0000644000175000017500000000545410730503127027710 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import java.util.List; import java.util.Properties; import java.util.Vector; /** * Defines a set of {@link #getCommands commands} to run. And which * {@link #getDriver driver} to use. And its {@link #getInfo configuration}. * * @version $Revision: 1.6 $, $Date: 2003/03/03 11:12:03 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ class Script { private String name; private String driver; private String url; private Properties info = new Properties(); private List commands = new Vector(); /** * Add a command to the script. * @param command to add */ protected void addCommand(Command command) { commands.add(command); } /** * Get all the commands, in the order in which they were added * @return list of commands */ protected Command[] getCommands() { return (Command[]) commands.toArray(new Command[commands.size()]); } /** * So we can recognise this script in the logs * @return name */ protected String getName() { return name; } /** * @see #getName */ protected void setName(String name) { this.name = name; } /** * The URL to pass to the Driver */ protected String getUrl() { return url; } /** * @see #getUrl */ protected void setUrl(String url) { this.url = url; } /** * The driver to use * @return the driver */ protected String getDriver() { return driver; } /** * @see #getDriver */ protected void setDriver(String driver) { this.driver = driver; } /** * Configuration of the Driver * @return properties */ protected Properties getInfo() { return info; } /** * Add a new property * @param name name of property * @param value value of property */ protected void addProperty(String name, String value) { info.setProperty(name, value); } } /* Revision history: $Log: Script.java,v $ Revision 1.6 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.5 2003/02/19 15:14:21 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.4 2002/11/09 15:59:52 billhorsman fix doc Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.1 2002/11/02 11:29:53 billhorsman new script runner for testing */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/ScriptBuilder.java0000644000175000017500000000641010730503127031210 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Parser to get {@link org.logicalcobwebs.dbscript.Script} from XML source * * @version $Revision: 1.9 $, $Date: 2006/01/18 14:40:05 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ class ScriptBuilder extends DefaultHandler { private static final Log LOG = LogFactory.getLog(ScriptBuilder.class); private Script script = null; /** * @see DefaultHandler#startElement */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("script")) { script = new Script(); script.setName(attributes.getValue("name")); script.setDriver(attributes.getValue("driver")); script.setUrl(attributes.getValue("url")); } else if (qName.equals("info")) { String name = attributes.getValue("name"); String value = attributes.getValue("value"); script.addProperty(name, value); } else if (qName.equals("command")) { Command command = new Command(); command.setName(attributes.getValue("name")); command.setSql(attributes.getValue("sql")); if (attributes.getValue("load") != null) { int load = Integer.parseInt(attributes.getValue("load")); command.setLoad(load); } if (attributes.getValue("loops") != null) { int loops = Integer.parseInt(attributes.getValue("loops")); command.setLoops(loops); } if (attributes.getValue("exception") != null) { String exception = attributes.getValue("exception"); command.setException(exception); } script.addCommand(command); } } /** * Get the script we just built. Call *after* {@link javax.xml.parsers.SAXParser#parse parsing} * @return the new script */ protected Script getScript() { return script; } } /* Revision history: $Log: ScriptBuilder.java,v $ Revision 1.9 2006/01/18 14:40:05 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.8 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.7 2003/02/19 15:14:21 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.6 2003/02/06 17:41:02 billhorsman now uses imported logging Revision 1.5 2002/11/09 16:00:08 billhorsman fix doc Revision 1.4 2002/11/09 14:45:07 billhorsman now threaded and better exception handling Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.1 2002/11/02 11:29:53 billhorsman new script runner for testing */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/ScriptFacade.java0000644000175000017500000001240510730503127030766 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXParseException; import org.xml.sax.SAXException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolException; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParser; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.sql.SQLException; /** * Allows you to run scripts from file. * * @version $Revision: 1.12 $, $Date: 2006/01/18 14:40:05 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class ScriptFacade { private static final Log LOG = LogFactory.getLog(ScriptFacade.class); /** * Run the script using the appropriate handler * @param scriptLocation the path to the file that contains the script XML * @param adapter so we know where to get {@link java.sql.Connection connections} from. */ public static void runScript(String scriptLocation, ConnectionAdapterIF adapter) { runScript(scriptLocation, adapter, null); } /** * Run the script using the appropriate handler * @param scriptLocation the path to the file that contains the script XML * @param adapter so we know where to get {@link java.sql.Connection connections} from. * @param commandFilter allows you to filter which commands get run and do things to the {@link java.sql.Connection} */ public static void runScript(String scriptLocation, ConnectionAdapterIF adapter, CommandFilterIF commandFilter) { File scriptFile = new File(scriptLocation); if (!scriptFile.canRead()) { throw new RuntimeException("Can't read from file at " + scriptFile.getAbsolutePath()); } try { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setValidating(false); saxParserFactory.setNamespaceAware(true); SAXParser saxParser = saxParserFactory.newSAXParser(); saxParser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces", true); saxParser.getXMLReader().setErrorHandler(new ErrorHandler() { public void warning(SAXParseException exception) throws SAXException { LOG.warn(exception.getLineNumber() + ":" + exception.getColumnNumber(), exception); } public void error(SAXParseException exception) throws SAXException { LOG.error(exception.getLineNumber() + ":" + exception.getColumnNumber(), exception); } public void fatalError(SAXParseException exception) throws SAXException { LOG.error(exception.getLineNumber() + ":" + exception.getColumnNumber(), exception); } }); ScriptBuilder scriptBuilder = new ScriptBuilder(); saxParser.parse(scriptFile, scriptBuilder); Script script = scriptBuilder.getScript(); ScriptRunner.runScript(script, adapter, commandFilter); } catch (FactoryConfigurationError factoryConfigurationError) { LOG.error(factoryConfigurationError); } catch (ParserConfigurationException e) { LOG.error("Problem running script " + scriptLocation, e); } catch (SAXException e) { LOG.error("Problem running script " + scriptLocation, e); } catch (IOException e) { LOG.error("Problem running script " + scriptLocation, e); } catch (SQLException e) { LOG.error("Problem running script " + scriptLocation, e); } catch (ProxoolException e) { LOG.error("Problem running script " + scriptLocation, e); } } } /* Revision history: $Log: ScriptFacade.java,v $ Revision 1.12 2006/01/18 14:40:05 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.10 2003/02/19 15:14:21 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.9 2003/02/06 17:41:02 billhorsman now uses imported logging Revision 1.8 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.7 2002/11/13 20:23:35 billhorsman change method name, throw exceptions differently, trivial changes Revision 1.6 2002/11/09 16:00:21 billhorsman fix doc Revision 1.5 2002/11/07 19:08:54 billhorsman Fixed up tests a bit Revision 1.4 2002/11/06 21:06:21 billhorsman Support for CommandFilterIF Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.1 2002/11/02 11:29:53 billhorsman new script runner for testing */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/dbscript/ScriptRunner.java0000644000175000017500000001035110730503127031072 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.dbscript; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolException; import java.sql.SQLException; /** * Run a {@link Script script}. * * @version $Revision: 1.12 $, $Date: 2006/01/18 14:40:05 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class ScriptRunner { private static final Log LOG = LogFactory.getLog(ScriptRunner.class); /** * Run the script. * * @param script to run * @param adapter so we know where to connections from * @throws SQLException if anything goes wrong */ protected static final void runScript(Script script, ConnectionAdapterIF adapter, CommandFilterIF commandFilter) throws SQLException, ProxoolException { adapter.setup(script.getDriver(), script.getUrl(), script.getInfo()); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use Options | File Templates. } Command[] commands = script.getCommands(); for (int i = 0; i < commands.length; i++) { Command command = commands[i]; long start = System.currentTimeMillis(); // Execute the SQL Commander[] commanders = new Commander[command.getLoad()]; for (int load = 0; load < command.getLoad(); load++) { commanders[load] = new Commander(adapter, command, commandFilter); Thread t = new Thread(commanders[load]); t.setName(script.getName() + "." + command.getName() + "." + load); t.start(); } while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { LOG.error("Awoken from sleep", e); } int remaining = command.getLoad(); for (int load = 0; load < command.getLoad(); load++) { if (commanders[load].isFinished()) { remaining--; } } if (remaining > 0) { // LOG.debug("Waiting for " + remaining + " threads to complete."); } else { break; } } long elapsed = System.currentTimeMillis() - start; int count = command.getLoad() * command.getLoops(); double lap = (double) elapsed / (double) count; if (count > 1) { LOG.info(adapter.getName() + ":" + command.getName() + " ran " + count + " commands in " + elapsed + " milliseconds (avg." + lap + ")"); } else { LOG.debug(adapter.getName() + ":" + command.getName() + " ran in " + elapsed + " milliseconds"); } } } } /* Revision history: $Log: ScriptRunner.java,v $ Revision 1.12 2006/01/18 14:40:05 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.10 2003/02/19 15:14:21 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.9 2003/02/06 17:41:02 billhorsman now uses imported logging Revision 1.8 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.7 2002/11/09 16:00:34 billhorsman fix doc Revision 1.6 2002/11/09 14:45:07 billhorsman now threaded and better exception handling Revision 1.5 2002/11/06 21:07:14 billhorsman Support for CommandFilterIF Revision 1.4 2002/11/02 14:22:16 billhorsman Documentation Revision 1.3 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.2 2002/11/02 12:45:54 billhorsman improved debug Revision 1.1 2002/11/02 11:29:53 billhorsman new script runner for testing */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/0000755000175000017500000000000011054125603025460 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/0000755000175000017500000000000011054125603026550 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/0000755000175000017500000000000011054125603027346 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/AbstractJMXTest.java0000644000175000017500000000376710730503130033203 0ustar twernertwernerpackage org.logicalcobwebs.proxool.admin.jmx; import java.util.Properties; import java.sql.SQLException; import java.sql.DriverManager; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.TestHelper; import org.logicalcobwebs.proxool.TestConstants; import org.logicalcobwebs.proxool.ProxoolConstants; /** * Parent class for the JMX tests. * * @version $Revision: 1.1 $, $Date: 2003/10/20 07:40:44 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: chr32 $ (current maintainer) * @since Proxool 0.8 */ public class AbstractJMXTest extends AbstractProxoolTest { /** * @see junit.framework.TestCase#TestCase(java.lang.String) */ public AbstractJMXTest(String alias) { super(alias); } /** * Create a very basic Proxool pool. * @param alias the alias of the pool * @return the properties used to create the pool. * @throws SQLException if the pool creation fails. */ protected Properties createBasicPool(String alias) throws SQLException { final String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); final Properties info = createBasicProperties(alias); DriverManager.getConnection(url, info).close(); return info; } /** * Create some very basic Proxool configuration. * @param alias the alias of the pool to be configured. * @return the created properties. */ protected Properties createBasicProperties(String alias) { final Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.JMX_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, alias); return info; } } libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/AllTests.java0000644000175000017500000000321010730503131031734 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.jmx; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; import org.logicalcobwebs.proxool.GlobalTest; /** * Run all tests in the jmx package. * * @version $Revision: 1.5 $, $Date: 2003/10/20 07:40:44 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: chr32 $ (current maintainer) * @since Proxool 0.8 */ public class AllTests { /** * Create a composite test of all the tests in the jmx package. * @return test suite */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(ConnectionPoolMBeanTest.class); suite.addTestSuite(MultipleAgentsConnectionPoolMBeanTest.class); // create a wrapper for global initialization code. TestSetup wrapper = new TestSetup(suite) { public void setUp() throws Exception { GlobalTest.globalSetup(); } }; return wrapper; } } /* Revision history: $Log: AllTests.java,v $ Revision 1.5 2003/10/20 07:40:44 chr32 Improved tests. Revision 1.4 2003/05/06 23:17:12 chr32 Moving JMX tests back in from sandbox. Revision 1.1 2003/03/07 16:35:17 billhorsman moved jmx stuff into sandbox until it is tested Revision 1.2 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.1 2003/02/26 19:03:43 chr32 Init rev. */ ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/ConnectionPoolMBeanTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/ConnectionPoolMBeanTes0000644000175000017500000002775610730503130033615 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.jmx; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolDriver; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.Notification; import javax.management.NotificationFilter; import javax.management.NotificationFilterSupport; import javax.management.NotificationListener; import javax.management.ObjectName; import java.util.Iterator; import java.util.Properties; /** * Test {@link org.logicalcobwebs.proxool.admin.jmx.ConnectionPoolMBean}. * * @version $Revision: 1.10 $, $Date: 2003/10/20 07:40:44 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: chr32 $ (current maintainer) * @since Proxool 0.8 */ public class ConnectionPoolMBeanTest extends AbstractJMXTest { private MBeanServer mBeanServer; private boolean notified; /** * @see junit.framework.TestCase#TestCase(java.lang.String) */ public ConnectionPoolMBeanTest(String s) { super(s); } /** * Test that an attribute can be fetched from the MBean. * @throws java.lang.Exception if an error occours. */ public void testGetAttribute() throws Exception { final String alias = "testGetAttribute"; createBasicPool(alias); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); final String fatalSql = (String) this.mBeanServer.getAttribute(objectName, ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.FATAL_SQL_EXCEPTION)); assertTrue("Expected fatalSQLException to be '" + alias + "', but it was '" + fatalSql + "'. ", fatalSql.equals(alias)); ProxoolFacade.removeConnectionPool(alias); } /** * Test that a list attributes can be fetched from the MBean. * @throws java.lang.Exception if an error occours. */ public void testGetAttributes() throws Exception { final String alias = "testGetAttributes"; createBasicPool(alias); final String fatalSQLAttribute = ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.FATAL_SQL_EXCEPTION); final String aliasAttribute = ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.ALIAS); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); final AttributeList attributes = this.mBeanServer.getAttributes(objectName, new String[]{ fatalSQLAttribute, aliasAttribute }); String fatalSqlValue = null; String aliasValue = null; Iterator attributeIterator = attributes.iterator(); while (attributeIterator.hasNext()) { Attribute attribute = (Attribute) attributeIterator.next(); if (attribute.getName().equals(aliasAttribute)) { aliasValue = (String) attribute.getValue(); } else if (attribute.getName().equals(fatalSQLAttribute)) { fatalSqlValue = (String) attribute.getValue(); } } assertNotNull("The value for the alias attribute is missing.", aliasValue); assertNotNull("The value for the fatalSQLException attribute is missing.", fatalSqlValue); assertTrue("Expeted alias to have value '" + aliasValue + "' but the value was '" + aliasValue + ".", aliasValue.equals(alias)); assertTrue("Expexted fatalSQLException to have value '" + alias + "' but the value was '" + fatalSqlValue + ".", fatalSqlValue.equals(alias)); ProxoolFacade.removeConnectionPool(alias); } /** * Test that an attribute can be fetched from the MBean. * @throws java.lang.Exception if an error occours. */ public void testSetAttribute() throws Exception { String alias = "testSetAttribute"; createBasicPool(alias); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); final String fatalSQLAttributeName = ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.FATAL_SQL_EXCEPTION); final String newValue = "dingo"; this.mBeanServer.setAttribute(objectName, new Attribute(fatalSQLAttributeName, newValue)); String fatalSQLAttribtueValue = (String) mBeanServer.getAttribute(objectName, fatalSQLAttributeName); // check that value vas registered by the bean. assertTrue("Expexted fatalSQLException JMX attribtue to have value '" + newValue + "' but the value was '" + fatalSQLAttribtueValue + "'.", fatalSQLAttribtueValue.equals(newValue)); // check that the bean updated the pool. final String proxoolProopertyValue = (String) ProxoolFacade.getConnectionPoolDefinition(alias) .getFatalSqlExceptions().toArray()[0]; assertTrue("Expexted fatal-sql-exception Proxool property to have value '" + newValue + "' but the value was '" + proxoolProopertyValue + "'.", proxoolProopertyValue.equals(newValue)); // check that string properites can be deleted. this.mBeanServer.setAttribute(objectName, new Attribute(fatalSQLAttributeName, "")); fatalSQLAttribtueValue = (String) mBeanServer.getAttribute(objectName, fatalSQLAttributeName); assertTrue("Expexted fatal-sql-exception Proxool property to be empty " + " but the value was '" + fatalSQLAttribtueValue + "'.", "".equals(fatalSQLAttribtueValue)); ProxoolFacade.removeConnectionPool(alias); } public void testSetAttributes() throws Exception { String alias = "testSetAttributes"; createBasicPool(alias); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); final String fatalSQLAttributeName = ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.FATAL_SQL_EXCEPTION); final String testSQLAttributeName = ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.HOUSE_KEEPING_TEST_SQL); final String newValue = "dingo"; // test when updated through JMX. final AttributeList attributeList = new AttributeList(); attributeList.add(new Attribute(fatalSQLAttributeName, newValue)); attributeList.add(new Attribute(testSQLAttributeName, newValue)); this.mBeanServer.setAttributes(objectName, attributeList); final String fatalSQLAttribtueValue = (String) mBeanServer.getAttribute(objectName, fatalSQLAttributeName); final String testSQLAttribtueValue = (String) mBeanServer.getAttribute(objectName, testSQLAttributeName); // check that values vas registered by the bean. assertTrue("Expexted fatalSQLException JMX attribtue to have value '" + newValue + "' but the value was '" + fatalSQLAttribtueValue + "'.", fatalSQLAttribtueValue.equals(newValue)); assertTrue("Expexted housekeeperTestSQL JMX attribtue to have value '" + newValue + "' but the value was '" + testSQLAttribtueValue + "'.", testSQLAttribtueValue.equals(newValue)); // check that the bean updated the pool. final String fatalSQLProxoolPropertyValue = (String) ProxoolFacade.getConnectionPoolDefinition(alias) .getFatalSqlExceptions().toArray()[0]; final String testSQLProxoolPropertyValue = ProxoolFacade.getConnectionPoolDefinition(alias) .getHouseKeepingTestSql(); assertTrue("Expexted fatal-sql-exception Proxool property to have value '" + newValue + "' but the value was '" + fatalSQLProxoolPropertyValue + ".", fatalSQLProxoolPropertyValue.equals(newValue)); assertTrue("Expexted housekeeper-test-sql Proxool property to have value '" + newValue + "' but the value was '" + testSQLProxoolPropertyValue + ".", testSQLProxoolPropertyValue.equals(newValue)); ProxoolFacade.removeConnectionPool(alias); } public void testInvokeShutown() throws Exception { final String alias = "testInvokeShutown"; createBasicPool(alias); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); this.mBeanServer.invoke(objectName, "shutdown", new Object[0], new String[0]); try { ProxoolFacade.removeConnectionPool(alias); fail("Removal of pool alias should have failed, because it should have already be removed."); } catch (ProxoolException e) { // we want this } } public void testNotification() throws Exception { String alias = "testNotification"; Properties info = createBasicPool(alias); final NotificationListener notificationListener = new TestNotificationListener(); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); this.mBeanServer.addNotificationListener(objectName, notificationListener, getFilter(), notificationListener); // test when updated through JMX. this.mBeanServer.setAttribute(objectName, new Attribute(ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.FATAL_SQL_EXCEPTION), "dingo")); assertTrue("We did not get notified when updating through JMX.", this.notified); this.notified = false; // test when updated through ProxoolFacade info = (Properties) info.clone(); info.put(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); ProxoolFacade.updateConnectionPool(ProxoolConstants.PROPERTY_PREFIX + alias, info); assertTrue("We did not get notified when updating through ProxoolFacade.", this.notified); ProxoolFacade.removeConnectionPool(alias); } private class TestNotificationListener implements NotificationListener { public void handleNotification(Notification notification, Object handBack) { if (handBack.equals(this)) { notified = true; } else { fail("Got notification with unknown handback."); } } } private NotificationFilter getFilter() { final NotificationFilterSupport notificationFilter = new NotificationFilterSupport(); notificationFilter.enableType(ConnectionPoolMBean.NOTIFICATION_TYPE_DEFINITION_UPDATED); return notificationFilter; } /** * Calls {@link org.logicalcobwebs.proxool.AbstractProxoolTest#setUp} * @see junit.framework.TestCase#setUp */ protected void setUp() throws Exception { this.notified = false; Class.forName(ProxoolDriver.class.getName()); this.mBeanServer = MBeanServerFactory.createMBeanServer(); super.setUp(); } /** * Calls {@link org.logicalcobwebs.proxool.AbstractProxoolTest#tearDown} * @see junit.framework.TestCase#setUp */ protected void tearDown() throws Exception { MBeanServerFactory.releaseMBeanServer(this.mBeanServer); this.mBeanServer = null; super.tearDown(); } } /* Revision history: $Log: ConnectionPoolMBeanTest.java,v $ Revision 1.10 2003/10/20 07:40:44 chr32 Improved tests. Revision 1.9 2003/05/06 23:17:12 chr32 Moving JMX tests back in from sandbox. Revision 1.1 2003/03/07 16:35:18 billhorsman moved jmx stuff into sandbox until it is tested Revision 1.7 2003/03/04 10:58:45 billhorsman checkstyle Revision 1.6 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.5 2003/03/03 17:09:09 billhorsman all tests now extend AbstractProxoolTest Revision 1.4 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.3 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.2 2003/02/28 12:53:59 billhorsman move database to db directory and use constants where possible Revision 1.1 2003/02/26 19:03:43 chr32 Init rev. */ ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/MultipleAgentsConnectionPoolMBeanTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/jmx/MultipleAgentsConnecti0000644000175000017500000001067410730503131033715 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin.jmx; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolDriver; import org.logicalcobwebs.proxool.TestConstants; import org.logicalcobwebs.proxool.TestHelper; import org.logicalcobwebs.proxool.ProxoolFacade; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * Test {@link org.logicalcobwebs.proxool.admin.jmx.ConnectionPoolMBean} when JMX is configured for multiple agents. * * @version $Revision: 1.1 $, $Date: 2003/10/20 07:40:44 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: chr32 $ (current maintainer) * @since Proxool 0.8 */ public class MultipleAgentsConnectionPoolMBeanTest extends AbstractJMXTest { private static final String AGENT1_DOMAIN = "testAgent1"; private static final String AGENT2_DOMAIN = "testAgent2"; private MBeanServer mBeanServer1; private MBeanServer mBeanServer2; private String mBeanServer1Id; private String mBeanServer2Id; /** * @see junit.framework.TestCase#TestCase(java.lang.String) */ public MultipleAgentsConnectionPoolMBeanTest(String s) { super(s); } /** * Test that pools can be regisered for multiple agents. * @throws Exception if the test fails in an unexpected way. */ public void testMultipleAgents() throws Exception { final String alias = "testMultipleAgents"; createMutipleAgentBasicPool(alias); final ObjectName objectName = ProxoolJMXHelper.getObjectName(alias); final String fatalSQLAttributeName = ProxoolJMXHelper.getValidIdentifier(ProxoolConstants.FATAL_SQL_EXCEPTION); String fatalSQLAttribtueValue = (String) mBeanServer1.getAttribute(objectName, fatalSQLAttributeName); assertTrue("Agent " + AGENT1_DOMAIN + " could not find " + fatalSQLAttribtueValue + " attribute.", fatalSQLAttribtueValue != null && fatalSQLAttribtueValue.trim().length() > 0); fatalSQLAttribtueValue = (String) mBeanServer2.getAttribute(objectName, fatalSQLAttributeName); assertTrue("Agent " + AGENT2_DOMAIN + " could not find " + fatalSQLAttribtueValue + " attribute.", fatalSQLAttribtueValue != null && fatalSQLAttribtueValue.trim().length() > 0); ProxoolFacade.removeConnectionPool(alias); } private Properties createMutipleAgentBasicPool(String alias) throws SQLException { final String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); final Properties info = createBasicProperties(alias); info.setProperty(ProxoolConstants.JMX_AGENT_PROPERTY, mBeanServer1Id + ", " + mBeanServer2Id); DriverManager.getConnection(url, info).close(); return info; } /** * Calls {@link org.logicalcobwebs.proxool.AbstractProxoolTest#setUp} * @see junit.framework.TestCase#setUp */ protected void setUp() throws Exception { Class.forName(ProxoolDriver.class.getName()); this.mBeanServer1 = MBeanServerFactory.createMBeanServer(AGENT1_DOMAIN); this.mBeanServer1Id = this.mBeanServer1.getAttribute( new ObjectName("JMImplementation:type=MBeanServerDelegate"), "MBeanServerId").toString(); this.mBeanServer2 = MBeanServerFactory.createMBeanServer(AGENT2_DOMAIN); this.mBeanServer2Id = this.mBeanServer2.getAttribute( new ObjectName("JMImplementation:type=MBeanServerDelegate"), "MBeanServerId").toString(); super.setUp(); } /** * Calls {@link org.logicalcobwebs.proxool.AbstractProxoolTest#tearDown} * @see junit.framework.TestCase#setUp */ protected void tearDown() throws Exception { MBeanServerFactory.releaseMBeanServer(this.mBeanServer1); MBeanServerFactory.releaseMBeanServer(this.mBeanServer2); this.mBeanServer1 = null; this.mBeanServer2 = null; super.tearDown(); } } /* Revision history: $Log: MultipleAgentsConnectionPoolMBeanTest.java,v $ Revision 1.1 2003/10/20 07:40:44 chr32 Improved tests. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/AllTests.java0000644000175000017500000000367310730503131031153 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; import org.logicalcobwebs.proxool.GlobalTest; /** * Run all in admin package tests * * @version $Revision: 1.5 $, $Date: 2003/03/07 16:35:09 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class AllTests { /** * Create a composite test of all admin package tests * @return test suite */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(StatisticsListenerTest.class); suite.addTestSuite(StatisticsTest.class); suite.addTestSuite(SnapshotTest.class); // create a wrapper for global initialization code. TestSetup wrapper = new TestSetup(suite) { public void setUp() throws Exception { GlobalTest.globalSetup(); } }; return wrapper; } } /* Revision history: $Log: AllTests.java,v $ Revision 1.5 2003/03/07 16:35:09 billhorsman moved jmx stuff into sandbox until it is tested Revision 1.4 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.3 2003/02/26 19:03:08 chr32 Added suite for JMX tests. Revision 1.2 2003/02/26 11:53:17 billhorsman added StatisticsTest and SnapshotTest Revision 1.1 2003/02/20 00:33:15 billhorsman renamed monitor package -> admin Revision 1.3 2003/02/19 23:36:50 billhorsman renamed monitor package to admin Revision 1.2 2003/02/19 15:14:28 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2003/02/07 15:10:36 billhorsman new admin tests */ ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/SnapshotResultMonitor.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/SnapshotResultMonitor.java0000644000175000017500000000405310730503131033757 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.ResultMonitor; /** * A ResultMonitor specifically for Snapshots * * @version $Revision: 1.4 $, $Date: 2003/03/03 11:12:05 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public abstract class SnapshotResultMonitor extends ResultMonitor { private SnapshotIF snapshot; private String alias; /** * @param alias so we can lookup the latest {@link SnapshotIF snapshot} */ public SnapshotResultMonitor(String alias) { this.alias = alias; } /** * Passes the latest snapshot to {@link #check(org.logicalcobwebs.proxool.admin.SnapshotIF) check}. * @return {@link #SUCCESS} or {@link #TIMEOUT} * @throws Exception if anything goes wrong */ public boolean check() throws Exception { snapshot = ProxoolFacade.getSnapshot(alias); return check(snapshot); } /** * Override this with your specific check * @param snapshot the latest snapshot * @return true if the result has happened, else false * @throws Exception if anything goes wrong */ public abstract boolean check(SnapshotIF snapshot) throws Exception; /** * Get the snapshot used in the most recent {@link #check(org.logicalcobwebs.proxool.admin.SnapshotIF) check} * @return snapshot */ public SnapshotIF getSnapshot() { return snapshot; } } /* Revision history: $Log: SnapshotResultMonitor.java,v $ Revision 1.4 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.3 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.2 2003/03/01 15:22:50 billhorsman doc Revision 1.1 2003/03/01 15:14:14 billhorsman new ResultMonitor to help cope with test threads */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/SnapshotTest.java0000644000175000017500000001451610730503130032054 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ConnectionInfoIF; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.TestConstants; import org.logicalcobwebs.proxool.TestHelper; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.util.Properties; /** * Test {@link SnapshotIF} * * @version $Revision: 1.14 $, $Date: 2006/01/18 14:40:05 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class SnapshotTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(SnapshotTest.class); /** * @see junit.framework.TestCase#TestCase */ public SnapshotTest(String s) { super(s); } /** * Test whether the statistics we get back are roughly right. */ public void testSnapshot() throws Exception { String testName = "snapshot"; final String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, "10s,15s"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "1"); info.setProperty(ProxoolConstants.TRACE_PROPERTY, "true"); // We don't test whether anything is logged, but this line should make something appear info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_DEBUG); // Register pool ProxoolFacade.registerConnectionPool(url, info); { Connection connection = DriverManager.getConnection(url); connection.createStatement().execute(TestConstants.HYPERSONIC_TEST_SQL); connection.close(); SnapshotIF snapshot = ProxoolFacade.getSnapshot(alias, true); assertEquals("servedCount", 1L, snapshot.getServedCount()); assertEquals("refusedCount", 0L, snapshot.getRefusedCount()); assertEquals("activeConnectionCount", 0, snapshot.getActiveConnectionCount()); ConnectionInfoIF[] connectionInfos = snapshot.getConnectionInfos(); assertTrue("connectionInfos.length != 0", connectionInfos.length != 0); assertEquals("connectionInfos activeCount", 0, getCount(connectionInfos, ConnectionInfoIF.STATUS_ACTIVE)); assertEquals("connectionInfos sql count", 1, connectionInfos[0].getSqlCalls().length); assertEquals("connectionInfos lastSql", TestConstants.HYPERSONIC_TEST_SQL, connectionInfos[0].getSqlCalls()[0].replace(';', ' ').trim()); } { Connection connection = DriverManager.getConnection(url); connection.createStatement().execute(TestConstants.HYPERSONIC_TEST_SQL); connection.createStatement().execute(TestConstants.HYPERSONIC_TEST_SQL_2); SnapshotIF snapshot = ProxoolFacade.getSnapshot(alias, true); assertEquals("servedCount", 2L, snapshot.getServedCount()); assertEquals("refusedCount", 0L, snapshot.getRefusedCount()); assertEquals("activeConnectionCount", 1, snapshot.getActiveConnectionCount()); ConnectionInfoIF[] connectionInfos = snapshot.getConnectionInfos(); assertTrue("connectionInfos.length != 0", connectionInfos.length != 0); assertEquals("connectionInfos activeCount", 1, getCount(connectionInfos, ConnectionInfoIF.STATUS_ACTIVE)); assertEquals("connectionInfos sql count", 2, connectionInfos[0].getSqlCalls().length); assertEquals("connectionInfos lastSql", TestConstants.HYPERSONIC_TEST_SQL, connectionInfos[0].getSqlCalls()[0].replace(';', ' ').trim()); assertEquals("connectionInfos lastSql", TestConstants.HYPERSONIC_TEST_SQL_2, connectionInfos[0].getSqlCalls()[1].replace(';', ' ').trim()); connection.close(); } } private int getCount(ConnectionInfoIF[] connectionInfos, int status) { int count = 0; for (int i = 0; i < connectionInfos.length; i++) { if (connectionInfos[i].getStatus() == status) { count++; } } return count; } } /* Revision history: $Log: SnapshotTest.java,v $ Revision 1.14 2006/01/18 14:40:05 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.13 2005/10/07 08:13:46 billhorsman Test new sqlCalls property of snapshot Revision 1.12 2003/03/10 23:46:43 billhorsman checkstyle Revision 1.11 2003/03/06 14:25:53 billhorsman fix for threading Revision 1.10 2003/03/06 11:31:17 billhorsman fix for unlikely prototyper situation Revision 1.8 2003/03/04 10:58:44 billhorsman checkstyle Revision 1.7 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.6 2003/03/03 17:09:08 billhorsman all tests now extend AbstractProxoolTest Revision 1.5 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.4 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.3 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.2 2003/02/26 16:05:51 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.1 2003/02/20 00:33:15 billhorsman renamed monitor package -> admin Revision 1.3 2003/02/19 23:36:50 billhorsman renamed monitor package to admin Revision 1.2 2003/02/19 15:14:29 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2003/02/07 17:28:36 billhorsman *** empty log message *** */ ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/StatisticsListenerTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/StatisticsListenerTest.jav0000644000175000017500000001443210730503131033752 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.TestConstants; import org.logicalcobwebs.proxool.TestHelper; import java.sql.DriverManager; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; /** * Test {@link StatisticsListenerIF} * * @version $Revision: 1.13 $, $Date: 2006/01/18 14:40:05 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class StatisticsListenerTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(StatisticsListenerTest.class); /** * HH:mm:ss */ private static final DateFormat TIME_FORMAT = new SimpleDateFormat("mm:ss"); /** * @see junit.framework.TestCase#TestCase */ public StatisticsListenerTest(String s) { super(s); } /** * Can we listen to statistics */ public void testListener() throws Exception { String testName = "listener"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, "5s"); // We don't test whether anything is logged, but this line should make something appear info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_DEBUG); // Register pool ProxoolFacade.registerConnectionPool(url, info); // Add listener TestListener testListener = new TestListener(); ProxoolFacade.addStatisticsListener(alias, testListener); Date lap0 = new Date(); // Wait for next statistics1 so we can guarantee that next set won't // be produced whilst we are building connection testListener.getNextStatistics(); Date lap1 = new Date(); DriverManager.getConnection(url).close(); Date lap2 = new Date(); StatisticsIF statistics1 = testListener.getNextStatistics(); Date lap3 = new Date(); StatisticsIF statistics2 = testListener.getNextStatistics(); Date lap4 = new Date(); StringBuffer detail = new StringBuffer(); detail.append("lap0:"); detail.append(TIME_FORMAT.format(lap0)); detail.append(", lap1:"); detail.append(TIME_FORMAT.format(lap1)); detail.append(", lap2:"); detail.append(TIME_FORMAT.format(lap2)); detail.append(", lap3:"); detail.append(TIME_FORMAT.format(lap3)); detail.append("("); detail.append(statistics1.getServedCount()); detail.append("), lap4:"); detail.append(TIME_FORMAT.format(lap4)); detail.append("("); detail.append(statistics2.getServedCount()); detail.append(")"); assertEquals("servedCount - " + detail, 1L, statistics1.getServedCount()); } class TestListener implements StatisticsListenerIF { private StatisticsIF statistics; private boolean somethingHappened; public void statistics(String alias, StatisticsIF statistics) { this.statistics = statistics; somethingHappened = true; } void reset() { statistics = null; somethingHappened = false; } public StatisticsIF getStatistics() { return statistics; } void waitForSomethingToHappen() { long start = System.currentTimeMillis(); while (!somethingHappened) { try { Thread.sleep(500); } catch (InterruptedException e) { LOG.error("Awoken", e); } if (System.currentTimeMillis() - start > 30000) { fail("Timeout waiting for something to happen"); } } } StatisticsIF getNextStatistics() { somethingHappened = false; waitForSomethingToHappen(); return statistics; } } } /* Revision history: $Log: StatisticsListenerTest.java,v $ Revision 1.13 2006/01/18 14:40:05 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.12 2003/09/05 16:27:27 billhorsman Better debug output. Revision 1.11 2003/03/04 10:58:44 billhorsman checkstyle Revision 1.10 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.9 2003/03/03 17:09:08 billhorsman all tests now extend AbstractProxoolTest Revision 1.8 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.7 2003/03/01 15:49:33 billhorsman fix Revision 1.6 2003/03/01 15:38:38 billhorsman better assert msg Revision 1.5 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.4 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.3 2003/02/27 09:45:33 billhorsman sleep a little Revision 1.2 2003/02/26 16:05:51 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.1 2003/02/20 00:33:15 billhorsman renamed monitor package -> admin Revision 1.5 2003/02/19 23:36:50 billhorsman renamed monitor package to admin Revision 1.4 2003/02/19 15:14:30 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.3 2003/02/07 17:28:23 billhorsman checkstyle and doc Revision 1.2 2003/02/07 15:11:33 billhorsman checkstyle Revision 1.1 2003/02/07 15:10:37 billhorsman new admin tests */ ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/StatisticsResultMonitor.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/StatisticsResultMonitor.ja0000644000175000017500000000713110730503131033763 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.ResultMonitor; /** * A ResultMonitor specifically for Snapshots * * @version $Revision: 1.10 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class StatisticsResultMonitor extends ResultMonitor { private static final Log LOG = LogFactory.getLog(StatisticsResultMonitor.class); private StatisticsIF statistics; private StatisticsIF oldStatistics; private String alias; private String token; /** * @param alias so we can lookup the latest {@link StatisticsIF statistics} * @param token so we can lookup the latest {@link StatisticsIF statistics} */ public StatisticsResultMonitor(String alias, String token) { this.alias = alias; this.token = token; setDelay(2000); } /** * waits for statistics * @return {@link #SUCCESS} or {@link #TIMEOUT} * @throws Exception if anything goes wrong */ public boolean check() throws Exception { statistics = ProxoolFacade.getStatistics(alias, token); if (statistics == null) { return false; } else if (oldStatistics == null) { return check(statistics); } else { if (!statistics.getStartDate().equals(oldStatistics.getStartDate())) { return check(statistics); } else { return false; } } } /** * This gets called when we get new statistics. By overriding this * method you get the option of rejecting these new statistics and * waiting for the next set * @param statistics the newly created statistics * @return true if we accept them, false if we want to wait for the next set * (if you don't override this it will return true) */ protected boolean check(StatisticsIF statistics) { return true; } public int getResult() throws ProxoolException { oldStatistics = statistics; return super.getResult(); } /** * Get the statistics used in the most recent {@link #check check} * @return snapshot */ public StatisticsIF getStatistics() { return statistics; } } /* Revision history: $Log: StatisticsResultMonitor.java,v $ Revision 1.10 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.9 2003/03/06 22:39:05 billhorsman fix Revision 1.8 2003/03/06 22:28:32 billhorsman another go at statistics threading (in tests) Revision 1.7 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.6 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.5 2003/03/01 18:17:50 billhorsman arrffgh. fix, Revision 1.4 2003/03/01 16:53:07 billhorsman fix Revision 1.3 2003/03/01 16:38:40 billhorsman fix Revision 1.2 2003/03/01 16:18:31 billhorsman fix Revision 1.1 2003/03/01 16:07:26 billhorsman helper Revision 1.3 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.2 2003/03/01 15:22:50 billhorsman doc Revision 1.1 2003/03/01 15:14:14 billhorsman new ResultMonitor to help cope with test threads */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/admin/StatisticsTest.java0000644000175000017500000001550410730503131032406 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.ResultMonitor; import org.logicalcobwebs.proxool.TestConstants; import org.logicalcobwebs.proxool.TestHelper; import java.sql.DriverManager; import java.text.DecimalFormat; import java.util.Properties; /** * Test {@link StatisticsIF} * * @version $Revision: 1.22 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class StatisticsTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(StatisticsTest.class); private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); /** * @see junit.framework.TestCase#TestCase */ public StatisticsTest(String s) { super(s); } /** * Test whether the statistics we get back are roughly right. */ public void testStatistics() throws Exception { String testName = "statistics"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, "10s,15s"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "1"); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); // We don't test whether anything is logged, but this line should make something appear info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_DEBUG); // Register pool ProxoolFacade.registerConnectionPool(url, info); // Skip past the first set because they will probably be for only part // of the 10s period. StatisticsResultMonitor srm = new StatisticsResultMonitor(alias, "10s"); assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); srm.getStatistics(); DriverManager.getConnection(url).close(); srm = new StatisticsResultMonitor(alias, "10s") { protected boolean check(StatisticsIF statistics) { return (statistics.getServedCount() == 1); } }; assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); StatisticsIF statistics = srm.getStatistics(); assertEquals("servedCount", 1L, statistics.getServedCount()); assertEquals("servedPerSecond", 0.09, 0.11, statistics.getServedPerSecond()); assertEquals("refusedCount", 0L, statistics.getRefusedCount()); } public void testOverhead() throws Exception { String testName = "overhead"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, "10s"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "1"); // We don't test whether anything is logged, but this line should make something appear info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_DEBUG); // Register pool ProxoolFacade.registerConnectionPool(url, info); ConnectionPoolDefinitionIF cpd = ProxoolFacade.getConnectionPoolDefinition(alias); Admin admin = new Admin(cpd); final int loops = 100000; long start = System.currentTimeMillis(); for (int i = 0; i < loops; i++) { admin.connectionReturned(10); } double avg = (double) (System.currentTimeMillis() - start) / (double) loops; LOG.info("Statistics take " + DECIMAL_FORMAT.format(avg * 1000) + " microseconds"); } } /* Revision history: $Log: StatisticsTest.java,v $ Revision 1.22 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.21 2003/03/06 22:28:31 billhorsman another go at statistics threading (in tests) Revision 1.20 2003/03/06 12:45:06 billhorsman switch on verbose logging Revision 1.19 2003/03/06 10:37:41 billhorsman better timeout assertion Revision 1.18 2003/03/04 10:58:44 billhorsman checkstyle Revision 1.17 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.16 2003/03/03 17:09:09 billhorsman all tests now extend AbstractProxoolTest Revision 1.15 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.14 2003/03/03 09:10:41 billhorsman removed debug Revision 1.13 2003/03/02 01:16:37 billhorsman removed flakey average active time test Revision 1.12 2003/03/01 18:25:53 billhorsman *** empty log message *** Revision 1.11 2003/03/01 16:46:08 billhorsman debug Revision 1.10 2003/03/01 16:14:32 billhorsman debug Revision 1.9 2003/03/01 16:04:45 billhorsman fix Revision 1.8 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.7 2003/02/28 12:36:33 billhorsman more robust waiting for statistics Revision 1.6 2003/02/28 12:23:59 billhorsman more robust waiting for statistics Revision 1.5 2003/02/27 18:01:49 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.4 2003/02/26 23:45:18 billhorsman add some sleep Revision 1.3 2003/02/26 18:30:02 billhorsman test for stats overhead Revision 1.2 2003/02/26 16:05:51 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.1 2003/02/20 00:33:15 billhorsman renamed monitor package -> admin Revision 1.3 2003/02/19 23:36:50 billhorsman renamed monitor package to admin Revision 1.2 2003/02/19 15:14:31 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2003/02/07 17:28:36 billhorsman *** empty log message *** */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/0000755000175000017500000000000011054125603030327 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/AllTests.java0000644000175000017500000000462610730503130032730 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; import org.logicalcobwebs.proxool.GlobalTest; /** * Run all tests * * @version $Revision: 1.7 $, $Date: 2003/03/03 11:12:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class AllTests { /** * Create a composite test of all Proxool configuration tests. * * @return a composite test of all Proxool configuration tests. */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(ConfiguratorTest.class); suite.addTestSuite(PropertyConfiguratorTest.class); suite.addTestSuite(JAXPConfiguratorTest.class); suite.addTestSuite(AvalonConfiguratorTest.class); // create a wrapper for global initialization code. TestSetup wrapper = new TestSetup(suite) { public void setUp() throws Exception { GlobalTest.globalSetup(); } }; return wrapper; } } /* Revision history: $Log: AllTests.java,v $ Revision 1.7 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.6 2003/02/19 15:14:26 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.5 2002/12/26 11:35:32 billhorsman Added PropertyConfiguratorTest to test suite. Revision 1.4 2002/12/23 02:40:21 chr32 Doc. Revision 1.3 2002/12/18 03:13:51 chr32 Doc. Revision 1.2 2002/12/16 17:35:43 chr32 Removed redundant imports. Revision 1.1 2002/12/16 17:06:26 billhorsman new test structure Revision 1.7 2002/12/15 19:16:58 chr32 Added JAXPConfigurator test. Revision 1.6 2002/11/07 18:53:41 billhorsman slight improvement to setup Revision 1.5 2002/11/02 11:37:48 billhorsman New tests Revision 1.4 2002/10/28 21:37:54 billhorsman now allows for non-existent log4jPath Revision 1.3 2002/10/27 13:05:02 billhorsman checkstyle Revision 1.2 2002/10/27 12:03:33 billhorsman clear up of tests Revision 1.1 2002/10/25 10:41:07 billhorsman draft changes to test globalSetup */ ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/AvalonConfiguratorTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/AvalonConfigurator0000644000175000017500000002103710730503130034053 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.avalon.excalibur.component.DefaultRoleManager; import org.apache.avalon.excalibur.component.ExcaliburComponentManager; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.context.DefaultContext; import org.apache.log.Hierarchy; import org.apache.log.LogTarget; import org.apache.log.Logger; import org.apache.log.Priority; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.TestHelper; import java.io.File; /** * Tests that the AvalonConfgiuration works. * * @version $Revision: 1.10 $, $Date: 2003/03/04 10:58:45 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class AvalonConfiguratorTest extends AbstractProxoolTest { private ExcaliburComponentManager componentManager; /** * @see junit.framework.TestCase#TestCase */ public AvalonConfiguratorTest(String name) { super(name); } /** * Test that the configuration succeds and that all expected properties * has been received by Proxool. The configuration file does not use namspaces. * @throws org.apache.avalon.framework.component.ComponentException if the configuration fails. * @throws java.sql.SQLException if ProxoolFacade operation fails. */ public void testNoNamspaces() throws Exception { initializeAvalon("src/java-test/org/logicalcobwebs/proxool/configuration/role.conf", "src/java-test/org/logicalcobwebs/proxool/configuration/component.conf"); this.componentManager.lookup(AvalonConfigurator.ROLE); try { TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("avalon-test")); } catch (ProxoolException e) { throw e; } try { TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("avalon-test-2")); } catch (ProxoolException e) { throw e; } this.componentManager.dispose(); } /** * Test that the configuration succeds and that all expected properties * has been received by Proxool. The configuration file uses namspaces. * @throws Exception if the test is interrupted. */ public void testWithNamespaces() throws Exception { initializeAvalon("src/java-test/org/logicalcobwebs/proxool/configuration/role.conf", "src/java-test/org/logicalcobwebs/proxool/configuration/component-ns.conf"); this.componentManager.lookup(AvalonConfigurator.ROLE); try { TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("avalon-test-ns")); } catch (ProxoolException e) { throw e; } try { TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("avalon-test-ns-2")); } catch (ProxoolException e) { throw e; } ProxoolFacade.removeConnectionPool("avalon-test-ns"); ProxoolFacade.removeConnectionPool("avalon-test-ns-2"); this.componentManager.dispose(); } /** * Test that a configurator that does not have close-on-dispose="false" * closes the pools it has configured when it is disposed. * @throws Exception if the test is interrupted. */ public void testDisposeOnClose() throws Exception { initializeAvalon("src/java-test/org/logicalcobwebs/proxool/configuration/role.conf", "src/java-test/org/logicalcobwebs/proxool/configuration/component.conf"); this.componentManager.lookup(AvalonConfigurator.ROLE); this.componentManager.dispose(); try { ProxoolFacade.getConnectionPoolDefinition("avalon-test"); fail("ProxoolFacade found pool 'avalon-test' but we expected the configurator to have removed it."); } catch (ProxoolException e) { // This is what we want. } try { ProxoolFacade.getConnectionPoolDefinition("avalon-test-2"); fail("ProxoolFacade found pool 'avalon-test-2' but we expected the configurator to have removed it."); } catch (ProxoolException e) { // This is what we want. } } /** * Test that a configurator that does have close-on-dispose="false" * does not close the pools it has configured when it is disposed. * @throws Exception if the test is interrupted. */ public void testNotDisposeOnClose() throws Exception { initializeAvalon("src/java-test/org/logicalcobwebs/proxool/configuration/role.conf", "src/java-test/org/logicalcobwebs/proxool/configuration/component-ns.conf"); this.componentManager.lookup(AvalonConfigurator.ROLE); this.componentManager.dispose(); try { ProxoolFacade.getConnectionPoolDefinition("avalon-test-ns"); } catch (ProxoolException e) { fail("ProxoolFacade did not find pool 'avalon-test-ns' but we didn't expect the configurator to have removed it."); } try { ProxoolFacade.getConnectionPoolDefinition("avalon-test-ns-2"); } catch (ProxoolException e) { fail("ProxoolFacade did not find pool 'avalon-ns-test-2' but we didn't expect the configurator to have removed it."); } ProxoolFacade.removeConnectionPool("avalon-test-ns"); ProxoolFacade.removeConnectionPool("avalon-test-ns-2"); } private void initializeAvalon(String roleFile, String componentFile) throws Exception { // create a Avalon logger final LogTarget logTarget = new LogKitTargetAdapter(); final Logger rootLogger = Hierarchy.getDefaultHierarchy().getLoggerFor("root"); rootLogger.unsetLogTargets(); rootLogger.setLogTargets(new LogTarget[]{logTarget}); rootLogger.setPriority(Priority.WARN); final DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(true); // create component configuration final Configuration componentConfiguration = builder.buildFromFile(new File(componentFile)); // create role configuration final Configuration roleConfiguration = builder.buildFromFile(new File(roleFile)); // create and configure role and component managers. this.componentManager = new ExcaliburComponentManager(); this.componentManager.setLogger(rootLogger.getChildLogger(ExcaliburComponentManager.class.getName())); DefaultRoleManager roleManager = new DefaultRoleManager(); roleManager.setLogger(rootLogger.getChildLogger(DefaultRoleManager.class.getName())); roleManager.configure(roleConfiguration); componentManager.contextualize(new DefaultContext()); componentManager.setRoleManager(roleManager); componentManager.configure(componentConfiguration); componentManager.initialize(); } } /* Revision history: $Log: AvalonConfiguratorTest.java,v $ Revision 1.10 2003/03/04 10:58:45 billhorsman checkstyle Revision 1.9 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.8 2003/03/03 17:09:12 billhorsman all tests now extend AbstractProxoolTest Revision 1.7 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.6 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.5 2003/02/27 18:01:49 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.4 2003/02/19 16:52:00 chr32 Added tests for close-on-dispose functionality. Revision 1.3 2003/02/19 15:14:26 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.2 2002/12/23 02:48:07 chr32 Checkstyle. Revision 1.1 2002/12/23 02:40:49 chr32 Init rev. Revision 1.5 2002/12/18 03:13:00 chr32 Added tests for xml validation. Revision 1.4 2002/12/16 17:06:41 billhorsman new test structure Revision 1.3 2002/12/16 02:35:40 chr32 Updated to new driver-properties xml format. Revision 1.2 2002/12/15 19:41:26 chr32 Style fixes. Revision 1.1 2002/12/15 19:10:49 chr32 Init rev. */ ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/ConfiguratorTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/ConfiguratorTest.j0000644000175000017500000001035610730503130034004 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.TestConstants; import org.logicalcobwebs.proxool.TestHelper; import java.util.Properties; /** * Tests that the programatic configuration of Proxool works. * * @version $Revision: 1.16 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class ConfiguratorTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ConfiguratorTest.class); private static final String TEST_TABLE = "test"; /** * @see junit.framework.TestCase#TestCase */ public ConfiguratorTest(String name) { super(name); } public void testConfigurator() throws Exception { String testName = "configurator"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Properties newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "3"); ProxoolFacade.updateConnectionPool(url, newInfo); final ConnectionPoolDefinitionIF cpd = ProxoolFacade.getConnectionPoolDefinition(alias); assertNotNull("definition is null", cpd); assertEquals("prototypeCount", 3, cpd.getPrototypeCount()); } } /* Revision history: $Log: ConfiguratorTest.java,v $ Revision 1.16 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.15 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.14 2003/03/03 17:09:17 billhorsman all tests now extend AbstractProxoolTest Revision 1.13 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.12 2003/02/27 18:01:49 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.11 2003/02/19 15:14:26 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.10 2003/02/07 10:11:35 billhorsman fix Revision 1.9 2003/02/07 09:35:52 billhorsman changed alias for testConfigurator Revision 1.8 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.7 2003/01/22 17:35:03 billhorsman checkstyle Revision 1.6 2003/01/18 15:13:14 billhorsman Signature changes (new ProxoolException thrown) on the ProxoolFacade API. Revision 1.5 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.4 2002/12/26 11:35:02 billhorsman Removed test regarding property configurator. Revision 1.3 2002/12/16 17:06:53 billhorsman new test structure Revision 1.2 2002/12/15 19:41:28 chr32 Style fixes. Revision 1.1 2002/12/15 19:10:49 chr32 Init rev. Revision 1.4 2002/12/04 13:20:11 billhorsman ConfigurationListenerIF test Revision 1.3 2002/11/09 16:00:45 billhorsman fix doc Revision 1.2 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.1 2002/11/02 11:37:48 billhorsman New tests Revision 1.4 2002/10/29 23:17:38 billhorsman Cleaned up SQL stuff Revision 1.3 2002/10/27 13:05:02 billhorsman checkstyle Revision 1.2 2002/10/27 12:03:33 billhorsman clear up of tests Revision 1.1 2002/10/25 10:41:07 billhorsman draft changes to test globalSetup */ ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/JAXPConfiguratorTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/JAXPConfiguratorTe0000644000175000017500000002057710730503130033676 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ProxoolConstants; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.TestHelper; import org.xml.sax.InputSource; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.sql.DriverManager; import java.sql.SQLException; /** * Tests that the JAXPConfgiuration works in various scenarios. * This is also a test of the {@link XMLConfigurator}, as it is delegated to. * * @version $Revision: 1.16 $, $Date: 2003/08/30 14:54:23 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class JAXPConfiguratorTest extends AbstractProxoolTest { /** * @see junit.framework.TestCase#TestCase */ public JAXPConfiguratorTest(String name) { super(name); } /** * Test that the confguration succeds and that all expected properties * has been received by Proxool. This test is done with a * xml without namespaces and validiation. * @throws ProxoolException if the configuration fails. * @throws SQLException if ProxoolFacade operation fails. */ public void testNoNamspaces() throws ProxoolException, SQLException { final String xmlFile = "src/java-test/org/logicalcobwebs/proxool/configuration/test-no-ns.xml"; JAXPConfigurator.configure(xmlFile, false); try { assertNotNull("2nd (deeply nested) pool was not configured.", ProxoolFacade.getConnectionPoolDefinition("xml-test-2")); } catch (ProxoolException e) { fail("2nd (deeply nested) pool was not configured."); } TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("xml-test")); TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("xml-test-2")); } /** * Test that the confguration succeds and that all expected properties * has been received by Proxool. This test is done with a * xml with namespaces and without validiation. * @throws ProxoolException if the configuration fails. * @throws SQLException if ProxoolFacade operation fails. */ public void testWithNamspaces() throws ProxoolException, SQLException { final String xmlFile = "src/java-test/org/logicalcobwebs/proxool/configuration/test-ns.xml"; JAXPConfigurator.configure(xmlFile, false); try { assertNotNull("2nd (deeply nested) pool was not configured.", ProxoolFacade.getConnectionPoolDefinition("xml-test-ns-2")); } catch (ProxoolException e) { fail("2nd (deeply nested) pool was not configured."); } TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("xml-test-ns")); TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("xml-test-ns-2")); } /** * Test that the confguration succeds and that all expected properties * has been received by Proxool, and that validiation succceds. This test is done with a * xml without namespaces. * @throws ProxoolException if the configuration fails. * @throws SQLException if ProxoolFacade operation fails. * @throws FileNotFoundException if the xml file is not found. */ public void testValidiation() throws ProxoolException, SQLException, FileNotFoundException { final String xmlFile = "src/java-test/org/logicalcobwebs/proxool/configuration/test-valid.xml"; final InputSource inputSource = new InputSource(new FileInputStream(xmlFile)); inputSource.setSystemId(getWorkingDirectoryUrl()); JAXPConfigurator.configure(inputSource, true); try { assertNotNull("2nd (deeply nested) pool was not configured.", ProxoolFacade.getConnectionPoolDefinition("xml-test-validating-2")); } catch (ProxoolException e) { fail("2nd (deeply nested) pool was not configured."); } TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("xml-test-validating")); TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("xml-test-validating-2")); } /** * Test that we can retrieve a conncetion using the alias after registration * @throws ProxoolException if the configuration fails. * @throws SQLException if ProxoolFacade operation fails. * @throws FileNotFoundException if the xml file is not found. */ public void testWithAlias() throws ProxoolException, SQLException, FileNotFoundException { final String xmlFile = "src/java-test/org/logicalcobwebs/proxool/configuration/test-valid.xml"; final InputSource inputSource = new InputSource(new FileInputStream(xmlFile)); inputSource.setSystemId(getWorkingDirectoryUrl()); JAXPConfigurator.configure(inputSource, true); final String alias = "xml-test-validating"; DriverManager.getConnection(ProxoolConstants.PROXOOL + "." + alias).close(); } /** * Test that the confguration fails when validiation is turned on and the given xml is not valid. * @throws SQLException if ProxoolFacade operation fails. * @throws FileNotFoundException if the xml file is not found. */ public void testValidiationFailure() throws SQLException, FileNotFoundException, ProxoolException { final String xmlFile = "src/java-test/org/logicalcobwebs/proxool/configuration/test-not-valid.xml"; final InputSource inputSource = new InputSource(new FileInputStream(xmlFile)); inputSource.setSystemId(getWorkingDirectoryUrl()); boolean failure = false; try { JAXPConfigurator.configure(inputSource, true); } catch (ProxoolException e) { failure = true; } assertTrue("Configuration did not fail on unvalid xml document.", failure); } private static String getWorkingDirectoryUrl() { String userDir = System.getProperty("user.dir"); String toReplace = "\\"; String replaceWith = "/"; int pos = 0; if (!toReplace.equals(replaceWith)) { while (true) { pos = userDir.indexOf(toReplace, pos); if (pos == -1) { break; } userDir = userDir.substring(0, pos) + replaceWith + userDir.substring(pos + toReplace.length()); pos += replaceWith.length(); } } if (!userDir.startsWith("/")) { userDir = "/" + userDir; } if (!userDir.endsWith("/")) { userDir = userDir + "/"; } return "file://" + userDir; } } /* Revision history: $Log: JAXPConfiguratorTest.java,v $ Revision 1.16 2003/08/30 14:54:23 billhorsman Checkstyle Revision 1.15 2003/04/29 11:51:49 billhorsman added new "with-alias" test Revision 1.14 2003/03/04 10:58:45 billhorsman checkstyle Revision 1.13 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.12 2003/03/03 17:36:33 billhorsman leave shutdown to AbstractProxoolTest Revision 1.11 2003/03/03 17:09:18 billhorsman all tests now extend AbstractProxoolTest Revision 1.10 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.9 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.8 2003/02/27 18:01:49 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.7 2003/02/19 15:14:27 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.6 2003/01/18 15:13:14 billhorsman Signature changes (new ProxoolException thrown) on the ProxoolFacade API. Revision 1.5 2002/12/18 03:13:00 chr32 Added tests for xml validation. Revision 1.4 2002/12/16 17:06:41 billhorsman new test structure Revision 1.3 2002/12/16 02:35:40 chr32 Updated to new driver-properties xml format. Revision 1.2 2002/12/15 19:41:26 chr32 Style fixes. Revision 1.1 2002/12/15 19:10:49 chr32 Init rev. */ ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/LogKitTargetAdapter.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/LogKitTargetAdapte0000644000175000017500000001071110730503130033724 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.apache.avalon.framework.CascadingThrowable; import org.apache.log.LogEvent; import org.apache.log.Priority; import org.apache.log.output.AbstractOutputTarget; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * An Avalon LogKit target that delegates to a Jakarta Commons org.apache.commons.logging.Log. * Can be used to make Avalons internal logging go the same output as * the Proxool internal logging. * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:06 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class LogKitTargetAdapter extends AbstractOutputTarget { private boolean isOpen = true; /** * @see org.apache.log.output.AbstractOutputTarget#doProcessEvent(org.apache.log.LogEvent) */ protected void doProcessEvent(LogEvent event) { // we do a workaround for the fact that Avalon CascadingThrowables // does not print the stacktrace of any nested exceptions. // Also we 'upgrade' DEBUG LogEvents containing Throwables // to WARN since Avalon seems to give some important exceptions // DEBUG priority. Throwable originalThrowable = event.getThrowable(); Throwable nestedThrowable = null; if (originalThrowable != null && originalThrowable instanceof CascadingThrowable) { nestedThrowable = ((CascadingThrowable) originalThrowable).getCause(); } int priority = event.getPriority().getValue(); if (originalThrowable != null && event.getPriority().isLower(Priority.WARN)) { priority = Priority.WARN.getValue(); } Log logger = LogFactory.getLog(event.getCategory()); if (Priority.DEBUG.getValue() == priority) { if (logger.isDebugEnabled()) { logger.debug(event.getMessage(), originalThrowable); } if (nestedThrowable != null) { logger.debug("... caused by:", nestedThrowable); } } else if (Priority.INFO.getValue() == priority) { if (logger.isInfoEnabled()) { logger.info(event.getMessage(), originalThrowable); } if (nestedThrowable != null) { logger.info("... caused by:", nestedThrowable); } } else if (Priority.WARN.getValue() == priority) { logger.warn(event.getMessage(), originalThrowable); if (nestedThrowable != null) { logger.warn("... caused by:", nestedThrowable); } } else if (Priority.ERROR.getValue() == priority) { logger.error(event.getMessage(), originalThrowable); if (nestedThrowable != null) { logger.error("... caused by:", nestedThrowable); } } else if (Priority.FATAL_ERROR.getValue() == priority) { logger.fatal(event.getMessage(), originalThrowable); if (nestedThrowable != null) { logger.fatal("... caused by:", nestedThrowable); } } else { logger.warn("Got log event of unknown priority: " + priority + ". Message: " + event.getMessage(), originalThrowable); } } /** * @see org.apache.log.output.AbstractOutputTarget#isOpen() */ protected boolean isOpen() { return this.isOpen; } /** * @see org.apache.log.output.AbstractOutputTarget#open() */ protected void open() { this.isOpen = true; } /** * @see org.apache.log.output.AbstractOutputTarget#close() */ public void close() { this.isOpen = false; } } /* Revision history: $Log: LogKitTargetAdapter.java,v $ Revision 1.6 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 11:12:06 billhorsman fixed licence Revision 1.3 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.2 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.1 2002/12/23 02:39:43 chr32 Needed by the AvalonConfigurator tests. */././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/PropertyConfiguratorTest.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/PropertyConfigurat0000644000175000017500000000474410730503127034132 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.configuration; import org.logicalcobwebs.proxool.AbstractProxoolTest; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.TestHelper; import java.sql.SQLException; /** * Tests that the PropertyConfigurator works. * * @version $Revision: 1.8 $, $Date: 2003/03/04 10:58:45 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.6 */ public class PropertyConfiguratorTest extends AbstractProxoolTest { /** * @see junit.framework.TestCase#TestCase */ public PropertyConfiguratorTest(String name) { super(name); } /** * Test that the configuration succeds and that all expected properties * has been received by Proxool. * @throws ProxoolException if the configuration fails. * @throws SQLException if ProxoolFacade operation fails. */ public void testPropertyConfigurator() throws ProxoolException, SQLException { PropertyConfigurator.configure("src/java-test/org/logicalcobwebs/proxool/configuration/test.properties"); TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("property-test")); TestHelper.equalsCompleteAlternativeProperties(ProxoolFacade.getConnectionPoolDefinition("property-test-2")); ProxoolFacade.removeConnectionPool("property-test"); ProxoolFacade.removeConnectionPool("property-test-2"); } } /* Revision history: $Log: PropertyConfiguratorTest.java,v $ Revision 1.8 2003/03/04 10:58:45 billhorsman checkstyle Revision 1.7 2003/03/04 10:24:41 billhorsman removed try blocks around each test Revision 1.6 2003/03/03 17:09:18 billhorsman all tests now extend AbstractProxoolTest Revision 1.5 2003/03/03 11:12:07 billhorsman fixed licence Revision 1.4 2003/03/01 15:27:25 billhorsman checkstyle Revision 1.3 2003/02/27 18:01:49 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.2 2003/02/19 15:14:27 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2002/12/26 11:34:15 billhorsman Init rev. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/component-ns.conf0000644000175000017500000000515010730503130033612 0ustar twernertwerner avalon-test-ns jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 avalon-test-ns-2 jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/component.conf0000644000175000017500000000476110730503127033211 0ustar twernertwerner avalon-test jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 avalon-test-2 jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/role.conf0000644000175000017500000000033210730503127032136 0ustar twernertwerner libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/test-no-ns.xml0000644000175000017500000000515210730503130033056 0ustar twernertwerner xml-test jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 xml-test-2 jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/test-not-valid.xmllibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/test-not-valid.xml0000644000175000017500000000452310730503130033722 0ustar twernertwerner xml-test-validating jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 Ouch! xml-test-validating-2 jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/test-ns.xml0000644000175000017500000000652510730503127032457 0ustar twernertwerner xml-test-ns jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 xml-test-ns-2 jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/test-valid.xml0000644000175000017500000000446110730503130033125 0ustar twernertwerner xml-test-validating jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 xml-test-validating-2 jdbc:hsqldb:db/test org.hsqldb.jdbcDriver 40000 select CURRENT_DATE 10 3 18000000 5 40000 50000 60000 true true Fatal error 2 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/configuration/test.properties0000644000175000017500000000266110730503127033432 0ustar twernertwernerjdbc-0.proxool.alias=property-test jdbc-0.proxool.driver-url=jdbc:hsqldb:db/test jdbc-0.proxool.driver-class=org.hsqldb.jdbcDriver jdbc-0.user=sa jdbc-0.password= jdbc-0.proxool.house-keeping-sleep-time=40000 jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE jdbc-0.proxool.maximum-connection-count=10 jdbc-0.proxool.minimum-connection-count=3 jdbc-0.proxool.maximum-connection-lifetime=18000000 jdbc-0.proxool.simultaneous-build-throttle=5 jdbc-0.proxool.recently-started-threshold=40000 jdbc-0.proxool.overload-without-refusal-lifetime=50000 jdbc-0.proxool.maximum-active-time=60000 jdbc-0.proxool.verbose=true jdbc-0.proxool.trace=true jdbc-0.proxool.fatal-sql-exception=Fatal error jdbc-0.proxool.prototype-count=2 jdbc-1.proxool.alias=property-test-2 jdbc-1.proxool.driver-url=jdbc:hsqldb:db/test jdbc-1.proxool.driver-class=org.hsqldb.jdbcDriver jdbc-1.user=sa jdbc-1.password= jdbc-1.proxool.house-keeping-sleep-time=40000 jdbc-1.proxool.house-keeping-test-sql=select CURRENT_DATE jdbc-1.proxool.maximum-connection-count=10 jdbc-1.proxool.minimum-connection-count=3 jdbc-1.proxool.maximum-connection-lifetime=18000000 jdbc-1.proxool.simultaneous-build-throttle=5 jdbc-1.proxool.recently-started-threshold=40000 jdbc-1.proxool.overload-without-refusal-lifetime=50000 jdbc-1.proxool.maximum-active-time=60000 jdbc-1.proxool.verbose=true jdbc-1.proxool.trace=true jdbc-1.proxool.fatal-sql-exception=Fatal error jdbc-1.proxool.prototype-count=2 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/util/0000755000175000017500000000000011054125603026435 5ustar twernertwernerlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/util/AllTests.java0000644000175000017500000000265510730503130031036 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.util; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; import org.logicalcobwebs.proxool.GlobalTest; /** * Run all tests in the util package. * * @version $Revision: 1.4 $, $Date: 2003/03/03 11:12:07 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class AllTests { /** * Create a composite test of all util package tests * @return test suite */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(ListenerContainerTest.class); // create a wrapper for global initialization code. TestSetup wrapper = new TestSetup(suite) { public void setUp() throws Exception { GlobalTest.globalSetup(); } }; return wrapper; } } /* Revision history: $Log: AllTests.java,v $ Revision 1.4 2003/03/03 11:12:07 billhorsman fixed licence Revision 1.3 2003/02/19 23:49:16 billhorsman fixed doc Revision 1.2 2003/02/19 15:14:32 billhorsman fixed copyright (copy and paste error, not copyright change) */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/util/ListenerContainerTest.java0000644000175000017500000000750710025537540033605 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool.util; import org.logicalcobwebs.proxool.AbstractProxoolTest; /** * Test {@link AbstractListenerContainer}. * * @version $Revision: 1.6 $, $Date: 2004/03/16 08:48:32 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: brenuart $ (current maintainer) * @since Proxool 0.7 */ public class ListenerContainerTest extends AbstractProxoolTest { /** * @see junit.framework.TestCase#TestCase */ public ListenerContainerTest(String name) { super(name); } /** * Test that added listeners get notified. */ public void testAdd() { CompositeTestListener compositeTestListener = new CompositeTestListener(); for (int i = 0; i < 10; ++i) { compositeTestListener.addListener(new TestListener()); } compositeTestListener.onEvent(); assertTrue("Only got " + compositeTestListener.getNumberOfNotifications() + " notifications but expected 10.", compositeTestListener.getNumberOfNotifications() == 10); } /** * Test that removed listeners are not notified, and that the remove method * returns false when trying to removed an unregistered listener. */ public void testRemove() { TestListenerIF[] testListeners = new TestListenerIF[]{ new TestListener(), new TestListener(), new TestListener(), new TestListener(), new TestListener(), new TestListener(), new TestListener(), new TestListener(), new TestListener(), new TestListener() }; CompositeTestListener compositeTestListener = new CompositeTestListener(); for (int i = 0; i < 10; ++i) { compositeTestListener.addListener(testListeners[i]); } for (int i = 0; i < 10; ++i) { assertTrue("Removal of a listener failed.", compositeTestListener.removeListener(testListeners[i])); } assertTrue("Removal of unregistered listener returned true", !compositeTestListener.removeListener(new TestListener())); compositeTestListener.onEvent(); assertTrue("Listeners was notified even if all listeners had been removed.", compositeTestListener.getNumberOfNotifications() == 0); } } interface TestListenerIF { void onEvent(); } class CompositeTestListener extends AbstractListenerContainer implements TestListenerIF { private int numberOfNotifications; public void onEvent() { Object[] listeners = getListeners(); for(int i=0; i '" + alias + "'"); Thread.currentThread().setName(alias); testLock.writeLock().acquire(); } /** * @see TestCase#tearDown() */ protected void tearDown() throws Exception { try { GlobalTest.globalTeardown(alias); Thread.currentThread().setName((String) threadNames.pop()); LOG.debug("Thread '" + alias + "' -> '" + Thread.currentThread().getName() + "'"); } finally { testLock.writeLock().release(); } } } /* Revision history: $Log: AbstractProxoolTest.java,v $ Revision 1.6 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2004/03/26 16:00:23 billhorsman Make sure we release lock on tearDown. I don't think this was a problem, but it was unrobust. Revision 1.4 2003/09/30 19:09:46 billhorsman Now uses a readwrite lock to make sure that each test runs sequentially. This should be true all the time, but sometimes tests fail and it is always because of some timing issue that is very hard to track down. This is an attempt to fix that. Revision 1.3 2003/03/04 10:11:09 billhorsman actually made abstract Revision 1.2 2003/03/03 17:38:47 billhorsman leave shutdown to AbstractProxoolTest Revision 1.1 2003/03/03 17:08:54 billhorsman all tests now extend AbstractProxoolTest */././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootlibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/AbstractSpringIntegrationTestBase.javalibproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/AbstractSpringIntegrationTestBas0000644000175000017500000000114410730503131034017 0ustar twernertwernerpackage org.logicalcobwebs.proxool; import org.springframework.test.AbstractTransactionalSpringContextTests; /** * TODO: Document! * * @author Mark Eagle * @author Phil Barnes * @since Mar 16, 2006 @ 7:55:30 AM */ public abstract class AbstractSpringIntegrationTestBase extends AbstractTransactionalSpringContextTests { protected String[] getConfigLocations() { return new String[]{ "classpath:org/logicalcobwebs/proxool/applicationContext.xml" }; } protected void onSetUpBeforeTransaction() throws Exception { GlobalTest.globalSetup(); } } libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/AllTests.java0000644000175000017500000001074510730503131030061 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; /** * Run all tests * * @version $Revision: 1.27 $, $Date: 2004/03/23 21:14:24 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class AllTests { /** * Run all tests * * @return a composite test of all Proxool tests. */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(ConfigurationListenerTest.class); suite.addTestSuite(ConnectionInfoTest.class); suite.addTestSuite(ConnectionListenerTest.class); suite.addTestSuite(ConnectionResetterTest.class); suite.addTestSuite(ProxoolDataSourceTest.class); suite.addTestSuite(DriverTest.class); suite.addTestSuite(ConnectionPoolTest.class); suite.addTestSuite(FatalSqlExceptionTest.class); suite.addTestSuite(HibernateTest.class); suite.addTestSuite(HouseKeeperTest.class); suite.addTestSuite(HypersonicTest.class); suite.addTestSuite(KillTest.class); suite.addTestSuite(ManyPoolsTest.class); suite.addTestSuite(PropertyTest.class); suite.addTestSuite(PrototyperTest.class); suite.addTestSuite(ProxyConnectionTest.class); suite.addTestSuite(ProxyDatabaseMetaDataTest.class); suite.addTestSuite(ProxyStatementTest.class); suite.addTestSuite(RegistrationTest.class); suite.addTestSuite(StateListenerTest.class); suite.addTestSuite(UpdateDefinitionTest.class); suite.addTestSuite(WrapperTest.class); // TODO Need more investigation into why this fails sometimes. // suite.addTestSuite(PerformanceTest.class); // create a wrapper for global initialization code. TestSetup wrapper = new TestSetup(suite) { public void setUp() throws Exception { GlobalTest.globalSetup(); } }; return wrapper; } } /* Revision history: $Log: AllTests.java,v $ Revision 1.27 2004/03/23 21:14:24 billhorsman new tests Revision 1.26 2004/03/18 17:10:01 chr32 Renamed DataSourceTest -> ProxoolDataSourceTest. Added test for factory-configured mode. Revision 1.25 2004/03/15 02:46:09 chr32 Added initial ProxoolDataSourceTest. Revision 1.24 2003/11/04 13:23:18 billhorsman Added PropetyTest Revision 1.23 2003/10/26 16:23:20 billhorsman Fixed up test suites Revision 1.22 2003/09/28 09:38:39 billhorsman New unit test for Hibernate. Revision 1.21 2003/04/27 22:11:34 billhorsman temporary removal of PerformanceTest Revision 1.20 2003/04/27 15:46:11 billhorsman moved ProxoolDataSourceTest to sandbox Revision 1.19 2003/04/19 13:01:01 billhorsman improve tests Revision 1.18 2003/03/11 14:58:30 billhorsman put PerformanceTest back in the global test Revision 1.17 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.16 2003/02/27 18:01:46 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.15 2003/02/19 23:25:28 billhorsman new StateListenerTest Revision 1.14 2003/02/19 15:14:22 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.13 2003/02/19 13:47:32 chr32 Added configuration listener test. Revision 1.12 2003/02/18 16:51:19 chr32 Added tests for ConnectionListeners. Revision 1.11 2003/02/06 17:41:02 billhorsman now uses imported logging Revision 1.10 2003/01/23 11:13:57 billhorsman remove PerformanceTest from suite Revision 1.9 2002/12/16 17:35:42 chr32 Removed redundant imports. Revision 1.8 2002/12/16 17:06:10 billhorsman new test structure Revision 1.7 2002/12/15 19:16:58 chr32 Added JAXPConfigurator test. Revision 1.6 2002/11/07 18:53:41 billhorsman slight improvement to setup Revision 1.5 2002/11/02 11:37:48 billhorsman New tests Revision 1.4 2002/10/28 21:37:54 billhorsman now allows for non-existent log4jPath Revision 1.3 2002/10/27 13:05:02 billhorsman checkstyle Revision 1.2 2002/10/27 12:03:33 billhorsman clear up of tests Revision 1.1 2002/10/25 10:41:07 billhorsman draft changes to test globalSetup */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ConfigurationListenerTest.java0000644000175000017500000002476510730503131033512 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Properties; import java.sql.DriverManager; /** * Test that registering a {@link org.logicalcobwebs.proxool.ConfigurationListenerIF} * with the {@link org.logicalcobwebs.proxool.ProxoolFacade} * works. * * @version $Revision: 1.13 $, $Date: 2006/01/18 14:40:06 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class ConfigurationListenerTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ConfigurationListenerTest.class); /** * @see junit.framework.TestCase#TestCase */ public ConfigurationListenerTest(String s) { super(s); } /** * Add a listener * * @throws Exception if anything goes wrong */ public void testAddAndRemove() throws Exception { String testName = "addAndRemove"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); // add a listener MyConfigurationListener mcl1 = new MyConfigurationListener(); ProxoolFacade.addConfigurationListener(alias, mcl1); // Update the definition Properties newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); ProxoolFacade.updateConnectionPool(url, newInfo); assertEquals("definitionReceived", true, mcl1.isUpdateReceived()); mcl1.reset(); // add another listener MyConfigurationListener mcl2 = new MyConfigurationListener(); ProxoolFacade.addConfigurationListener(alias, mcl2); // Update the definition newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.FALSE.toString()); ProxoolFacade.updateConnectionPool(url, newInfo); assertEquals("definitionReceived", true, mcl1.isUpdateReceived()); assertEquals("definitionReceived", true, mcl2.isUpdateReceived()); mcl1.reset(); mcl2.reset(); // Remove the first listener ProxoolFacade.removeConfigurationListener(alias, mcl1); // Update the definition newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); ProxoolFacade.updateConnectionPool(url, newInfo); assertEquals("definitionReceived", false, mcl1.isUpdateReceived()); assertEquals("definitionReceived", true, mcl2.isUpdateReceived()); mcl1.reset(); mcl2.reset(); // Check that just asking for another Connection (without config // change) doesn't trigger another event DriverManager.getConnection(url).close(); assertEquals("definitionReceived", false, mcl2.isUpdateReceived()); mcl2.reset(); // Now try again, but this time pass in the properties (without // change) LOG.debug("Getting another connection to trigger any pending config changes"); DriverManager.getConnection(url, info).close(); mcl2.reset(); LOG.debug("Getting another connection which shouldn't cause another config change"); DriverManager.getConnection(url, info).close(); assertEquals("definitionReceived", false, mcl2.isUpdateReceived()); mcl2.reset(); // This time pass in the properties (WITH change) LOG.debug("Expecting a change now"); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.FALSE.toString()); DriverManager.getConnection(url, info).close(); assertEquals("definitionReceived", true, mcl2.isUpdateReceived()); mcl2.reset(); // Remove the second listener ProxoolFacade.removeConfigurationListener(alias, mcl2); // Update the definition newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.FALSE.toString()); ProxoolFacade.updateConnectionPool(url, newInfo); assertEquals("definitionReceived", false, mcl1.isUpdateReceived()); assertEquals("definitionReceived", false, mcl2.isUpdateReceived()); mcl1.reset(); mcl2.reset(); } /** * Do configuration listeners work * * @throws Exception if anything goes wrong */ public void testConfigurationListeners() throws Exception { String testName = "configurationListener"; String alias = testName; // Register pool final String delegateUrl1 = TestConstants.HYPERSONIC_TEST_URL; final String delegateUrl2 = TestConstants.HYPERSONIC_TEST_URL2; final String url1 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, delegateUrl1); final String url2 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, delegateUrl2); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url1, info); int propertyCount = info.size(); // listen to the configuration MyConfigurationListener mcl = new MyConfigurationListener(); ProxoolFacade.addConfigurationListener(alias, mcl); // Update the URL ProxoolFacade.updateConnectionPool(url2, null); LOG.debug("changed: " + mcl.getChangedInfo()); LOG.debug("complete: " + mcl.getCompleteInfo()); assertEquals("changed size", 0, mcl.getChangedInfo().size()); assertEquals("complete size", propertyCount, mcl.getCompleteInfo().size()); assertEquals("url", delegateUrl2, mcl.getConnectionPoolDefinition().getUrl()); mcl.reset(); // Add the verbose property Properties newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); ProxoolFacade.updateConnectionPool(url2, newInfo); LOG.debug("changed: " + mcl.getChangedInfo()); LOG.debug("complete: " + mcl.getCompleteInfo()); assertEquals("completeInfo size", propertyCount + 1, mcl.getCompleteInfo().size()); assertEquals("changedInfo size", 1, mcl.getChangedInfo().size()); assertEquals("url", true, mcl.getConnectionPoolDefinition().isVerbose()); mcl.reset(); // modify the verbose property newInfo = new Properties(); newInfo.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.FALSE.toString()); ProxoolFacade.updateConnectionPool(url2, newInfo); LOG.debug("changed: " + mcl.getChangedInfo()); LOG.debug("complete: " + mcl.getCompleteInfo()); assertEquals("completeInfo size", propertyCount + 1, mcl.getCompleteInfo().size()); assertEquals("changedInfo size", 1, mcl.getChangedInfo().size()); assertEquals("url", false, mcl.getConnectionPoolDefinition().isVerbose()); mcl.reset(); } class MyConfigurationListener implements ConfigurationListenerIF { private Properties completeInfo; private Properties changedInfo; private ConnectionPoolDefinitionIF connectionPoolDefinition; private boolean updateReceived; public void definitionUpdated(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo) { this.connectionPoolDefinition = connectionPoolDefinition; this.completeInfo = completeInfo; this.changedInfo = changedInfo; updateReceived = true; } public Properties getCompleteInfo() { return completeInfo; } public Properties getChangedInfo() { return changedInfo; } public ConnectionPoolDefinitionIF getConnectionPoolDefinition() { return connectionPoolDefinition; } public boolean isUpdateReceived() { return updateReceived; } public void reset() { completeInfo.clear(); changedInfo.clear(); updateReceived = false; } } } /* Revision history: $Log: ConfigurationListenerTest.java,v $ Revision 1.13 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.12 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.11 2003/04/27 15:44:19 billhorsman better tests Revision 1.10 2003/04/10 21:48:58 billhorsman enhanced to trap bug where config change event gets fired all the time Revision 1.9 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.8 2003/03/03 17:08:54 billhorsman all tests now extend AbstractProxoolTest Revision 1.7 2003/03/03 11:12:03 billhorsman fixed licence Revision 1.6 2003/02/27 18:01:47 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.5 2003/02/26 16:05:49 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.4 2003/02/24 18:04:07 chr32 Fixde some eroneous property names. Revision 1.3 2003/02/19 17:00:51 chr32 Fixed eroneous method names. Revision 1.2 2003/02/19 15:14:22 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2003/02/19 13:47:31 chr32 Added configuration listener test. Revision 1.2 2003/02/18 16:58:12 chr32 Checkstyle. Revision 1.1 2003/02/18 16:51:20 chr32 Added tests for ConnectionListeners. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ConnectionInfoTest.java0000644000175000017500000000665410730503130032104 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.DriverManager; import java.util.Properties; /** * Tests {@link ProxoolFacade#getConnectionInfos} * * @version $Revision: 1.8 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ConnectionInfoTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ConnectionInfoTest.class); public ConnectionInfoTest(String alias) { super(alias); } /** * If we ask for more simultaneous connections then we have allowed we should gracefully * refuse them. */ public void testConnectionInfo() throws Exception { String testName = "connectionInfo"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); DriverManager.getConnection(url); assertEquals("connectionInfo count", 1, ProxoolFacade.getSnapshot(alias, true).getConnectionInfos().length); DriverManager.getConnection(url); assertEquals("connectionInfo count", 2, ProxoolFacade.getSnapshot(alias, true).getConnectionInfos().length); DriverManager.getConnection(url).close(); assertEquals("connectionInfo count", 3, ProxoolFacade.getSnapshot(alias, true).getConnectionInfos().length); ConnectionInfoIF[] connectionInfos = ProxoolFacade.getSnapshot(alias, true).getConnectionInfos(); assertEquals("activeCount", 2, getCount(connectionInfos, ConnectionInfoIF.STATUS_ACTIVE)); assertEquals("availableCount", 1, getCount(connectionInfos, ConnectionInfoIF.STATUS_AVAILABLE)); } private int getCount(ConnectionInfoIF[] connectionInfos, int status) { int count = 0; for (int i = 0; i < connectionInfos.length; i++) { ConnectionInfoIF connectionInfo = connectionInfos[i]; if (connectionInfo.getStatus() == status) { count++; } } return count; } } /* Revision history: $Log: ConnectionInfoTest.java,v $ Revision 1.8 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.7 2003/04/28 20:02:43 billhorsman changed from deprecated getConnectionInfos to Snapshot Revision 1.6 2003/03/11 00:38:41 billhorsman allowed for connections in different order Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:08:55 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:47 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ConnectionListenerTest.java0000644000175000017500000003004610730503130032766 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.*; import java.util.Properties; /** * Test that registering a {@link ConnectionListenerIF} with the {@link ProxoolFacade} * works. * * @version $Revision: 1.17 $, $Date: 2007/01/25 23:38:24 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class ConnectionListenerTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ConnectionListenerTest.class); private int onBirthCalls; private int onDeathCalls; private int onExecuteCalls; private int onFailCalls; /** * @see junit.framework.TestCase#TestCase */ public ConnectionListenerTest(String s) { super(s); } /** * Test that multiple connection listeners can be added through ProxoolFacade, * and that they get the expected events. * @throws Exception if the test fails. */ public void testAddConnectionListener() throws Exception { clear(); String alias = "connectionListenerTest"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY, "1"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "0"); Connection connection1 = DriverManager.getConnection(url, info); ProxoolFacade.addConnectionListener(alias, new TestConnectionListener()); ProxoolFacade.addConnectionListener(alias, new TestConnectionListener()); Connection connection2 = DriverManager.getConnection(url); // provoke execution error boolean errorOccured = false; try { connection1.createStatement().executeQuery("DINGO"); } catch (SQLException e) { // we want this. errorOccured = true; } assertTrue("We failed to provoke a connection failure.", errorOccured); // following statement should be ok connection2.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); // close both connections connection1.close(); connection2.close(); // shutdown connection pool ProxoolFacade.removeConnectionPool(alias); // test results assertTrue("Expected 2 onBirth calls, but got " + this.onBirthCalls + ".", this.onBirthCalls == 2); assertTrue("Expected 2 onExecute calls, but got " + this.onExecuteCalls + ".", this.onExecuteCalls == 2); assertTrue("Expected 2 onFail calls, but got " + this.onFailCalls + ".", this.onFailCalls == 2); assertTrue("Expected 4 onDeath calls, but got " + this.onDeathCalls + ".", this.onDeathCalls == 4); } /** * See whether the command parameter passed to {@link ConnectionListenerIF#onFail(java.lang.String, java.lang.Exception)} * is correct. And assume it is also right for onExecute. * @throws Exception if the test fails. */ public void testExecuteCommand() throws Exception { clear(); String alias = "executeCommand"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); Connection connection1 = DriverManager.getConnection(url, info); final TestConnectionListener tcl = new TestConnectionListener(); ProxoolFacade.addConnectionListener(alias, tcl); Statement createStatement = connection1.createStatement(); createStatement.execute("CREATE TABLE NOTHING (a boolean, b datetime, c integer, d decimal, e varchar)"); // provoke execution error java.util.Date date = new java.util.Date(); PreparedStatement ps = connection1.prepareStatement("select * from NOTHING where a = ? and b = ? and c = ? and d = ? and e = ?"); ps.setBoolean(1, true); ps.setDate(2, new Date(date.getTime())); ps.setInt(3, 3); ps.setDouble(4, 4.0); ps.setString(5, "test"); ps.execute(); LOG.debug(tcl.getCommand()); assertEquals("command", "select * from NOTHING where a = true and b = '" + AbstractProxyStatement.getDateAsString(date) + "' and c = 3 and d = 4.0 and e = 'test';", tcl.getCommand().trim()); // Check that it works with no parameters final String s2 = "select * from NOTHING;"; tcl.clear(); ps = connection1.prepareStatement(s2); ps.execute(); LOG.debug(tcl.getCommand()); assertEquals("command", s2, tcl.getCommand().trim()); tcl.clear(); ps = connection1.prepareStatement(s2); ps.execute(); LOG.debug(tcl.getCommand()); assertEquals("command", s2, tcl.getCommand().trim()); } /** * Test that multiple connection listeners can be added through ProxoolFacade, * and then removed, and that they do not receive events after they have been removed. * @throws Exception if the test fails. */ public void testRemoveConnectionListener() throws Exception { clear(); String alias = "removeConnectionListenerTest"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY, "1"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "0"); Connection connection1 = DriverManager.getConnection(url, info); TestConnectionListener testConnectionListener1 = new TestConnectionListener(); TestConnectionListener testConnectionListener2 = new TestConnectionListener(); ProxoolFacade.addConnectionListener(alias, testConnectionListener1); ProxoolFacade.addConnectionListener(alias, testConnectionListener2); assertTrue("Failed to remove testConnectionListener1", ProxoolFacade.removeConnectionListener(alias, testConnectionListener1)); assertTrue("Failed to remove testConnectionListener2", ProxoolFacade.removeConnectionListener(alias, testConnectionListener2)); ProxoolFacade.removeConnectionListener(alias, testConnectionListener2); Connection connection2 = DriverManager.getConnection(url, info); // provoke execution error boolean errorOccured = false; try { connection1.createStatement().executeQuery("DINGO"); } catch (SQLException e) { // we want this. errorOccured = true; } assertTrue("We failed to proovoke a connection failure.", errorOccured); // following statement should be ok connection2.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); // close connections connection1.close(); connection2.close(); // shutdown connection pool ProxoolFacade.removeConnectionPool(alias); // validate results assertTrue("Expected 0 onBirth calls, but got " + this.onBirthCalls + ".", this.onBirthCalls == 0); assertTrue("Expected 0 onExecute calls, but got " + this.onExecuteCalls + ".", this.onExecuteCalls == 0); assertTrue("Expected 0 onFail calls, but got " + this.onFailCalls + ".", this.onFailCalls == 0); assertTrue("Expected 0 onDeath calls, but got " + this.onDeathCalls + ".", this.onDeathCalls == 0); } private void clear() { this.onBirthCalls = 0; this.onDeathCalls = 0; this.onExecuteCalls = 0; this.onFailCalls = 0; } // /** // * Calls {@link AbstractProxoolTest#setUp} // * @see junit.framework.TestCase#setUp // */ // protected void setUp() throws Exception { // super.setUp(); // Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); // } class TestConnectionListener implements ConnectionListenerIF { String command; public void onBirth(Connection connection) throws SQLException { onBirthCalls++; } public void onDeath(Connection connection, int reasonCode) throws SQLException { onDeathCalls++; } public void onExecute(String command, long elapsedTime) { onExecuteCalls++; this.command = command; } public void onFail(String command, Exception exception) { onFailCalls++; this.command = command; } public String getCommand() { return command; } public void clear() { command = null; } public void onAboutToDie(Connection connection, int reason) throws SQLException { // Ignore } } } /* Revision history: $Log: ConnectionListenerTest.java,v $ Revision 1.17 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.16 2007/01/25 00:10:24 billhorsman New onAboutToDie event for ConnectionListenerIF that gets called if the maximum-active-time is exceeded. Revision 1.15 2006/03/23 11:42:20 billhorsman Create dummy table so test statements work. With HSQL 1.8 it is the prepareStatement() that throws the exception, not the execute() which means the listeners never gets the event. Revision 1.14 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.13 2004/06/02 20:04:00 billhorsman Added test for onExecute command Revision 1.12 2004/05/26 17:19:10 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.11 2003/03/10 23:31:04 billhorsman fixed deprecated properties and doc Revision 1.10 2003/03/04 10:58:43 billhorsman checkstyle Revision 1.9 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.8 2003/03/03 17:08:55 billhorsman all tests now extend AbstractProxoolTest Revision 1.7 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.6 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.5 2003/02/28 10:26:38 billhorsman removed killAllConnections call which should be unnecessary and forced me to fix bug in ConnectionPool.shutdown where onDeath wasn't getting called. Also used constants for properties and used database in db directory (to clean up files) Revision 1.4 2003/02/19 15:14:22 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.3 2003/02/19 13:47:51 chr32 Fixed wrong proxool parameters. Revision 1.2 2003/02/18 16:58:12 chr32 Checkstyle. Revision 1.1 2003/02/18 16:51:20 chr32 Added tests for ConnectionListeners. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ConnectionPoolTest.java0000644000175000017500000002057710730503130032122 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Connection; import java.util.Properties; /** * Test {@link ConnectionPool} * * @version $Revision: 1.3 $, $Date: 2006/01/18 14:40:06 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ConnectionPoolTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ConnectionPoolTest.class); public ConnectionPoolTest(String name) { super(name); } /** * If we ask for more simultaneous connections then we have allowed we should gracefully * refuse them. */ public void testMaximumConnectionCount() throws Exception { String testName = "maximumConnectionCount"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); ProxoolFacade.registerConnectionPool(url, info); DriverManager.getConnection(url); DriverManager.getConnection(url); try { DriverManager.getConnection(url); fail("Didn't expect to get third connection"); } catch (SQLException e) { // Log message only so we don't get a worrying stack trace LOG.debug("Ignoring expected exception: " + e.getMessage()); } assertEquals("activeConnectionCount", 2, ProxoolFacade.getSnapshot(alias, true).getActiveConnectionCount()); } /** * test what happens if maximum = minimum = 1 */ public void testMaximumEqualsMinimumConnectionCount() throws Exception { String testName = "maximumEqualsMinimumConnectionCount"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "1"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "1"); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); ProxoolFacade.registerConnectionPool(url, info); // opening and closing a connection should have no effect Connection c1 = DriverManager.getConnection(url); c1.close(); // Leave this one open for a while Connection c2 = DriverManager.getConnection(url); try { Connection c3 = DriverManager.getConnection(url); c3.close(); fail("Didn't expect to get third connection"); } catch (SQLException e) { // Log message only so we don't get a worrying stack trace LOG.debug("Ignoring expected exception: " + e.getMessage()); } assertEquals("activeConnectionCount", 1, ProxoolFacade.getSnapshot(alias, true).getActiveConnectionCount()); c2.close(); // Just check it all still works DriverManager.getConnection(url).close(); assertEquals("activeConnectionCount", 0, ProxoolFacade.getSnapshot(alias, true).getActiveConnectionCount()); } /** * Checks whether shutdown is patient enough to wait for active connections */ public void testShutdownPatience() throws ProxoolException, SQLException { String testName = "shutdownPatience"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); ProxoolFacade.registerConnectionPool(url, info); // Open a connection that will close in 5 seconds new Thread(new Closer(DriverManager.getConnection(url), 5000)).start(); long startTime = System.currentTimeMillis(); ProxoolFacade.removeConnectionPool(alias, 100000); long shutdownTime = System.currentTimeMillis() - startTime; assertTrue("shutdown took too long", shutdownTime < 50000); assertTrue("shutdown was too quick", shutdownTime > 2000); } /** * Checks whether shutdown is impatient enough to shutdown even if * some connections are still active */ public void testShutdownImpatience() throws ProxoolException, SQLException { String testName = "shutdownImpatience"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); ProxoolFacade.registerConnectionPool(url, info); // Open a connection that will close in 100 seconds new Thread(new Closer(DriverManager.getConnection(url), 100000)).start(); long startTime = System.currentTimeMillis(); ProxoolFacade.removeConnectionPool(alias, 3000); long shutdownTime = System.currentTimeMillis() - startTime; assertTrue("shutdown took too long", shutdownTime < 50000); assertTrue("shutdown was too quick", shutdownTime > 1000); } class Closer implements Runnable { private Connection connection; private long duration; public Closer(Connection connection, long duration) { this.connection = connection; this.duration = duration; } public void run() { long startTime = System.currentTimeMillis(); try { Thread.sleep(duration); } catch (InterruptedException e) { LOG.error("Awoken", e); } try { connection.close(); LOG.debug("Connection closed after " + (System.currentTimeMillis() - startTime) + " milliseconds."); } catch (SQLException e) { LOG.error("Problem closing connection", e); } } } } /* Revision history: $Log: ConnectionPoolTest.java,v $ Revision 1.3 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.2 2004/06/02 21:05:19 billhorsman Don't log worrying stack traces for expected exceptions. Revision 1.1 2003/10/26 16:10:46 billhorsman renamed to be more consistent Revision 1.9 2003/09/11 23:14:57 billhorsman New test for when maximum-connection-count = 1 and minimum-connection-count = 1 Revision 1.8 2003/03/12 00:14:12 billhorsman change thresholds Revision 1.7 2003/03/11 01:19:48 billhorsman new tests Revision 1.6 2003/03/10 15:31:26 billhorsman fixes Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:08:55 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:47 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ConnectionResetterTest.java0000644000175000017500000001407410730503130033001 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; /** * Test whether the {@link ConnectionResetter} works. * * @version $Revision: 1.16 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class ConnectionResetterTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ConnectionResetterTest.class); /** * @see junit.framework.TestCase#TestCase */ public ConnectionResetterTest(String s) { super(s); } /** * Test whether autoCommit is correctly reset when a connection is * returned to the pool. */ public void testAutoCommit() throws Exception { String testName = "autoCommit"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection c1 = DriverManager.getConnection(url); Connection c2 = DriverManager.getConnection(url); c1.setAutoCommit(false); c1.close(); c1 = DriverManager.getConnection(url); assertTrue("c1.getAutoCommit", c1.getAutoCommit()); c2.close(); c1.close(); assertEquals("connectionCount", 2, ProxoolFacade.getSnapshot(alias).getConnectionCount()); } /** * Test connectionCount when we deliberately introduce an exception during connection reset. */ public void testFailedReset() throws Exception { try { // This is a bit of a hack to force an exception during reset ConnectionResetter.setTriggerResetException(true); String testName = "failedReset"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection c1 = DriverManager.getConnection(url); c1.setAutoCommit(false); c1.close(); assertEquals("connectionCount", 0, ProxoolFacade.getSnapshot(alias).getConnectionCount()); } finally { // Back to normal ConnectionResetter.setTriggerResetException(false); } } /** * Test whether autoCommit is correctly reset when a connection is * returned to the pool. */ public void testReadOnly() throws Exception { String testName = "readOnly"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); ProxoolFacade.registerConnectionPool(url, info); Connection c1 = DriverManager.getConnection(url); ; Connection c2 = DriverManager.getConnection(url); ; boolean originalReadOnly = c1.isReadOnly(); c1.setReadOnly(true); c1.close(); c1 = DriverManager.getConnection(url); ; assertTrue("readOnly", c1.isReadOnly() == originalReadOnly); c2.close(); c1.close(); } } /* Revision history: $Log: ConnectionResetterTest.java,v $ Revision 1.16 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.15 2005/10/07 08:12:58 billhorsman Test deliberate exception durinng reset Revision 1.14 2003/03/04 10:58:43 billhorsman checkstyle Revision 1.13 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.12 2003/03/03 17:08:56 billhorsman all tests now extend AbstractProxoolTest Revision 1.11 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.10 2003/02/27 18:01:47 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.9 2003/02/19 15:14:22 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.8 2003/02/06 17:41:02 billhorsman now uses imported logging Revision 1.7 2002/12/16 17:05:38 billhorsman new test structure Revision 1.6 2002/12/03 10:53:08 billhorsman checkstyle Revision 1.5 2002/11/13 20:53:30 billhorsman new tests for autoCommit and readOnly Revision 1.4 2002/11/12 20:24:12 billhorsman checkstyle Revision 1.3 2002/11/12 20:18:26 billhorsman Made connection resetter a bit more friendly. Now, if it encounters any problems during reset then that connection is thrown away. This is going to cause you problems if you always close connections in an unstable state (e.g. with transactions open. But then again, it's better to know about that as soon as possible, right? Revision 1.2 2002/11/09 16:01:21 billhorsman fixed CommandFilterIF implementation Revision 1.1 2002/11/06 21:08:02 billhorsman new ConnectionResetter test */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/DelegateConnectionTest.java0000644000175000017500000000323710730503130032715 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Properties; import java.sql.Connection; import java.sql.DriverManager; /** * Tests whether we have access to the delegate connection * @version $Revision: 1.1 $, $Date: 2004/03/23 21:14:24 $ * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class DelegateConnectionTest extends AbstractProxoolTest { /** * @see AbstractProxoolTest */ public DelegateConnectionTest(String alias) { super(alias); } /** * Get a connection and cast it into the appropriate interface */ public void testDelegateConnection() throws Exception { String alias = "delegateConnection"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); Connection c1 = DriverManager.getConnection(url, info); // TODO cast the connection into the appropriate *interface* and see if it works. c1.close(); } } /* Revision history: $Log: DelegateConnectionTest.java,v $ Revision 1.1 2004/03/23 21:14:24 billhorsman new tests */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/DependencyCheck.java0000644000175000017500000000530210730503131031333 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.impl.SimpleLog; import java.sql.DriverManager; import java.util.Properties; /** * A minimal check to see what libraries we need to include with * our binary distribution * * @version $Revision: 1.3 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman {bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class DependencyCheck { /** * A minimal check to see what libraries we need to include with * our binary distribution */ public static void main(String[] args) { try { System.setProperty("org.apache.commons.logging.Log", SimpleLog.class.getName()); System.setProperty(Log.class.getName(), SimpleLog.class.getName()); System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "debug"); Log log = LogFactory.getLog(DependencyCheck.class); log.info("Can you read this?"); log.debug("Can you read this?"); Class.forName(ProxoolDriver.class.getName()); String alias = "dependencyCheck"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); DriverManager.getConnection(url, info).close(); System.out.println("Done"); } catch (Throwable e) { if (e instanceof ProxoolException) { e = ((ProxoolException) e).getCause(); } e.printStackTrace(); System.out.println("Fail"); } finally { ProxoolFacade.shutdown(0); } } } /* Revision history: $Log: DependencyCheck.java,v $ Revision 1.3 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.2 2003/11/04 13:54:02 billhorsman checkstyle Revision 1.1 2003/10/25 18:38:17 billhorsman Not a test, just a standalone class you can run to see what libraries you need to use Proxool. It just checks the core features - you're gonna need other libraries for things like JAXP configuration, etc. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/DriverTest.java0000644000175000017500000000525510730503131030421 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.DriverManager; import java.util.Properties; /** * Tests {@link ProxoolDriver} * * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class DriverTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(DriverTest.class); public DriverTest(String alias) { super(alias); } /** * Can we refer to the same pool by either the complete URL or the alias? */ public void testAlias() throws Exception { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); DriverManager.getConnection(url, info).close(); assertEquals("servedCount", 1, ProxoolFacade.getSnapshot(alias).getServedCount()); // Get it back by url url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); DriverManager.getConnection(url).close(); assertEquals("servedCount", 2, ProxoolFacade.getSnapshot(alias).getServedCount()); // Get it back by name url = TestHelper.buildProxoolUrl(alias); DriverManager.getConnection(ProxoolConstants.PROXOOL + "." + alias).close(); assertEquals("servedCount", 3, ProxoolFacade.getSnapshot(alias).getServedCount()); } } /* Revision history: $Log: DriverTest.java,v $ Revision 1.6 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2003/04/29 12:04:18 billhorsman fix test Revision 1.4 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.3 2003/03/03 17:08:57 billhorsman all tests now extend AbstractProxoolTest Revision 1.2 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/FatalSqlExceptionTest.java0000644000175000017500000002455410730503131032557 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * Test whether ProxyStatement works * * @version $Revision: 1.8 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class FatalSqlExceptionTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(FatalSqlExceptionTest.class); public FatalSqlExceptionTest(String alias) { super(alias); } public void testFatalSqlException() throws Exception { String testName = "fatalSqlException"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); info.setProperty(ProxoolConstants.TRACE_PROPERTY, String.valueOf(Boolean.TRUE)); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection c1 = null; long id1 = 0; try { c1 = DriverManager.getConnection(url); id1 = ProxoolFacade.getId(c1); } finally { if (c1 != null) { c1.close(); } } Connection c2 = null; long id2 = 0; try { c2 = DriverManager.getConnection(url); id2 = ProxoolFacade.getId(c2); assertTrue("Expected same connection back", id1 == id2); Statement s = c2.createStatement(); // Doing it twice will guarantee a failure. Even if it exists s.execute(TestConstants.FATAL_SQL_STATEMENT); s.execute(TestConstants.FATAL_SQL_STATEMENT); } catch (SQLException e) { assertTrue("Didn't expect a " + FatalSQLException.class.getName(), !(e instanceof FatalSQLException)); // Expected exception (foo doesn't exist) //LOG.debug("Expected exception (safe to ignore)", e); } finally { if (c2 != null) { c2.close(); } } Connection c3 = null; long id3 = 0; try { c3 = DriverManager.getConnection(url); id3 = ProxoolFacade.getId(c3); assertTrue("Expected a different connection", id1 != id3); } finally { if (c3 != null) { c3.close(); } } } public void testWrappedFatalSqlException() throws Exception { String testName = "wrappedFatalSqlException"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, FatalSQLException.class.getName()); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection c = null; try { c = DriverManager.getConnection(url); Statement s = c.createStatement(); s.execute(TestConstants.FATAL_SQL_STATEMENT); } catch (SQLException e) { assertTrue("Expected a " + FatalSQLException.class.getName() + " but got a " + e.getClass().getName() + " instead", e instanceof FatalSQLException); // Expected exception (foo doesn't exist) //LOG.debug("Expected exception (safe to ignore)", e); } try { if (c != null) { c.close(); } } catch (SQLException e) { LOG.debug("Couldn't close connection", e); } Thread.sleep(1000); // Proxool should automatically throw away that connection that caused a fatal sql exception assertEquals("availableConnectionCount", 0L, ProxoolFacade.getSnapshot(alias, false).getAvailableConnectionCount()); } public void testWrappedFatalRuntimeException() throws Exception { String testName = "wrappedFatalRuntimeException"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, FatalRuntimeException.class.getName()); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection c = null; try { c = DriverManager.getConnection(url); Statement s = c.createStatement(); s.execute(TestConstants.FATAL_SQL_STATEMENT); } catch (RuntimeException e) { assertTrue("Expected a " + FatalRuntimeException.class.getName() + " but got a " + e.getClass().getName() + " instead", e instanceof FatalRuntimeException); // Expected exception (foo doesn't exist) LOG.debug("Expected exception (safe to ignore)", e); } try { if (c != null) { c.close(); } } catch (SQLException e) { LOG.debug("Couldn't close connection", e); } Thread.sleep(1000); // Proxool should automatically throw away that connection that caused a fatal sql exception assertEquals("availableConnectionCount", 0L, ProxoolFacade.getSnapshot(alias, false).getAvailableConnectionCount()); } public void testFatalSqlExceptionWrapperNotFound() throws Exception { String testName = "fatalSqlExceptionWrapperNotFound"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, "org.does.not.Exist"); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); try { ProxoolFacade.registerConnectionPool(url, info); fail("Registration was expected to have failed"); } catch (ProxoolException e) { LOG.debug("Expected exception", e); // That's OK. We're expecting one of these } } public void testFatalSqlExceptionWrapperInvalid() throws Exception { String testName = "fatalSqlExceptionWrapperInvalid"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, TestConstants.FATAL_SQL_EXCEPTION); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); // ProxoolException isn't a RuntimeException or an SQLException info.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS_PROPERTY, ProxoolException.class.getName()); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); try { ProxoolFacade.registerConnectionPool(url, info); fail("Registration was expected to have failed"); } catch (ProxoolException e) { LOG.debug("Expected exception", e); // That's OK. We're expecting one of these } } } /* Revision history: $Log: FatalSqlExceptionTest.java,v $ Revision 1.8 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.7 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.6 2004/03/23 21:16:05 billhorsman make use of new getId() to compare connections Revision 1.5 2003/11/04 23:58:48 billhorsman Made more robust (against existing database state) Revision 1.4 2003/09/29 17:50:45 billhorsman Tests for new wrapper. Revision 1.3 2003/09/05 16:59:20 billhorsman Tests for wrapped exceptions. Revision 1.2 2003/08/27 18:58:11 billhorsman Fixed up test Revision 1.1 2003/07/23 06:54:48 billhorsman draft JNDI changes (shouldn't effect normal operation) Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:09:05 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/GlobalTest.java0000644000175000017500000001563010730503131030364 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.io.InputStream; import java.lang.reflect.Field; import java.util.Properties; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestSuite; import org.apache.log4j.xml.DOMConfigurator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Provides a suite of all tests. And some utility methods for setting * up the logging. * * The test configuration can be specified using the env property "testConfig" * * @version $Revision: 1.22 $, $Date: 2006/03/23 11:52:28 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class GlobalTest { private static final String defaultConfig = "/org/logicalcobwebs/proxool/testconfig-hsqldb.properties"; private static final Log LOG = LogFactory.getLog(GlobalTest.class); private static boolean initialised; public static synchronized void globalSetup() throws Exception { // return immediately if we are already initialised if (initialised) { return; } // configure log4j String log4jPath = System.getProperty("log4jPath"); if (log4jPath != null && log4jPath.length() > 0) { try { DOMConfigurator.configureAndWatch(log4jPath); } catch (Exception e) { LOG.debug("Can't configure logging using " + log4jPath); } } else { // Well, at least switch on debugging System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "debug"); org.apache.log4j.BasicConfigurator.resetConfiguration(); org.apache.log4j.BasicConfigurator.configure(); } // Load ProxoolDriver class into DriverManager Class.forName(ProxoolDriver.class.getName()); // initialise test configuration initTestConstants(); // remember we are correctly initialized initialised = true; } /** * * @throws Exception */ private static void initTestConstants() throws Exception { String resourceName = System.getProperty("testConfig", defaultConfig); initTestConstants(resourceName); } /** * * @param resourceName */ private static void initTestConstants(String resourceName) throws Exception { // locate and read resource file InputStream resourceStream = null; Properties props = new Properties(); try { LOG.info("Loading test configuration from "+resourceName); resourceStream = resourceName.getClass().getResourceAsStream(resourceName); props.load(resourceStream); } catch(Exception e) { LOG.error("Problem while loading test configuration", e); throw new IllegalArgumentException("Couldn't load resources from " + resourceName, e); } finally { if( resourceStream != null ) { resourceStream.close(); } } // parse resource file and initialize TestConstants Field[] fields = TestConstants.class.getDeclaredFields(); for(int i=0; iHibernate 2.x. * (Code contributed by Mark Eagle) * @version $Revision: 1.3 $, $Date: 2006/03/24 00:14:59 $ * @author Bill Horsman {bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) */ public class HibernateTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(HibernateTest.class); public HibernateTest(String alias) { super(alias); } /** * Can we get a connection straight from Hibernate? We register the pool first * and theb ask for Hibernate for it. * @throws ProxoolException if there was a Proxool problem * @throws HibernateException if there was a Hibernate problem */ public void testSimpleHibernateConnection() throws HibernateException, ProxoolException { String testName = "simpleHibernateConnection"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); ProxoolFacade.registerConnectionPool(url, info); Configuration configuration = null; SessionFactory sessionFactory = null; Session session = null; Properties hibernateProperties = new Properties(); Connection connection = null; try { hibernateProperties.setProperty(Environment.DRIVER, ProxoolDriver.class.getName()); hibernateProperties.setProperty(Environment.URL, url); configuration = new Configuration().addProperties(hibernateProperties); // create a session object to the database sessionFactory = configuration.buildSessionFactory(); session = sessionFactory.openSession(); assertNotNull("Expected a session", session); // Inspect the assigned connection to the session from // the pool. connection = session.connection(); // assert that the connection is not null assertNotNull("Expected a connection", connection); } finally { try { connection.close(); } catch (Exception e) { LOG.error("Problem closing Hibernate session", e); } // close the session which will also close it's assigned connection try { session.close(); } catch (Exception e) { LOG.error("Problem closing Hibernate session", e); } } try { Thread.sleep(2000); } catch (InterruptedException e) { LOG.debug("Woken up", e); } // We just need to test that we served at least one connection. I suspect that // Hibernate is doing its own house keeping and getting at least an additional // one. assertTrue("servedCount", ProxoolFacade.getSnapshot(alias).getServedCount() > 0); // They should definitely all be returned to the pool once we're finished though assertEquals("activeCount", 0, ProxoolFacade.getSnapshot(alias).getActiveConnectionCount()); } /** * Can we get a connection from a Proxool pool that we have already registered? We * ask Hibernate to lookup the pool by its alias. * @throws ProxoolException if there was a Proxool problem * @throws HibernateException if there was a Hibernate problem */ public void testDirectHibernateConnection() throws HibernateException, ProxoolException { String testName = "directHibernateConnection"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Configuration configuration = null; SessionFactory sessionFactory = null; Session session = null; Properties hibernateProperties = new Properties(); Connection connection = null; try { hibernateProperties.setProperty(Environment.PROXOOL_EXISTING_POOL, "true"); hibernateProperties.setProperty(Environment.PROXOOL_POOL_ALIAS, alias); configuration = new Configuration().addProperties(hibernateProperties); // create a session object to the database sessionFactory = configuration.buildSessionFactory(); session = sessionFactory.openSession(); assertNotNull("Expected a session", session); // Inspect the assigned connection to the session from // the pool. connection = session.connection(); // assert that the connection is not null assertNotNull("Expected a connection", connection); } finally { try { connection.close(); } catch (Exception e) { LOG.error("Problem closing Hibernate session", e); } // close the session which will also close it's assigned connection try { session.close(); } catch (Exception e) { LOG.error("Problem closing Hibernate session", e); } } // We just need to test that we served at least one connection. I suspect that // Hibernate is doing its own house keeping and getting at least an additional // one. assertTrue("servedCount", ProxoolFacade.getSnapshot(alias).getServedCount() > 0); // They should definitely all be returned to the pool once we're finished though assertEquals("activeCount", 0, ProxoolFacade.getSnapshot(alias).getActiveConnectionCount()); } /** * Can we get a connection from a pool configured by Hibernate * @throws ProxoolException if there was a Proxool problem * @throws HibernateException if there was a Hibernate problem */ public void testHibernateConfiguredConnection() throws HibernateException, ProxoolException { String testName = "hibernateConfiguredConnection"; String alias = testName; Configuration configuration = null; SessionFactory sessionFactory = null; Session session = null; Properties hibernateProperties = new Properties(); Connection connection = null; try { hibernateProperties.setProperty(Environment.PROXOOL_XML, "src/java-test/org/logicalcobwebs/proxool/hibernate.xml"); hibernateProperties.setProperty(Environment.PROXOOL_POOL_ALIAS, alias); configuration = new Configuration().addProperties(hibernateProperties); // create a session object to the database sessionFactory = configuration.buildSessionFactory(); session = sessionFactory.openSession(); assertNotNull("Expected a session", session); // Inspect the assigned connection to the session from // the pool. connection = session.connection(); assertNotNull("Expected a connection", connection); } finally { try { connection.close(); } catch (Exception e) { LOG.error("Problem closing Hibernate session", e); } // close the session which will also close it's assigned connection try { session.close(); } catch (Exception e) { LOG.error("Problem closing Hibernate session", e); } } // We just need to test that we served at least one connection. I suspect that // Hibernate is doing its own house keeping and getting at least an additional // one. assertTrue("servedCount", ProxoolFacade.getSnapshot(alias).getServedCount() > 0); // They should definitely all be returned to the pool once we're finished though assertEquals("activeCount", 0, ProxoolFacade.getSnapshot(alias).getActiveConnectionCount()); } } /* Revision history: $Log: HibernateTest.java,v $ Revision 1.3 2006/03/24 00:14:59 billhorsman Changes for Hibernate 3 Revision 1.2 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.1 2003/09/28 09:38:30 billhorsman New unit test for Hibernate. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/HouseKeeperTest.java0000644000175000017500000003775410730503131031416 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.admin.SnapshotIF; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.sql.SQLException; import java.util.Properties; /** * Test the house keeper in ConnectionPool * * @author bill * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.15 $, $Date: 2007/01/25 23:38:24 $ * @since Proxool 0.8 */ public class HouseKeeperTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(HouseKeeperTest.class); public HouseKeeperTest(String alias) { super(alias); } /** * Test that connections that remain active for longer than the configured * time are closed (and destroyed) automatically. */ public void testMaximumActiveTime() throws Exception { ConnectionResetter.setTriggerResetException(true); String testName = "maximumActiveTime"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY, "1000"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "1"); info.setProperty(ProxoolConstants.TRACE_PROPERTY, "true"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); ProxoolFacade.registerConnectionPool(url, info); Listener listener = new Listener(); ProxoolFacade.addConnectionListener(alias, listener); assertEquals("Shouldn't be any active connections yet", 0, ProxoolFacade.getSnapshot(alias, false).getServedCount()); final Connection connection = DriverManager.getConnection(url); connection.setAutoCommit(false); connection.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); long start = System.currentTimeMillis(); assertEquals("We just opened 1 connection", 1, ProxoolFacade.getSnapshot(alias, false).getServedCount()); new ResultMonitor() { public boolean check() throws Exception { return connection.isClosed(); } }.getResult(); try { Thread.sleep(3000); } catch (InterruptedException e) { LOG.debug("Awoken."); } long elapsed = System.currentTimeMillis() - start; assertTrue("Connection has not been closed after " + elapsed + " milliseconds as expected", connection.isClosed()); assertTrue("onAboutToDie not called as expected", listener.called); assertEquals("Expected the connection to be inactive", 0, ProxoolFacade.getSnapshot(alias, false).getActiveConnectionCount()); try { connection.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); fail("Calling createStatement() on a closed connection should fail"); } catch (Exception e) { // s'okay. We expected this LOG.debug("Ignoring expected exception: " + e.getMessage()); } // Now close the connection ourselves. It's already been closed by the House Keeper but nothing bad should // happen if we do it again now. connection.close(); // Let's see if the prototyper builds another one try { Thread.sleep(3000); } catch (InterruptedException e) { LOG.debug("Awoken."); } SnapshotIF snapshot = ProxoolFacade.getSnapshot(alias, false); assertEquals("activeConnectionCount", 0, snapshot.getActiveConnectionCount()); assertEquals("availableConnectionCount", 1, snapshot.getAvailableConnectionCount()); assertEquals("connectionCount", 1, snapshot.getConnectionCount()); } /** * Test that connections that remain active for longer than the configured * time are closed (and destroyed) automatically. Also, it gets errors during * reset. We don't want the connectionCount to be decremented twice. */ public void testMaximumActiveTimeWithResetFailure() throws Exception { try { ConnectionResetter.setTriggerResetException(true); String testName = "maximumActiveTimeWithResetFailure"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY, "1000"); info.setProperty(ProxoolConstants.TRACE_PROPERTY, "true"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); ProxoolFacade.registerConnectionPool(url, info); assertEquals("Shouldn't be any active connections yet", 0, ProxoolFacade.getSnapshot(alias, false).getServedCount()); final Connection connection = DriverManager.getConnection(url); connection.setAutoCommit(false); connection.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); long start = System.currentTimeMillis(); assertEquals("We just opened 1 connection", 1, ProxoolFacade.getSnapshot(alias, false).getServedCount()); new ResultMonitor() { public boolean check() throws Exception { return connection.isClosed(); } }.getResult(); try { Thread.sleep(3000); } catch (InterruptedException e) { LOG.debug("Awoken."); } long elapsed = System.currentTimeMillis() - start; assertTrue("Connection has not been closed after " + elapsed + " milliseconds as expected", connection.isClosed()); assertEquals("Expected the connection to be inactive", 0, ProxoolFacade.getSnapshot(alias, false).getActiveConnectionCount()); try { connection.createStatement().executeQuery(TestConstants.HYPERSONIC_TEST_SQL); fail("Calling createStatement() on a closed connection should fail"); } catch (Exception e) { // s'okay. We expected this LOG.debug("Ignoring expected exception: " + e.getMessage()); } // Now close the connection ourselves. It's already been closed by the House Keeper but nothing bad should // happen if we do it again now. connection.close(); // Let's see if the prototyper builds another one try { Thread.sleep(3000); } catch (InterruptedException e) { LOG.debug("Awoken."); } SnapshotIF snapshot = ProxoolFacade.getSnapshot(alias, false); assertEquals("activeConnectionCount", 0, snapshot.getActiveConnectionCount()); assertEquals("availableConnectionCount", 0, snapshot.getAvailableConnectionCount()); assertEquals("connectionCount", 0, snapshot.getConnectionCount()); } finally { // Back to normal ConnectionResetter.setTriggerResetException(false); } } /** * Test that house keeper destroys connections that fail configured * the test sql */ public void testHouseKeeperTestSql() throws Exception { String testName = "houseKeeperTestSql"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, "SELECT NOW"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); ProxoolFacade.registerConnectionPool(url, info); DriverManager.getConnection(url).close(); try { Thread.sleep(3000); } catch (InterruptedException e) { LOG.debug("Awoken."); } DriverManager.getConnection(url).close(); } /** * Test that house keeper destroys connections that fail configured * the test sql */ public void testInvalidBeforeUse() throws Exception { String testName = "invalidBeforeUse"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, "Invalid test"); info.setProperty(ProxoolConstants.TEST_BEFORE_USE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.TRACE_PROPERTY, Boolean.TRUE.toString()); ProxoolFacade.registerConnectionPool(url, info); // This should trigger a test followed the actual executed command. Because we've // deliberately made the test invalid, we should get an exception when getting a // connection Connection connection = null; Statement s = null; try { connection = DriverManager.getConnection(url); s = connection.createStatement(); s.execute(TestConstants.HYPERSONIC_TEST_SQL); fail("Expected to get an exception because the test failed"); } catch (SQLException e) { // Log message only so we don't get a worrying stack trace LOG.debug("Expected exception: " + e.getMessage()); } } /** * Test that house keeper destroys connections that fail configured * the test sql */ public void testInvalidAfterUse() throws Exception { String testName = "invalidAfterUse"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, "Invalid test"); info.setProperty(ProxoolConstants.TEST_AFTER_USE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.TRACE_PROPERTY, Boolean.TRUE.toString()); ProxoolFacade.registerConnectionPool(url, info); // This should trigger a test as soon as we close the connection. Because we've // deliberately made the test invalid then it should get thrown away Connection connection = null; Statement s = null; try { connection = DriverManager.getConnection(url); s = connection.createStatement(); s.execute(TestConstants.HYPERSONIC_TEST_SQL); } finally { if (connection != null) { connection.close(); } } // There should be no available connections. We don't have a minimum setup and the one we // just created on demand got thrown away because it failed its test assertEquals("Available connections", 0, ProxoolFacade.getSnapshot(alias).getAvailableConnectionCount()); } public void testBeforeAndAfterUse() throws Exception { String testName = "beforeAndAfterUse"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); info.setProperty(ProxoolConstants.TEST_BEFORE_USE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.TEST_AFTER_USE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.TRACE_PROPERTY, Boolean.TRUE.toString()); ProxoolFacade.registerConnectionPool(url, info); Connection connection = null; Statement s = null; try { connection = DriverManager.getConnection(url); s = connection.createStatement(); s.execute(TestConstants.HYPERSONIC_TEST_SQL); } finally { if (connection != null) { connection.close(); } } // There should be one available connection. assertEquals("Available connections", 1, ProxoolFacade.getSnapshot(alias).getAvailableConnectionCount()); } class Listener implements ConnectionListenerIF { boolean called; public void onBirth(Connection connection) throws SQLException {} public void onDeath(Connection connection, int reasonCode) throws SQLException { called = (reasonCode == ConnectionListenerIF.MAXIMUM_ACTIVE_TIME_EXPIRED); } public void onExecute(String command, long elapsedTime) {} public void onFail(String command, Exception exception) {} } } /* Revision history: $Log: HouseKeeperTest.java,v $ Revision 1.15 2007/01/25 23:38:24 billhorsman Scrapped onAboutToDie and altered onDeath signature instead. Now includes reasonCode (see ConnectionListenerIF) Revision 1.14 2007/01/25 00:10:24 billhorsman New onAboutToDie event for ConnectionListenerIF that gets called if the maximum-active-time is exceeded. Revision 1.13 2006/03/24 00:17:32 billhorsman Correct alias name Revision 1.12 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2005/10/07 08:11:34 billhorsman New test for reset failure Revision 1.10 2005/10/02 12:30:59 billhorsman Improved test by checking connectionCount Revision 1.9 2004/06/02 21:05:19 billhorsman Don't log worrying stack traces for expected exceptions. Revision 1.8 2003/09/30 18:40:16 billhorsman New tests for test-before-use and test-after-use Revision 1.7 2003/09/11 23:58:05 billhorsman New test for house-keeper-test-sql Revision 1.6 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.5 2003/03/03 17:08:57 billhorsman all tests now extend AbstractProxoolTest Revision 1.4 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.3 2003/03/02 00:53:49 billhorsman more robust wait Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/HsqlConnectionIF.java0000644000175000017500000000155310730503131031471 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.SQLException; import java.sql.Connection; /** * Supports {@link InjectableInterfaceTest} * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.2 $, $Date: 2004/06/17 21:33:54 $ * @since 0.9.0 */ public interface HsqlConnectionIF extends Connection { } /* Revision history: $Log: HsqlConnectionIF.java,v $ Revision 1.2 2004/06/17 21:33:54 billhorsman Mistake. Can't put private classes in the interface. Doh. Revision 1.1 2004/06/02 20:59:52 billhorsman New injectable interface tests */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/HsqlPreparedStatementIF.java0000644000175000017500000000155110730503131033017 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.PreparedStatement; /** * Supports {@link InjectableInterfaceTest} * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.2 $, $Date: 2004/06/17 21:33:54 $ * @since 0.9.0 */ public interface HsqlPreparedStatementIF extends PreparedStatement { } /* Revision history: $Log: HsqlPreparedStatementIF.java,v $ Revision 1.2 2004/06/17 21:33:54 billhorsman Mistake. Can't put private classes in the interface. Doh. Revision 1.1 2004/06/02 20:59:52 billhorsman New injectable interface tests */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/HsqlStatementIF.java0000644000175000017500000000154710730503130031340 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.SQLException; import java.sql.Statement; /** * Supports {@link InjectableInterfaceTest} * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.2 $, $Date: 2004/06/17 21:33:54 $ * @since 0.9.0 */ public interface HsqlStatementIF extends Statement { } /* Revision history: $Log: HsqlStatementIF.java,v $ Revision 1.2 2004/06/17 21:33:54 billhorsman Mistake. Can't put private classes in the interface. Doh. Revision 1.1 2004/06/02 20:59:52 billhorsman New injectable interface tests */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/HypersonicTest.java0000644000175000017500000000412210730503130031300 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Very basic test to see if Hypersonic test database is working * * @version $Revision: 1.13 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class HypersonicTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(HypersonicTest.class); private static final String TEST_TABLE = "test"; public HypersonicTest(String s) { super(s); } public void testHypersonic() throws Exception { String testName = "hypersonic"; TestHelper.getDirectConnection().close(); } } /* Revision history: $Log: HypersonicTest.java,v $ Revision 1.13 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.12 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.11 2003/03/03 17:08:57 billhorsman all tests now extend AbstractProxoolTest Revision 1.10 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.9 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.8 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.7 2003/02/19 15:14:23 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.6 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.5 2002/12/16 17:04:55 billhorsman new test structure Revision 1.4 2002/11/09 16:01:38 billhorsman fix doc Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.1 2002/10/29 23:18:30 billhorsman Tests that hypersonic db works ok */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/InjectableInterfaceTest.java0000644000175000017500000001341410730503130033042 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Properties; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.CallableStatement; /** * Tests whether we can inject a new interface into one of the proxy objects * @version $Revision: 1.3 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class InjectableInterfaceTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(InjectableInterfaceTest.class); /** * @see AbstractProxoolTest */ public InjectableInterfaceTest(String alias) { super(alias); } /** * Get a connection and cast it into the appropriate interface */ public void testInjectableConnectionInterface() throws Exception { String alias = "injectableConnectionInterface"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.INJECTABLE_CONNECTION_INTERFACE_NAME_PROPERTY, HsqlConnectionIF.class.getName()); Connection c1 = DriverManager.getConnection(url, info); // Can we cast it? HsqlConnectionIF hc = (HsqlConnectionIF) c1; // TODO - need to test a vendor specific method? // Does close() still work? hc.close(); assertTrue("c1.isClosed()", c1.isClosed()); } /** * Get a statement and cast it into the appropriate interface */ public void testInjectableStatementInterface() throws Exception { String alias = "injectableStatementInterface"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.INJECTABLE_STATEMENT_INTERFACE_NAME_PROPERTY, HsqlStatementIF.class.getName()); Connection c1 = DriverManager.getConnection(url, info); Statement s = c1.createStatement(); // Can we cast it? HsqlStatementIF hs = (HsqlStatementIF) s; // TODO : call a vendor specific method? // hs.checkClosed(); // Does close() still work? hs.close(); c1.close(); } /** * Get a statement and cast it into the appropriate interface */ public void testInjectablePreparedStatementInterface() throws Exception { String alias = "injectablePreparedStatementInterface"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME_PROPERTY, HsqlPreparedStatementIF.class.getName()); Connection c1 = DriverManager.getConnection(url, info); PreparedStatement ps = c1.prepareStatement(TestConstants.HYPERSONIC_TEST_SQL); // Can we cast it? HsqlPreparedStatementIF hps = (HsqlPreparedStatementIF) ps; // TODO : call a vendor specific method? // hps.build(); // Does close() still work? hps.close(); c1.close(); } /** * Get a statement and cast it into the appropriate interface */ public void testInjectableCallableStatementInterface() throws Exception { String alias = "injectableCallableStatementInterface"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME_PROPERTY, HsqlPreparedStatementIF.class.getName()); Connection c1 = DriverManager.getConnection(url, info); CallableStatement cs = c1.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); // Can we cast it? (Note: HSQLDB uses the same class for both Prepared and Callable statements) HsqlPreparedStatementIF hps = (HsqlPreparedStatementIF) cs; // TODO - call a vendor specific method? // Does close() still work? hps.close(); c1.close(); } } /* Revision history: $Log: InjectableInterfaceTest.java,v $ Revision 1.3 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.2 2004/06/17 21:36:39 billhorsman Removed call to private methods. They're going to fail anyway. Revision 1.1 2004/06/02 20:59:52 billhorsman New injectable interface tests */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/KillTest.java0000644000175000017500000001603310730503131030055 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.util.Properties; import java.sql.Connection; import java.sql.DriverManager; /** * Tests whether we can kill connections when we want to * @version $Revision: 1.2 $, $Date: 2006/05/23 21:33:52 $ * @author Bill Horsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class KillTest extends AbstractProxoolTest { private static final boolean MERCIFUL = true; private static final boolean MERCILESS = false; private static final boolean DETAILED = true; /** * @see AbstractProxoolTest */ public KillTest(String alias) { super(alias); } /** * @see ProxoolFacade#killAllConnections(java.lang.String, java.lang.String, boolean) */ public void testKillAllMercifully() throws Exception { String alias = "killAllMercifully"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); Connection c1 = DriverManager.getConnection(url, info); Connection c2 = DriverManager.getConnection(url, info); c1.close(); c2.close(); // There should now be two connections built assertEquals("Connection count", 2, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); ProxoolFacade.killAllConnections(alias, "testing", MERCIFUL); // None left assertEquals("Connection count", 0, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); } /** * @see ProxoolFacade#killAllConnections(java.lang.String, java.lang.String, boolean) */ public void testKillAllMercilessly() throws Exception { String alias = "killAllMercilessly"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); Connection c1 = DriverManager.getConnection(url, info); Connection c2 = DriverManager.getConnection(url, info); // There should now be two connections built assertEquals("Connection count", 2, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); ProxoolFacade.killAllConnections(alias, "testing", MERCILESS); // None left assertEquals("Connection count", 0, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); c1.close(); c2.close(); } /** * @see ProxoolFacade#killConnecton(java.lang.String, long, boolean) */ public void testKillOneById() throws Exception { String alias = "killOneById"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); Connection c1 = DriverManager.getConnection(url, info); Connection c2 = DriverManager.getConnection(url, info); c1.close(); c2.close(); // There should now be two connections built assertEquals("Connection count", 2, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); long id1 = ProxoolFacade.getId(c1); long id2 = ProxoolFacade.getId(c2); ProxoolFacade.killConnecton(alias, id1, MERCIFUL); // One left assertEquals("Connection count", 1, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); assertEquals("Active count", 0, ProxoolFacade.getSnapshot(alias, DETAILED).getActiveConnectionCount()); Connection c3 = DriverManager.getConnection(url, info); assertEquals("Active count", 1, ProxoolFacade.getSnapshot(alias, DETAILED).getActiveConnectionCount()); long id3 = ProxoolFacade.getId(c3); Connection c4 = DriverManager.getConnection(url, info); assertEquals("Active count", 2, ProxoolFacade.getSnapshot(alias, DETAILED).getActiveConnectionCount()); long id4 = ProxoolFacade.getId(c4); c3.close(); c4.close(); assertTrue("Killed ID served", id3 != id1); assertTrue("Killed ID served", id4 != id1); } /** * @see ProxoolFacade#killConnecton(java.lang.String, long, boolean) */ public void testKillOneByConnection() throws Exception { String alias = "killOneByConnection"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); Connection c1 = DriverManager.getConnection(url, info); Connection c2 = DriverManager.getConnection(url, info); c1.close(); c2.close(); // There should now be two connections built assertEquals("Connection count", 2, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); long id1 = ProxoolFacade.getId(c1); long id2 = ProxoolFacade.getId(c2); ProxoolFacade.killConnecton(c1, MERCIFUL); // One left assertEquals("Connection count", 1, ProxoolFacade.getSnapshot(alias, DETAILED).getConnectionInfos().length); Connection c3 = DriverManager.getConnection(url, info); long id3 = ProxoolFacade.getId(c3); Connection c4 = DriverManager.getConnection(url, info); long id4 = ProxoolFacade.getId(c4); c3.close(); c4.close(); assertTrue("Killed ID served", id3 != id1); assertTrue("Killed ID served", id4 != id1); } } /* Revision history: $Log: KillTest.java,v $ Revision 1.2 2006/05/23 21:33:52 billhorsman More asserts Revision 1.1 2004/03/23 21:14:24 billhorsman new tests */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ManyPoolsTest.java0000644000175000017500000000744010730503131031105 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.admin.SnapshotResultMonitor; import org.logicalcobwebs.proxool.admin.SnapshotIF; import java.util.Properties; /** * Test whether Proxool is happy to run lots of pools. Is it scalable? * * @version $Revision: 1.4 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ManyPoolsTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ManyPoolsTest.class); public ManyPoolsTest(String alias) { super(alias); } public void testManyPools() throws ProxoolException { final String testName = "manyPools"; Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "0"); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "5"); info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "30000"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); final int poolCount = 100; String alias[] = new String[poolCount]; for (int i = 0; i < poolCount; i++) { alias[i] = testName + "_" + i; String url = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER + alias[i] + ProxoolConstants.URL_DELIMITER + TestConstants.HYPERSONIC_DRIVER + ProxoolConstants.URL_DELIMITER + TestConstants.HYPERSONIC_URL_PREFIX + i; ProxoolFacade.registerConnectionPool(url, info); } SnapshotResultMonitor srm = new SnapshotResultMonitor(alias[poolCount - 1]) { public boolean check(SnapshotIF snapshot) throws Exception { LOG.debug("Checking availableConnectionCount: " + snapshot.getAvailableConnectionCount()); return (snapshot.getAvailableConnectionCount() == 2); } }; srm.setDelay(2000); srm.setTimeout(300000); assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); assertEquals("activeConnectionCount", 0, srm.getSnapshot().getActiveConnectionCount()); } } /* Revision history: $Log: ManyPoolsTest.java,v $ Revision 1.4 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.3 2004/07/13 20:36:57 billhorsman Open a different database for each pool. Otherwise Hypersonic has some threading issues. Revision 1.2 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.1 2003/03/05 18:49:27 billhorsman moved test to right tree Revision 1.1 2003/03/05 18:42:33 billhorsman big refactor of prototyping and house keeping to drastically reduce the number of threads when using many pools */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/PerformanceTest.java0000644000175000017500000003201510730503131031421 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.admin.StatisticsIF; import org.logicalcobwebs.proxool.admin.StatisticsListenerIF; import org.logicalcobwebs.proxool.admin.SnapshotIF; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import java.text.DecimalFormat; /** * Tests how fast Proxool is compared to the "perfect" pool, {@link SimpoolAdapter}. * * @version $Revision: 1.18 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class PerformanceTest extends AbstractProxoolTest implements StatisticsListenerIF { private static final Log LOG = LogFactory.getLog(PerformanceTest.class); private static DecimalFormat millisecondsFormat = new DecimalFormat("0.00"); private Thread waitingThead; private StatisticsIF statistics; private static final int PERIOD = 5; private static final int COUNT = 6; private long servedCount; public PerformanceTest(String s) { super(s); } /** * Test how many connections we can serve if we go as fast as we can! * @throws ProxoolException if anything goes wrong */ public void testPerformance() throws ProxoolException, InterruptedException { waitingThead = Thread.currentThread(); String alias = "testPeformance"; int threadCount = 20; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); /* info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, String.valueOf(PERIOD) + "s"); info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_INFO); */ ProxoolFacade.registerConnectionPool(url, info); /* ProxoolFacade.addStatisticsListener(alias, this); */ doWait(); AnnoyingConnector[] annoyingConnectors = new AnnoyingConnector[threadCount]; for (int i = 0; i < annoyingConnectors.length; i++) { annoyingConnectors[i] = new AnnoyingConnector(alias); Thread t = new Thread(annoyingConnectors[i]); t.start(); } for (int i = 0; i < COUNT; i++) { doWait(); } for (int i = 0; i < annoyingConnectors.length; i++) { annoyingConnectors[i].cancel(); } for (int i = 0; i < 5; i++) { int activeConnectionCount = ProxoolFacade.getSnapshot(alias).getActiveConnectionCount(); if (activeConnectionCount > 0) { LOG.info("Waiting for 10 seconds for connections to become inactive (" + activeConnectionCount + ")"); Thread.sleep(10000); } else { break; } } final SnapshotIF snapshot = ProxoolFacade.getSnapshot(alias, true); LOG.info("Active count: " + snapshot.getActiveConnectionCount()); LOG.info("Available count: " + snapshot.getAvailableConnectionCount()); ConnectionInfoIF[] cis = snapshot.getConnectionInfos(); LOG.info("Found " + cis.length + " connetions with a detailed snapshot" + ""); for (int i = 0; i < cis.length; i++) { ConnectionInfoIF ci = cis[i]; LOG.info("#" + ci.getId() + ": " + ci.getStatus() + ", lap=" + (ci.getTimeLastStopActive() - ci.getTimeLastStartActive())); } LOG.info("Served a total of " + ProxoolFacade.getSnapshot(alias).getServedCount()); } private void doWait() { synchronized (Thread.currentThread()) { try { Thread.currentThread().wait(60000); } catch (InterruptedException e) { fail("Statistics didn't arrive as expected"); } } } public void statistics(String alias, StatisticsIF statistics) { this.servedCount += statistics.getServedCount(); this.statistics = statistics; synchronized (waitingThead) { waitingThead.notify(); } } public void testSnapshotImpact() throws ProxoolException { waitingThead = Thread.currentThread(); String alias = "testPeformance"; int threadCount = 10; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, String.valueOf(PERIOD) + "s"); info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_INFO); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); ProxoolFacade.registerConnectionPool(url, info); ProxoolFacade.addStatisticsListener(alias, this); DisagreeableSnapshotter disagreeableSnapshotter = new DisagreeableSnapshotter(alias); new Thread(disagreeableSnapshotter).start(); AnnoyingConnector[] annoyingConnectors = new AnnoyingConnector[threadCount]; for (int i = 0; i < annoyingConnectors.length; i++) { annoyingConnectors[i] = new AnnoyingConnector(alias); Thread t = new Thread(annoyingConnectors[i]); t.start(); } doWait(); int servedCount = 0; for (int i = 0; i < COUNT; i++) { doWait(); servedCount += statistics.getServedCount(); assertTrue("disparityNoticed", !disagreeableSnapshotter.isDisparityNoticed()); } for (int i = 0; i < annoyingConnectors.length; i++) { annoyingConnectors[i].cancel(); } disagreeableSnapshotter.cancel(); long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < 30000) { int threadsRunning = 0; for (int i = 0; i < annoyingConnectors.length; i++) { if (annoyingConnectors[i].isRunning()) { threadsRunning++; } } if (disagreeableSnapshotter.isRunning()) { threadsRunning++; } if (threadsRunning == 0) { break; } } assertTrue("disparityNoticed", !disagreeableSnapshotter.isDisparityNoticed()); LOG.info("Served " + servedCount + " at " + millisecondsFormat.format((double) (1000 * PERIOD * COUNT) / (double) servedCount) + " ms per connection"); } class DisagreeableSnapshotter implements Runnable { private String alias; private boolean cancelled; private boolean disparityNoticed; private boolean running; public DisagreeableSnapshotter(String alias) { this.alias = alias; } public void run() { running = true; int snapshotCount = 0; while (!cancelled) { try { Thread.sleep(100); } catch (InterruptedException e) { LOG.error("Awoken", e); } try { SnapshotIF s = ProxoolFacade.getSnapshot(alias, true); int c1 = s.getActiveConnectionCount(); int c2 = getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_ACTIVE); int v1 = s.getAvailableConnectionCount(); int v2 = getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_AVAILABLE); int o1 = s.getOfflineConnectionCount(); int o2 = getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_OFFLINE); if (c1 != c2 || v1 != v2 || o1 != o2) { LOG.error("Disparity noticed. Active: " + c1 + (c1 == c2 ? " == " : " != ") + c2 + ", available: " + v1 + (v1 == v2 ? " == " : " != ") + v2 + ", offline: " + o1 + (o1 == o2 ? " == " : " != ") + o2); disparityNoticed = true; } snapshotCount++; } catch (ProxoolException e) { LOG.error("Couldn't get snapshot", e); } } LOG.info(snapshotCount + " snapshots taken"); running = false; } public boolean isRunning() { return running; } private int getCount(ConnectionInfoIF[] connectionInfos, int status) { int count = 0; for (int i = 0; i < connectionInfos.length; i++) { if (connectionInfos[i].getStatus() == status) { count++; } } return count; } public boolean isDisparityNoticed() { return disparityNoticed; } public void cancel() { cancelled = true; } } class AnnoyingConnector implements Runnable { private String alias; private boolean cancelled; private int exceptionCount; private boolean running = false; public AnnoyingConnector(String alias) { this.alias = alias; } public void run() { running = true; while (!cancelled) { try { Connection connection = null; Statement s = null; try { connection = DriverManager.getConnection(TestHelper.buildProxoolUrl(alias)); s = connection.createStatement(); Thread.yield(); } finally { if (s != null) { s.close(); } if (connection != null) { connection.close(); } } } catch (SQLException e) { LOG.error(Thread.currentThread().getName(), e); exceptionCount++; } } running = false; } public boolean isRunning() { return running; } public void cancel() { cancelled = true; } public int getExceptionCount() { return exceptionCount; } } } /* Revision history: $Log: PerformanceTest.java,v $ Revision 1.18 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.17 2003/11/04 13:54:02 billhorsman checkstyle Revision 1.16 2003/03/11 14:58:32 billhorsman put PerformanceTest back in the global test Revision 1.15 2003/03/11 14:51:43 billhorsman more concurrency fixes relating to snapshots Revision 1.14 2003/03/10 23:49:04 billhorsman new test to measure the impact of taking snapshots Revision 1.13 2003/03/10 15:31:26 billhorsman fixes Revision 1.12 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.11 2003/03/03 17:08:57 billhorsman all tests now extend AbstractProxoolTest Revision 1.10 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.9 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.8 2003/02/19 15:14:23 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.7 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.6 2002/12/16 17:05:05 billhorsman new test structure Revision 1.5 2002/11/09 16:01:53 billhorsman fix doc Revision 1.4 2002/11/02 14:22:16 billhorsman Documentation Revision 1.3 2002/11/02 13:57:34 billhorsman checkstyle Revision 1.2 2002/11/02 11:37:48 billhorsman New tests Revision 1.1 2002/10/30 21:17:51 billhorsman new performance tests */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/PropertyTest.java0000644000175000017500000001037110730503131031005 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * Tests whether {@link ConnectionPoolDefinition} recognises properties * properly * @version $Revision: 1.3 $, $Date: 2006/03/24 00:18:46 $ * @author billhorsman * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8.2 */ public class PropertyTest extends AbstractProxoolTest { public PropertyTest(String alias) { super(alias); } /** * Test whether we are successfully passing properties onto the delegate driver. This * relies on a feature of Hypersonic 1.7.1 where ResultSetMetaData.isWritable() is * unsupported. The default behaviour, however, is just to return a value that maybe * incorrect but without throwing an exception. If you set the property jdbc.strict_md = true * then Hypersonic does throw an exception. This might change in future versions of Hypersonic * so we should keep an eye on this. * See http://hsqldb.sourceforge.net/doc/src/org/hsqldb/jdbcResultSet.html */ public void testDelegateProperty() throws Exception { String testName = "delegateProperty"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); Connection c = null; try { c = DriverManager.getConnection(url, info); Statement s = c.createStatement(); try { s.execute("drop table z"); } catch (SQLException e) { // Probably because it doesn't exist. } s.execute("create table z (a int)"); s.execute("select * from z"); ResultSet rs = s.getResultSet(); ResultSetMetaData rsmd = rs.getMetaData(); // by default, this should work without error (even if the value returned is rubbish) rsmd.isWritable(1); } finally { if (c != null) { c.close(); c = null; } } /* This doesn't work with HSQLDB 1.8.0. They don't seem to mention the strict_md propertry in their documentation anymore. // And now test with the strict meta data info.setProperty("jdbc.strict_md", "true"); try { c = DriverManager.getConnection(url, info); Statement s = c.createStatement(); s.execute("select * from z"); ResultSet rs = s.getResultSet(); ResultSetMetaData rsmd = rs.getMetaData(); try { rsmd.isWritable(1); fail("Expected isWritable() to throw unsupported exception"); } catch (SQLException e) { // Expected an exception } } finally { if (c != null) { c.close(); } } */ } } /* Revision history: $Log: PropertyTest.java,v $ Revision 1.3 2006/03/24 00:18:46 billhorsman Changes for HSQL 1.8 Revision 1.2 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.1 2003/11/04 13:22:43 billhorsman New test for delegate properties */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/PrototyperTest.java0000644000175000017500000001633510730503131031356 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.logicalcobwebs.proxool.admin.SnapshotIF; import org.logicalcobwebs.proxool.admin.SnapshotResultMonitor; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; /** * Test the prototyper in ConnectionPool * * @version $Revision: 1.11 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class PrototyperTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(PrototyperTest.class); public PrototyperTest(String alias) { super(alias); } /** * Test that spare connections are made as we run out of them */ public void testPrototypeCount() throws Exception { final String testName = "prototypeCount"; final String alias = testName; Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "0"); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "5"); info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); String url = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER + alias + ProxoolConstants.URL_DELIMITER + TestConstants.HYPERSONIC_DRIVER + ProxoolConstants.URL_DELIMITER + TestConstants.HYPERSONIC_TEST_URL; ProxoolFacade.registerConnectionPool(url, info); Connection[] connections = new Connection[6]; SnapshotResultMonitor srm = new SnapshotResultMonitor(alias) { public boolean check(SnapshotIF snapshot) throws Exception { SnapshotIF s = ProxoolFacade.getSnapshot(alias); return (s.getActiveConnectionCount() == 0 && s.getAvailableConnectionCount() >= 2); } }; assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); assertEquals("activeConnectionCount", 0, srm.getSnapshot().getActiveConnectionCount()); assertEquals("availableConnectionCount", 2, srm.getSnapshot().getAvailableConnectionCount()); connections[0] = DriverManager.getConnection(url); srm = new SnapshotResultMonitor(alias) { public boolean check(SnapshotIF snapshot) throws Exception { SnapshotIF s = ProxoolFacade.getSnapshot(alias); return (s.getActiveConnectionCount() == 1 && s.getAvailableConnectionCount() >= 2); } }; assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); assertEquals("activeConnectionCount", 1, srm.getSnapshot().getActiveConnectionCount()); assertEquals("availableConnectionCount", 2, srm.getSnapshot().getAvailableConnectionCount()); connections[1] = DriverManager.getConnection(url); connections[2] = DriverManager.getConnection(url); connections[3] = DriverManager.getConnection(url); srm = new SnapshotResultMonitor(alias) { public boolean check(SnapshotIF snapshot) throws Exception { SnapshotIF s = ProxoolFacade.getSnapshot(alias); return (s.getActiveConnectionCount() == 4 && s.getAvailableConnectionCount() == 1); } }; assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); assertEquals("activeConnectionCount", 4, srm.getSnapshot().getActiveConnectionCount()); assertEquals("availableConnectionCount", 1, srm.getSnapshot().getAvailableConnectionCount()); } /** * Test that the minimum number of connections is maintained */ public void testMinimumConnectionCount() throws Exception { String testName = "miniumumConnectionCount"; final String alias = testName; Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, Boolean.TRUE.toString()); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "2"); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "5"); info.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "0"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); ProxoolFacade.registerConnectionPool(url, info); ResultMonitor srm = new SnapshotResultMonitor(alias) { public boolean check(SnapshotIF snapshot) throws Exception { SnapshotIF s = ProxoolFacade.getSnapshot(alias); return (s.getAvailableConnectionCount() == 2); } }; assertEquals("Timeout", ResultMonitor.SUCCESS, srm.getResult()); assertEquals("availableConnectionCount", 2, ProxoolFacade.getSnapshot(alias, false).getAvailableConnectionCount()); } } /* Revision history: $Log: PrototyperTest.java,v $ Revision 1.11 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.10 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.9 2003/03/10 15:31:26 billhorsman fixes Revision 1.8 2003/03/06 10:11:24 billhorsman trap timeouts better Revision 1.7 2003/03/05 18:45:17 billhorsman better threading Revision 1.6 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.5 2003/03/03 17:08:57 billhorsman all tests now extend AbstractProxoolTest Revision 1.4 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.3 2003/03/01 15:14:15 billhorsman new ResultMonitor to help cope with test threads Revision 1.2 2003/03/01 00:39:23 billhorsman made more robust Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ProxoolAdapter.java0000644000175000017500000001341210730503131031263 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.logicalcobwebs.dbscript.ConnectionAdapterIF; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * Provides Proxool connections to the {@link org.logicalcobwebs.dbscript.ScriptFacade ScriptFacade} * * @version $Revision: 1.22 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class ProxoolAdapter implements ConnectionAdapterIF, ConfigurationListenerIF { private static final Log LOG = LogFactory.getLog(ProxoolAdapter.class); private String alias = String.valueOf(hashCode()); private String fullUrl; private Properties changedInfo; private Properties completeInfo; /** * Use this constructor if you want to define the alias * @param alias the alias of the pool */ public ProxoolAdapter(String alias) { this.alias = alias; } /** * Default constructor. Will use the hashCode as the alias for the pool */ public ProxoolAdapter() { } public void definitionUpdated(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo) { setCompleteInfo(completeInfo); setChangedInfo(changedInfo); LOG.debug("Definition updated " + connectionPoolDefinition.getCompleteUrl()); if (changedInfo != null && changedInfo.size() > 0) { LOG.debug(changedInfo.size() + " properties updated"); } else { LOG.debug("No properties updated"); } } public Properties getChangedInfo() { return changedInfo; } public void setChangedInfo(Properties changedInfo) { this.changedInfo = changedInfo; } public Properties getCompleteInfo() { return completeInfo; } public void setCompleteInfo(Properties completeInfo) { this.completeInfo = completeInfo; } public String getName() { return "proxool"; } public void update(Properties info) throws SQLException, ProxoolException { ProxoolFacade.updateConnectionPool(getFullUrl(), info); } public void update(String url) throws SQLException, ProxoolException { ProxoolFacade.updateConnectionPool(url, null); } public void setup(String driver, String url, Properties info) throws SQLException, ProxoolException { try { Class.forName(ProxoolDriver.class.getName()); } catch (ClassNotFoundException e) { throw new SQLException("Couldn't find " + driver); } fullUrl = TestHelper.buildProxoolUrl(alias, driver, url); ProxoolFacade.registerConnectionPool(fullUrl, info); ProxoolFacade.addConfigurationListener(alias, this); } public Connection getConnection() throws SQLException { return DriverManager.getConnection(ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER + alias); } public String getFullUrl() { return fullUrl; } public void closeConnection(Connection connection) throws SQLException { if (connection != null) { connection.close(); } } public void tearDown() { try { ProxoolFacade.removeConnectionPool(alias); } catch (ProxoolException e) { LOG.error("Problem tearing down " + alias, e); } } } /* Revision history: $Log: ProxoolAdapter.java,v $ Revision 1.22 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.21 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.20 2003/03/03 11:12:04 billhorsman fixed licence Revision 1.19 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.18 2003/02/26 16:05:49 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.17 2003/02/19 15:14:24 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.16 2003/02/07 10:09:58 billhorsman removed connectionPoolDefinition property. not needed. Revision 1.15 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.14 2003/01/23 11:13:40 billhorsman use new setConfiguratorListener method Revision 1.13 2003/01/18 15:13:13 billhorsman Signature changes (new ProxoolException thrown) on the ProxoolFacade API. Revision 1.12 2003/01/17 00:38:12 billhorsman wide ranging changes to clarify use of alias and url - this has led to some signature changes (new exceptions thrown) on the ProxoolFacade API. Revision 1.11 2002/12/16 16:41:59 billhorsman allow URL updates to pool Revision 1.10 2002/12/12 10:49:43 billhorsman now includes properties in definitionChanged event Revision 1.9 2002/12/04 13:20:10 billhorsman ConfigurationListenerIF test Revision 1.8 2002/11/13 20:23:38 billhorsman change method name, throw exceptions differently, trivial changes Revision 1.7 2002/11/09 16:09:06 billhorsman checkstyle Revision 1.6 2002/11/09 16:02:05 billhorsman fix doc Revision 1.5 2002/11/09 14:45:35 billhorsman only close connection if it is open Revision 1.4 2002/11/07 18:56:59 billhorsman allow explicit definition of alias Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 12:46:42 billhorsman improved debug Revision 1.1 2002/11/02 11:37:48 billhorsman New tests */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ProxoolDataSourceTest.java0000644000175000017500000001551410730503127032607 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.NamingManager; import javax.sql.DataSource; import java.util.Hashtable; import java.util.Properties; import tyrex.naming.MemoryContextFactory; /** * Tests the Proxool datasources. * * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @version $Revision: 1.2 $, $Date: 2006/03/23 11:51:24 $ * @since Proxool 0.9 */ public class ProxoolDataSourceTest extends AbstractProxoolTest { public ProxoolDataSourceTest(String alias) { super(alias); } /** * Test the Proxool managed DataSource */ public void testPreconfiguredDataSource() throws Exception { String alias = "preconfiguredDatasourceTest"; String jndiName = "TestDB"; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.JNDI_NAME_PROPERTY, jndiName); info.setProperty(ProxoolConstants.JNDI_PROPERTY_PREFIX + "java.naming.factory.initial", MemoryContextFactory.class.getName()); info.setProperty(ProxoolConstants.JNDI_PROPERTY_PREFIX + "java.naming.factory.url.pkgs", "tyrex.naming"); info.setProperty(ProxoolConstants.JNDI_PROPERTY_PREFIX + "java.naming.provider.url", alias); ProxoolFacade.registerConnectionPool(url, info); Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, MemoryContextFactory.class.getName()); env.put(Context.URL_PKG_PREFIXES, "tyrex.naming"); env.put(Context.PROVIDER_URL, alias); Context context = new InitialContext(env); DataSource dataSource = (DataSource) context.lookup(jndiName); assertNotNull("Connection was null.", dataSource.getConnection()); ProxoolFacade.removeConnectionPool(alias); context.close(); } /** * Test the bean configured DataSource. */ public void testBeanConfiguredDataSource() throws Exception { String alias = "beanConfiguredDataSourceTest"; String jndiName = "jdbc/beanConfiguredTestDB"; // pretend to be a J2EE server that instantites the data source // populates its properties and binds it to JNDI ProxoolDataSource dataSource = new ProxoolDataSource(); dataSource.setAlias(alias); dataSource.setDriver(TestConstants.HYPERSONIC_DRIVER); dataSource.setDriverUrl(TestConstants.HYPERSONIC_TEST_URL); dataSource.setUser(TestConstants.HYPERSONIC_USER); dataSource.setPassword(TestConstants.HYPERSONIC_PASSWORD); dataSource.setDelegateProperties("dummy=foo,anotherDummy=bar"); Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, MemoryContextFactory.class.getName()); env.put(Context.URL_PKG_PREFIXES, "tyrex.naming"); env.put(Context.PROVIDER_URL, alias); Context context = new InitialContext(env); context.createSubcontext("jdbc"); context.bind(jndiName, dataSource); context.close(); // end J2EE server // now... pretend to be a client. context = new InitialContext(env); DataSource clientDataSource = (DataSource) context.lookup(jndiName); assertNotNull("Connection was null.", clientDataSource.getConnection()); ConnectionPoolDefinitionIF cpd = ProxoolFacade.getConnectionPoolDefinition(alias); assertEquals("dummy", "foo", cpd.getDelegateProperty("dummy")); assertEquals("dummy", "bar", cpd.getDelegateProperty("anotherDummy")); ProxoolFacade.removeConnectionPool(alias); context.close(); } /** * Test the bean configured DataSource. */ public void testFactoryConfiguredDataSource() throws Exception { String alias = "factoryConfiguredDataSourceTest"; String jndiName = "jdbc/factoryConfiguredTestDB"; Reference reference = new Reference(ProxoolDataSource.class.getName(), ProxoolDataSource.class.getName(), null); reference.add(new StringRefAddr(ProxoolConstants.ALIAS_PROPERTY, alias)); reference.add(new StringRefAddr(ProxoolConstants.DRIVER_CLASS_PROPERTY, TestConstants.HYPERSONIC_DRIVER)); reference.add(new StringRefAddr(ProxoolConstants.DRIVER_URL_PROPERTY, TestConstants.HYPERSONIC_TEST_URL)); reference.add(new StringRefAddr(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER)); reference.add(new StringRefAddr(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD)); reference.add(new StringRefAddr("dummy", "foo")); reference.add(new StringRefAddr("anotherDummy", "bar")); // pretend to be a JNDI aware container that builds the DataSource // using its factory Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, MemoryContextFactory.class.getName()); env.put(Context.URL_PKG_PREFIXES, "tyrex.naming"); env.put(Context.PROVIDER_URL, alias); Context context = new InitialContext(env); context.createSubcontext("jdbc"); context.bind(jndiName, NamingManager.getObjectInstance(reference, null, null, null)); context.close(); // end JNDI aware container // now... pretend to be a client. context = new InitialContext(env); DataSource clientDataSource = (DataSource) context.lookup(jndiName); assertNotNull("Connection was null.", clientDataSource.getConnection()); ConnectionPoolDefinitionIF cpd = ProxoolFacade.getConnectionPoolDefinition(alias); assertEquals("dummy", "foo", cpd.getDelegateProperty("dummy")); assertEquals("dummy", "bar", cpd.getDelegateProperty("anotherDummy")); ProxoolFacade.removeConnectionPool(alias); context.close(); } } /* Revision history: $Log: ProxoolDataSourceTest.java,v $ Revision 1.2 2006/03/23 11:51:24 billhorsman Allow for delegate properties Revision 1.1 2004/03/18 17:10:01 chr32 Renamed DataSourceTest -> ProxoolDataSourceTest. Added test for factory-configured mode. Revision 1.4 2004/03/15 23:56:33 chr32 Added test for ProxoolDataSource. Revision 1.3 2004/03/15 02:46:09 chr32 Added initial ProxoolDataSourceTest. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ProxyConnectionTest.java0000644000175000017500000000665710730503130032335 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * Test whether ProxyConnection works * * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ProxyConnectionTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ProxyConnectionTest.class); public ProxyConnectionTest(String alias) { super(alias); } /** * Tests whether a statement gets closed automatically by the * Connection. I can't think of a way of asserting this but you should * see a line in the log saying it was closed. */ public void testCloseStatement() throws Exception { String testName = "closeStatement"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection c = DriverManager.getConnection(url); Statement s = c.createStatement(); try { s.execute("drop table foo"); } catch (SQLException e) { // Expected exception (foo doesn't exist) LOG.debug("Ignoring excepted exception", e); } finally { // this should trigger an automatic close of the statement. // Unfortunately, I can't find a way of asserting that this // really happens. Hypersonic seems to let me continue // to use all the methods on the Statement despite it being // closed. c.close(); } c = DriverManager.getConnection(url); Statement s2 = c.createStatement(); try { s2.execute("drop table foo"); } catch (SQLException e) { // Expected exception (foo doesn't exist) LOG.debug("Excepted exception", e); } finally { if (s2 != null) { s2.close(); } // this should NOT trigger an automatic close of the statement // because it's been closed explicitly above c.close(); } } } /* Revision history: $Log: ProxyConnectionTest.java,v $ Revision 1.6 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:09:04 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ProxyDatabaseMetaDataTest.java0000644000175000017500000000521210730503130033325 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.util.Properties; /** * Test whether ProxyDatabaseMetaData works * * @version $Revision: 1.6 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ProxyDatabaseMetaDataTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ProxyDatabaseMetaDataTest.class); public ProxyDatabaseMetaDataTest(String alias) { super(alias); } /** * Test whether we can get the Proxool connection back from the * DatabaseMetaData object (rather than the delegate connection) */ public void testGetConnection() throws Exception { String testName = "getConnection"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); Connection connection = DriverManager.getConnection(url); DatabaseMetaData dmd = connection.getMetaData(); Connection retrievedConnection = dmd.getConnection(); assertEquals("Retrieved connection not the same", connection, retrievedConnection); assertEquals("Retrieved connection not the same", connection.getClass(), retrievedConnection.getClass()); connection.close(); } } /* Revision history: $Log: ProxyDatabaseMetaDataTest.java,v $ Revision 1.6 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:09:05 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ProxyStatementTest.java0000644000175000017500000002164710730503130032176 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.Statement; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Test whether ProxyStatement works * * @version $Revision: 1.13 $, $Date: 2006/03/03 09:58:26 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class ProxyStatementTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(ProxyStatementTest.class); public ProxyStatementTest(String alias) { super(alias); } /** * That we can get the delegate driver's Statement from the one given by Proxool */ public void testDelegateStatement() throws Exception { String testName = "delegateStatement"; // Register pool String url = registerPool(testName); // get a connection from the pool and create a statement with it Connection c = DriverManager.getConnection(url); Statement s = c.createStatement(); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); Class delegateStatementClass = delegateStatement.getClass(); s.close(); LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatementClass); // get a *real* connection directly from the native driver (bypassing the pool) Connection realConnection = TestHelper.getDirectConnection(); Statement realStatement = realConnection.createStatement(); Class realStatementClass = realStatement.getClass(); realStatement.close(); realConnection.close(); // are they of the same type ? assertEquals("Delegate statement isn't of the expected type.", realStatementClass, delegateStatementClass); } /** * Test what interfaces are supported when getting a PreparedStatement */ public void testPreparedStatement() throws Exception { String testName = "preparedStatement"; // Register pool String url = registerPool(testName); // get a connection from the pool and create a prepare statement with it Connection c = DriverManager.getConnection(url); PreparedStatement s = c.prepareStatement(TestConstants.HYPERSONIC_TEST_SQL); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); Class delegateStatementClass = delegateStatement.getClass(); s.close(); c.close(); LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatementClass); // get a *real* connection directly from the native driver (bypassing the pool) Connection realConnection = TestHelper.getDirectConnection(); Statement realStatement = realConnection.prepareStatement(TestConstants.HYPERSONIC_TEST_SQL); Class realStatementClass = realStatement.getClass(); realStatement.close(); realConnection.close(); // are they of the same type ? assertEquals("Delegate statement isn't of the expected type.", realStatementClass, delegateStatementClass); } /** * Test what interfaces are supported when getting a CallableStatement */ public void testCallableStatement() throws Exception { String testName = "callableStatement"; // Register pool String url = registerPool(testName); // get a connection from the pool and create a callable statement with it Connection c = DriverManager.getConnection(url); CallableStatement s = c.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); Statement delegateStatement = ProxoolFacade.getDelegateStatement(s); Class delegateStatementClass = delegateStatement.getClass(); s.close(); LOG.debug("Statement " + s.getClass() + " is delegating to " + delegateStatementClass); // get a *real* connection directly from the native driver (bypassing the pool) Connection realConnection = TestHelper.getDirectConnection(); Statement realStatement = realConnection.prepareCall(TestConstants.HYPERSONIC_TEST_SQL); Class realStatementClass = realStatement.getClass(); realStatement.close(); realConnection.close(); // are they of the same type ? assertEquals("Delegate statement isn't of the expected type.", realStatementClass, delegateStatementClass ); } /** * That we can get the delegate driver's Connection from the one given by Proxool */ public void testDelegateConnection() throws Exception { String testName = "delegateConnection"; // Register pool String url = registerPool(testName); // get a connection from the pool Connection c = DriverManager.getConnection(url); Connection delegateConnection = ProxoolFacade.getDelegateConnection(c); Class delegateConnectionClass = delegateConnection.getClass(); LOG.debug("Connection " + c + " is delegating to " + delegateConnectionClass); c.close(); // get a *real* connection directly from the native driver (bypassing the pool) Connection realConnection = TestHelper.getDirectConnection(); Class realConnectionClass = realConnection.getClass(); realConnection.close(); assertEquals("Connection isn't of the expected.", realConnectionClass, delegateConnectionClass); } /** * * @param alias * @throws Exception */ private String registerPool(String alias) throws Exception { String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); return url; } public void testCloseByStatement() throws Exception { String testName = "snapshot"; final String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); // get a connection from the pool and create a statement with it Connection c = DriverManager.getConnection(url); Statement s = c.createStatement(); // Even if we ask the statement to close it it should still work. s.getConnection().close(); assertEquals("servedCount", 0, ProxoolFacade.getSnapshot(alias).getActiveConnectionCount()); } } /* Revision history: $Log: ProxyStatementTest.java,v $ Revision 1.13 2006/03/03 09:58:26 billhorsman Fix for statement.getConnection(). See bug 1149834. Revision 1.12 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2004/07/13 21:32:41 billhorsman Close the first connection first before opening the real connection (directly) otherwise you get a "database already in use"error on Windows. Revision 1.10 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.9 2004/03/23 21:17:23 billhorsman added preparedStatement and callableStatement tests Revision 1.8 2003/12/09 18:52:19 billhorsman checkstyle Revision 1.7 2003/11/05 00:00:52 billhorsman Remove redundant test (already in FatalSqlExceptionTest) Revision 1.6 2003/08/27 18:03:20 billhorsman added new getDelegateConnection() method Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:09:05 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/RegistrationTest.java0000644000175000017500000001360510730503130031635 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * Test whether we can register and remove a pool in various ways * * @version $Revision: 1.7 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class RegistrationTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(RegistrationTest.class); public RegistrationTest(String alias) { super(alias); } /** * Test whether we can implicitly register a pool by */ public void testRegister() throws Exception { String testName = "register"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); assertNotNull("snapshot exists", ProxoolFacade.getSnapshot(alias)); // TODO check that properties are configured properly } /** * Can we register, remove and then re-register the same pool? */ public void testRemove() throws Exception { String testName = "remove"; String alias = testName; // Register String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url, info); try { DriverManager.getConnection(url).close(); } catch (SQLException e) { fail("Couldn't get connection"); } // Remove using alias ProxoolFacade.removeConnectionPool(alias); try { ProxoolFacade.getConnectionPoolDefinition(alias); fail("Didn't expect to get definition of pool that was just removed"); } catch (ProxoolException e) { LOG.debug("Ignore expected exception", e); } // Register again ProxoolFacade.registerConnectionPool(url, info); try { DriverManager.getConnection(url).close(); } catch (SQLException e) { fail("Couldn't get connection"); } // Should only be one served (the earlier one is forgotten) assertEquals("servedCount", 1L, ProxoolFacade.getSnapshot(alias).getServedCount()); // Remove using alias ProxoolFacade.removeConnectionPool(alias); try { ProxoolFacade.getConnectionPoolDefinition(alias); fail("Didn't expect to get definition of pool that was just removed"); } catch (ProxoolException e) { LOG.debug("Ignore expected exception", e); } // Register again ProxoolFacade.registerConnectionPool(url, info); try { DriverManager.getConnection(url).close(); } catch (SQLException e) { fail("Couldn't get connection"); } // Should only be one served (the earlier one is forgotten) assertEquals("servedCount", 1L, ProxoolFacade.getSnapshot(alias).getServedCount()); } /** * Can we have multiple pools? */ public void testMultiple() throws Exception, ClassNotFoundException { String testName = "multiple"; String alias1 = testName + "1"; String alias2 = testName + "2"; // Register String url1 = TestHelper.buildProxoolUrl(alias1, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); String url2 = TestHelper.buildProxoolUrl(alias2, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); ProxoolFacade.registerConnectionPool(url1, info); ProxoolFacade.registerConnectionPool(url2, info); // Open 2 connections on #1 DriverManager.getConnection(url1).close(); DriverManager.getConnection(url1).close(); // Open 1 connection on #2 DriverManager.getConnection(url2).close(); assertEquals("connectionsServedCount #1", 2L, ProxoolFacade.getSnapshot(alias1).getServedCount()); assertEquals("connectionsServedCount #2", 1L, ProxoolFacade.getSnapshot(alias2).getServedCount()); } } /* Revision history: $Log: RegistrationTest.java,v $ Revision 1.7 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.6 2003/03/04 10:58:44 billhorsman checkstyle Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:09:06 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/ResultMonitor.java0000644000175000017500000000702110730503130031144 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Waits for a set of results to become true with timeout * functionality * * @version $Revision: 1.10 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public abstract class ResultMonitor { private static final Log LOG = LogFactory.getLog(ResultMonitor.class); /** * This monitor is still waiting for the result to come true */ public static final int WAITING = 0; /** * The result has happened */ public static final int SUCCESS = 1; /** * There was a timeout waiting for the result to happen * @see #setTimeout */ public static final int TIMEOUT = 3; /** * Seems awfully long, but it seems to need it. Sometimes. */ private long timeout = 60000; private int result = WAITING; private int delay = 500; /** * Override this with your specific check * @return true if the result has happened, else false * @throws Exception if anything goes wrong */ public abstract boolean check() throws Exception; /** * Wait for the result to happen, or for a timeout * @return {@link #SUCCESS} or {@link #TIMEOUT} * @throws ProxoolException if the {@link #check} threw an exception * @see #setTimeout */ public int getResult() throws ProxoolException { try { long startTime = System.currentTimeMillis(); if (check()) { result = SUCCESS; } while (true) { if (System.currentTimeMillis() - startTime > timeout) { result = TIMEOUT; LOG.debug("Timeout"); break; } try { Thread.sleep(delay); } catch (InterruptedException e) { LOG.error("Awoken", e); } if (check()) { result = SUCCESS; LOG.debug("Success"); break; } } return result; } catch (Exception e) { throw new ProxoolException("Problem monitoring result", e); } } /** * Set the timeout * @param timeout milliseconds */ public void setTimeout(long timeout) { this.timeout = timeout; } public void setDelay(int delay) { this.delay = delay; } } /* Revision history: $Log: ResultMonitor.java,v $ Revision 1.10 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.9 2003/03/05 18:44:10 billhorsman fix delay and timeout Revision 1.8 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.7 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.6 2003/03/02 00:53:38 billhorsman increased timeout to 60 sec! Revision 1.5 2003/03/01 18:17:51 billhorsman arrffgh. fix, Revision 1.4 2003/03/01 16:54:20 billhorsman fix Revision 1.3 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.2 2003/03/01 15:22:50 billhorsman doc Revision 1.1 2003/03/01 15:14:15 billhorsman new ResultMonitor to help cope with test threads */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/SimpoolAdapter.java0000644000175000017500000000667010730503130031252 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.logicalcobwebs.dbscript.ConnectionAdapterIF; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * This is the simplest pool you can get. It isn\ufffdt thread safe. It isn't robust. * But it is fast. We use it as our bench mark on how could we should strive * to be. * * Provides Simpool connections to the {@link org.logicalcobwebs.dbscript.ScriptFacade ScriptFacade} * * @version $Revision: 1.12 $, $Date: 2006/01/18 14:40:06 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class SimpoolAdapter implements ConnectionAdapterIF { private static final Log LOG = LogFactory.getLog(SimpoolAdapter.class); private Connection[] connections; private int index = 0; public String getName() { return "simpool"; } public void setup(String driver, String url, Properties info) throws SQLException { try { Class.forName(driver); } catch (ClassNotFoundException e) { throw new SQLException("Couldn't find " + driver); } int connectionCount = Integer.parseInt(info.getProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY)); connections = new Connection[connectionCount]; for (int i = 0; i < connectionCount; i++) { connections[i] = DriverManager.getConnection(url, info); } } public Connection getConnection() throws SQLException { Connection c = connections[index]; index++; if (index >= connections.length) { index = 0; } return c; } public void closeConnection(Connection connection) { // Do nothing ! } public void tearDown() { try { for (int i = 0; i < connections.length; i++) { connections[i].close(); } } catch (SQLException e) { LOG.error("Problem tearing down " + getName() + " adapter", e); } } } /* Revision history: $Log: SimpoolAdapter.java,v $ Revision 1.12 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.11 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.10 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.9 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.8 2003/02/19 15:14:25 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.7 2003/02/06 17:41:03 billhorsman now uses imported logging Revision 1.6 2003/01/27 23:32:10 billhorsman encoding fix (no idea how that happened) Revision 1.5 2002/11/13 20:23:38 billhorsman change method name, throw exceptions differently, trivial changes Revision 1.4 2002/11/09 16:02:20 billhorsman fix doc Revision 1.3 2002/11/02 14:22:16 billhorsman Documentation Revision 1.2 2002/11/02 12:46:42 billhorsman improved debug Revision 1.1 2002/11/02 11:37:48 billhorsman New tests Revision 1.1 2002/10/30 21:17:50 billhorsman new performance tests */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/StateListenerTest.java0000644000175000017500000001642210730503130031751 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * Test that registering a {@link ConfigurationListenerIF} with the {@link ProxoolFacade} * works. * * @version $Revision: 1.14 $, $Date: 2006/01/18 14:40:06 $ * @author Christian Nedregaard (christian_nedregaard@email.com) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.7 */ public class StateListenerTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(StateListenerTest.class); /** * @see junit.framework.TestCase#TestCase */ public StateListenerTest(String s) { super(s); } /** * Test whether we can add a state listener and that it receives * notification of change of state */ public void testAddStateListener() throws Exception { String testName = "addStateListener"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "1"); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "0"); info.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "1000"); info.setProperty(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY, "6000"); ProxoolFacade.registerConnectionPool(url, info); assertEquals("maximumConnectionCount", 1, ProxoolFacade.getConnectionPoolDefinition(alias).getMaximumConnectionCount()); StateResultMonitor srm = new StateResultMonitor(); ProxoolFacade.addStateListener(alias, srm); assertEquals("maximumConnectionCount", 1, ProxoolFacade.getConnectionPoolDefinition(alias).getMaximumConnectionCount()); Connection c1 = DriverManager.getConnection(url); // Test BUSY srm.setExpectedUpState(StateListenerIF.STATE_BUSY); assertEquals("Timeout waiting for BUSY", ResultMonitor.SUCCESS, srm.getResult()); assertEquals("maximumConnectionCount", 1, ProxoolFacade.getConnectionPoolDefinition(alias).getMaximumConnectionCount()); try { Connection c2 = DriverManager.getConnection(url); fail("Didn't expect second connection since maximumConnectionCount is 1"); } catch (SQLException e) { // We expect a refusal here // Log message only so we don't get a worrying stack trace LOG.debug("Ignoring expected refusal: " + e.getMessage()); } // Test Overloaded srm.setExpectedUpState(StateListenerIF.STATE_OVERLOADED); assertEquals("Timeout waiting for OVERLOADED", ResultMonitor.SUCCESS, srm.getResult()); // Test Busy again srm.setExpectedUpState(StateListenerIF.STATE_BUSY); assertEquals("Timeout waiting for BUSY", ResultMonitor.SUCCESS, srm.getResult()); // Test Quiet again c1.close(); srm.setExpectedUpState(StateListenerIF.STATE_QUIET); assertEquals("Timeout waiting for QUIET", ResultMonitor.SUCCESS, srm.getResult()); // Bogus definition -> should be down try { ProxoolFacade.updateConnectionPool("proxool." + alias + ":blah:foo", null); } catch (ProxoolException e) { LOG.debug("Ignoring expected exception when trying to register a pool with a bogus driver", e); } srm.setExpectedUpState(StateListenerIF.STATE_DOWN); assertEquals("Timeout waiting for DOWN", ResultMonitor.SUCCESS, srm.getResult()); } class TestStateListener implements StateListenerIF { private boolean somethingHappened; private int upState; public void upStateChanged(int newUpState) { LOG.debug("upState: " + upState + " -> " + newUpState); upState = newUpState; somethingHappened = true; } boolean isSomethingHappened() { return somethingHappened; } int getUpState() { return upState; } void reset() { upState = 0; somethingHappened = false; } void waitForSomethingToHappen(int stateToWaitFor) { long start = System.currentTimeMillis(); while (!somethingHappened) { if (upState == stateToWaitFor) { if (!somethingHappened) { LOG.error("Waiting for state = " + stateToWaitFor + " but it's already at that state"); break; } } try { Thread.sleep(500); } catch (InterruptedException e) { LOG.error("Awoken", e); } if (System.currentTimeMillis() - start > 30000) { fail("Timeout waiting for something to happen"); } } } int zgetNextState(int stateToWaitFor) { waitForSomethingToHappen(stateToWaitFor); somethingHappened = false; return upState; } } } /* Revision history: $Log: StateListenerTest.java,v $ Revision 1.14 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.13 2005/05/04 16:03:23 billhorsman Now catches ProxoolException when pool is updated with bogus driver. Revision 1.12 2004/06/02 21:05:19 billhorsman Don't log worrying stack traces for expected exceptions. Revision 1.11 2003/03/04 10:58:44 billhorsman checkstyle Revision 1.10 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.9 2003/03/03 17:09:06 billhorsman all tests now extend AbstractProxoolTest Revision 1.8 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.7 2003/03/02 00:37:23 billhorsman more robust Revision 1.6 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.5 2003/03/01 15:24:09 billhorsman tweaked properties Revision 1.4 2003/02/28 17:41:13 billhorsman more robust wait for state change Revision 1.3 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.2 2003/02/26 16:05:50 billhorsman widespread changes caused by refactoring the way we update and redefine pool definitions. Revision 1.1 2003/02/19 23:07:57 billhorsman new test Revision 1.2 2003/02/19 15:14:22 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2003/02/19 13:47:31 chr32 Added configuration listener test. Revision 1.2 2003/02/18 16:58:12 chr32 Checkstyle. Revision 1.1 2003/02/18 16:51:20 chr32 Added tests for ConnectionListeners. */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/StateResultMonitor.java0000644000175000017500000000403210730503131032145 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * A ResultMonitor specifically for State * * @version $Revision: 1.4 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class StateResultMonitor extends ResultMonitor implements StateListenerIF { private static final Log LOG = LogFactory.getLog(StateResultMonitor.class); private int upState; private int expectedUpState; /** * waits for statistics * @return {@link #SUCCESS} or {@link #TIMEOUT} * @throws Exception if anything goes wrong */ public boolean check() throws Exception { return (upState == expectedUpState); } public void upStateChanged(int upState) { this.upState = upState; } public void setExpectedUpState(int expectedUpState) { this.expectedUpState = expectedUpState; } } /* Revision history: $Log: StateResultMonitor.java,v $ Revision 1.4 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.3 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.2 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.1 2003/03/02 00:37:23 billhorsman more robust Revision 1.5 2003/03/01 18:17:50 billhorsman arrffgh. fix, Revision 1.4 2003/03/01 16:53:07 billhorsman fix Revision 1.3 2003/03/01 16:38:40 billhorsman fix Revision 1.2 2003/03/01 16:18:31 billhorsman fix Revision 1.1 2003/03/01 16:07:26 billhorsman helper Revision 1.3 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.2 2003/03/01 15:22:50 billhorsman doc Revision 1.1 2003/03/01 15:14:14 billhorsman new ResultMonitor to help cope with test threads */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/TestConstants.java0000644000175000017500000000603510730503131031137 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; /** * Some useful constants for testing. * * Note: these values will be overriden at startup by the GlobalTest init procedure. * * @version $Revision: 1.8 $, $Date: 2006/03/24 00:19:10 $ * @author Bill Horsman (bill@logicalcobwebs.co.uk) * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.5 */ public class TestConstants { /** * Proxool Driver class */ public static String PROXOOL_DRIVER = "org.logicalcobwebs.proxool.ProxoolDriver"; /** * JDBC driver class */ public static String HYPERSONIC_DRIVER = "org.hsqldb.jdbcDriver"; /** * URL connection base (without database) */ public static String HYPERSONIC_URL_PREFIX = "jdbc:hsqldb:db/"; /** * URL to a first test database. User should have rw access */ public static String HYPERSONIC_TEST_URL = HYPERSONIC_URL_PREFIX + "test"; /** * URL to a second test database */ public static String HYPERSONIC_TEST_URL2 = HYPERSONIC_URL_PREFIX + "2"; /** * Connection credentials */ public static String HYPERSONIC_USER = "sa"; /** * Connection credentials */ public static String HYPERSONIC_PASSWORD = ""; /** * SQL statement that should always succeed */ public static String HYPERSONIC_TEST_SQL = "SELECT COUNT(1) FROM INFORMATION_SCHEMA.SYSTEM_TABLES"; /** * SQL statement that should always succeed */ public static String HYPERSONIC_TEST_SQL_2 = "SELECT COUNT(2) FROM INFORMATION_SCHEMA.SYSTEM_TABLES"; /** * SQL statement that should always fail */ public static String FATAL_SQL_STATEMENT = "drop table Z"; /** * SQLException message fragment used to detect fatal exceptions */ public static String FATAL_SQL_EXCEPTION = "Table not found"; } /* Revision history: $Log: TestConstants.java,v $ Revision 1.8 2006/03/24 00:19:10 billhorsman Changes for HSQL 1.8 Revision 1.7 2005/10/07 08:10:33 billhorsman Second test SQL Revision 1.6 2004/05/26 17:19:09 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.5 2003/09/30 18:39:39 billhorsman New test sql syntax constant Revision 1.4 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.3 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. Revision 1.2 2003/02/19 15:14:26 billhorsman fixed copyright (copy and paste error, not copyright change) Revision 1.1 2002/11/13 20:23:58 billhorsman improved tests */ libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/TestHelper.java0000644000175000017500000001715310730503130030404 0ustar twernertwernerpackage org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * Helper for all tests * * @version $Revision: 1.23 $, $Date: 2007/06/19 11:33:35 $ * @author bill * @author $Author: billhorsman $ (current maintainer) */ public class TestHelper { private static final Log LOG = LogFactory.getLog(TestHelper.class); /** * Builds a complete set of proxool properties, with all values set to * something different than the default vaule. * @return the properties that was buildt. */ public static Properties buildCompleteAlternativeProperties() { Properties properties = new Properties(); properties.setProperty("user", "sa"); properties.setProperty("password", ""); properties.setProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME_PROPERTY, "40000"); properties.setProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL_PROPERTY, TestConstants.HYPERSONIC_TEST_SQL); properties.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "10"); properties.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "3"); properties.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME_PROPERTY, "18000000"); properties.setProperty(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE_PROPERTY, "5"); properties.setProperty(ProxoolConstants.RECENTLY_STARTED_THRESHOLD_PROPERTY, "40000"); properties.setProperty(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME_PROPERTY, "50000"); properties.setProperty(ProxoolConstants.MAXIMUM_ACTIVE_TIME_PROPERTY, "60000"); properties.setProperty(ProxoolConstants.VERBOSE_PROPERTY, "true"); properties.setProperty(ProxoolConstants.TRACE_PROPERTY, "true"); properties.setProperty(ProxoolConstants.FATAL_SQL_EXCEPTION_PROPERTY, "Fatal error"); properties.setProperty(ProxoolConstants.PROTOTYPE_COUNT_PROPERTY, "2"); return properties; } /** * Test that the given ConnectionPoolDefinitionIF contains all the properties as defined in * {@link #buildCompleteAlternativeProperties}. * @param connectionPoolDefinition the ConnectionPoolDefinitionIF to be tested. * @throws ProxoolException if any properties are missing or have the wrong value. */ public static void equalsCompleteAlternativeProperties(ConnectionPoolDefinitionIF connectionPoolDefinition) throws ProxoolException { checkProperty("user", "sa", connectionPoolDefinition.getDelegateProperties().getProperty("user")); checkProperty("password", "", connectionPoolDefinition.getDelegateProperties().getProperty("password")); checkProperty(ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME, 40000, connectionPoolDefinition.getHouseKeepingSleepTime()); checkProperty(ProxoolConstants.HOUSE_KEEPING_TEST_SQL, "select CURRENT_DATE", connectionPoolDefinition.getHouseKeepingTestSql()); checkProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, 10, connectionPoolDefinition.getMaximumConnectionCount()); checkProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT, 3, connectionPoolDefinition.getMinimumConnectionCount()); checkProperty(ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME, 18000000, connectionPoolDefinition.getMaximumConnectionLifetime()); checkProperty(ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE, 5, connectionPoolDefinition.getSimultaneousBuildThrottle()); checkProperty(ProxoolConstants.RECENTLY_STARTED_THRESHOLD, 40000, connectionPoolDefinition.getRecentlyStartedThreshold()); checkProperty(ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME, 50000, connectionPoolDefinition.getOverloadWithoutRefusalLifetime()); checkProperty(ProxoolConstants.MAXIMUM_ACTIVE_TIME, 60000, connectionPoolDefinition.getMaximumActiveTime()); checkProperty(ProxoolConstants.VERBOSE, "true", new Boolean(connectionPoolDefinition.isVerbose()).toString()); checkProperty(ProxoolConstants.TRACE, "true", new Boolean(connectionPoolDefinition.isTrace() == true).toString()); checkProperty(ProxoolConstants.FATAL_SQL_EXCEPTION, "Fatal error", connectionPoolDefinition.getFatalSqlExceptions().iterator().next().toString()); checkProperty(ProxoolConstants.PROTOTYPE_COUNT, 2, connectionPoolDefinition.getPrototypeCount()); } private static void checkProperty(String name, String correctValue, String candidateValue) throws ProxoolException { if (candidateValue == null) { throw new ProxoolException(name + " was null."); } else if (!candidateValue.equals(correctValue)) { throw new ProxoolException("Expected value for " + name + " was " + correctValue + " but the value was " + candidateValue + "."); } } private static void checkProperty(String name, int correctValue, int candidateValue) throws ProxoolException { checkProperty(name, String.valueOf(correctValue), String.valueOf(candidateValue)); } private static void checkProperty(String name, long correctValue, long candidateValue) throws ProxoolException { checkProperty(name, String.valueOf(correctValue), String.valueOf(candidateValue)); } /** * Build a valid Proxool URL * @param alias identifies the pool * @param driver the delegate driver * @param delegateUrl the url to send to the delegate driver * @return proxool.alias:driver:delegateUrl */ public static String buildProxoolUrl(String alias, String driver, String delegateUrl) { String url = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER + alias + ProxoolConstants.URL_DELIMITER + driver + ProxoolConstants.URL_DELIMITER + delegateUrl; return url; } /** * Build a valid Proxool URL * @param alias identifies the pool * @return proxool.alias */ public static String buildProxoolUrl(String alias) { String url = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER + alias; return url; } public static Connection getDirectConnection() throws ClassNotFoundException, SQLException { Connection connection = null; Class.forName(TestConstants.HYPERSONIC_DRIVER); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); connection = DriverManager.getConnection(TestConstants.HYPERSONIC_TEST_URL, info); return connection; } } /* Revision history: $Log: TestHelper.java,v $ Revision 1.23 2007/06/19 11:33:35 billhorsman Changed time (millisecond) properties from int to long: maximumConnectionLifetime, houseKeepingSleepTime, recentlyStartedThreshold, overloadWithoutRefusalLifetime, maximumActiveTime Revision 1.22 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.21 2003/09/30 18:39:50 billhorsman New test sql syntax constant Revision 1.20 2003/03/05 23:28:55 billhorsman deprecated maximum-new-connections property in favour of more descriptive simultaneous-build-throttle Revision 1.19 2003/03/04 10:58:44 billhorsman checkstyle */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/UpdateDefinitionTest.java0000644000175000017500000002132710730503130032416 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.DriverManager; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; /** * Test that we can update the definition of a pool * * @version $Revision: 1.9 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.8 */ public class UpdateDefinitionTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(UpdateDefinitionTest.class); public UpdateDefinitionTest(String alias) { super(alias); } /** * Can we change the delegate URL of a pool */ public void testChangeUrl() throws Exception { String testName = "changeUrl"; String alias = testName; String url1 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); String url2 = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL2); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, "2"); // register pool ProxoolFacade.registerConnectionPool(url1, info); // Get one connection DriverManager.getConnection(url1).close(); assertEquals("connectionsServedCount", 1L, ProxoolFacade.getSnapshot(alias, false).getServedCount()); ProxoolFacade.updateConnectionPool(url2, null); // Get another connection DriverManager.getConnection(url2).close(); assertEquals("connectionsServedCount", 2L, ProxoolFacade.getSnapshot(alias, false).getServedCount()); ProxoolFacade.updateConnectionPool(url1, null); DriverManager.getConnection(url1).close(); assertEquals("connectionsServedCount", 3L, ProxoolFacade.getSnapshot(alias, false).getServedCount()); } /** * Can we update a pool definition by passing a new Properties object? */ public void testUpdate() throws Exception, ClassNotFoundException { String testName = "update"; String alias = testName; String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "1"); ProxoolFacade.registerConnectionPool(url, info); // Open a connection. Just for the hell of it DriverManager.getConnection(url).close(); assertEquals("maximumConnectionCount", 1, ProxoolFacade.getConnectionPoolDefinition(alias).getMaximumConnectionCount()); // Update using facade info = new Properties(); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "2"); ProxoolFacade.updateConnectionPool(url, info); assertEquals("maximumConnectionCount", 2, ProxoolFacade.getConnectionPoolDefinition(alias).getMaximumConnectionCount()); // Now do it on the fly (this is a redefine really) info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "3"); DriverManager.getConnection(url, info).close(); assertEquals("maximumConnectionCount", 3, ProxoolFacade.getConnectionPoolDefinition(alias).getMaximumConnectionCount()); } /** * If we request a connection using exactly the same URL and properties check that it doesn't trigger an update * which forces the pool to be restarted (all existing connections destroyed). */ public void testDefinitionNotChanging() throws SQLException, ProxoolException { String testName = "definitionNotChanging"; String alias = testName; Connection c1 = null; try { String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "1"); c1 = DriverManager.getConnection(url, info); assertEquals("id=1", 1L, ProxoolFacade.getId(c1)); } finally { c1.close(); } // The second attempt (using the same definition) should give back the same connection ID Connection c2 = null; try { String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, "1"); c2 = DriverManager.getConnection(url, info); assertEquals("id=1", 1L, ProxoolFacade.getId(c2)); } finally { c2.close(); } // Not the same object. It's wrapped. assertNotSame("c1!=c2", c1, c2); } /** * Can we update a pool definition by calling updateConnectionPool? */ public void testUpdateUsingAPI() throws Exception, ClassNotFoundException { String testName = "updateUsingAPI"; String alias = testName; String url = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER + alias + ProxoolConstants.URL_DELIMITER + TestConstants.HYPERSONIC_DRIVER + ProxoolConstants.URL_DELIMITER + TestConstants.HYPERSONIC_TEST_URL2; //"jdbc:hsqldb:db/update"; LOG.debug("Register pool"); Properties info = new Properties(); String checkAlias = ProxoolFacade.registerConnectionPool(url, info); assertEquals(alias, checkAlias); LOG.debug("setConfigurationListener"); ProxoolFacade.addConfigurationListener(alias, new ConfigurationListenerIF() { public void definitionUpdated(ConnectionPoolDefinitionIF connectionPoolDefinition, Properties completeInfo, Properties changedInfo) { } }); LOG.debug("setStateListener"); ProxoolFacade.addStateListener(alias, new StateListenerIF() { public void upStateChanged(int upState) { } }); LOG.debug("Update pool"); ProxoolFacade.updateConnectionPool(url, info); } } /* Revision history: $Log: UpdateDefinitionTest.java,v $ Revision 1.9 2006/01/18 14:40:06 billhorsman Unbundled Jakarta's Commons Logging. Revision 1.8 2005/09/25 21:48:09 billhorsman New test to check that asking for a connection using the same URL and properties doesn't redefine the pool. Revision 1.7 2004/05/26 17:19:10 brenuart Allow JUnit tests to be executed against another database. By default the test configuration will be taken from the 'testconfig-hsqldb.properties' file located in the org.logicalcobwebs.proxool package. This behavior can be overriden by setting the 'testConfig' environment property to another location. Revision 1.6 2003/03/04 12:50:44 billhorsman fix Revision 1.5 2003/03/04 10:24:40 billhorsman removed try blocks around each test Revision 1.4 2003/03/03 17:09:07 billhorsman all tests now extend AbstractProxoolTest Revision 1.3 2003/03/03 11:12:05 billhorsman fixed licence Revision 1.2 2003/03/01 15:27:24 billhorsman checkstyle Revision 1.1 2003/02/27 18:01:48 billhorsman completely rethought the test structure. it's now more obvious. no new tests yet though. */libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/WrapperTest.java0000644000175000017500000002550410730503130030604 0ustar twernertwerner/* * This software is released under a licence similar to the Apache Software Licence. * See org.logicalcobwebs.proxool.package.html for details. * The latest version is available at http://proxool.sourceforge.net */ package org.logicalcobwebs.proxool; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.SQLException; import java.util.Properties; /** * Tests whether we are wrapping up connections correctly. There disposable * wrappers stop the user doing nasty things to the connection after it has * been closed. * @version $Revision: 1.4 $, $Date: 2006/01/18 14:40:06 $ * @author bill * @author $Author: billhorsman $ (current maintainer) * @since Proxool 0.9 */ public class WrapperTest extends AbstractProxoolTest { private static final Log LOG = LogFactory.getLog(WrapperTest.class); /** * @see AbstractProxoolTest */ public WrapperTest(String alias) { super(alias); } /** * Check that closing a connection twice can't close the same connection for the * next user */ public void testDoubleConnection() throws Exception { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); Connection c1 = DriverManager.getConnection(url, info); Connection dc1 = ProxoolFacade.getDelegateConnection(c1); c1.close(); assertEquals("servedCount", 1, ProxoolFacade.getSnapshot(alias).getServedCount()); LOG.debug("c1 = " + c1.toString() + ", dc1 = " + dc1); Connection c2 = DriverManager.getConnection(url, info); Connection dc2 = ProxoolFacade.getDelegateConnection(c2); LOG.debug("c2 = " + c2 + ", dc2 = " + dc2); assertEquals("Expected the delegate connection to be the same", dc1, dc2); // Closing the first connection should not fail, but it shouldn't do anything either. c1.close(); // Check that the second connection hasn't been effected assertTrue("Connection was closed unexpectedly", !c2.isClosed()); // Trying to use the first connection should fail Statement s = null; try { s = c1.createStatement(); s.execute(TestConstants.HYPERSONIC_TEST_SQL); fail("Expected to get an exception because the test failed"); } catch (SQLException e) { LOG.debug("Expected exception.", e); } // The second connection should work okay though try { s = c2.createStatement(); s.execute(TestConstants.HYPERSONIC_TEST_SQL); } catch (SQLException e) { fail("Connection failed, but it should have worked"); } c2.close(); assertTrue("Connection was not closed", c2.isClosed()); } /** * Check that nothing bad happens if you close a connection twice * @throws SQLException if anything goes wrong * @throws ProxoolException if anything goes wrong */ public void testDoubleClose() throws SQLException, ProxoolException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); Connection c1 = DriverManager.getConnection(url, info); c1.close(); c1.close(); } /** * Check that calling createStatement after a connection has been closed * throws an exception * @throws SQLException if anything goes wrong * @throws ProxoolException if anything goes wrong */ public void testCreateStatementAfterClose() throws SQLException, ProxoolException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); Connection c1 = DriverManager.getConnection(url, info); c1.close(); try { c1.createStatement(); fail("Expected createStatement() to fail after connection was closed"); } catch (SQLException e) { // Ignore (we expected it) } } /** * Check that isClosed() returns true after we have closed a connection * @throws SQLException if anything goes wrong * @throws ProxoolException if anything goes wrong */ public void testIsClosedAfterClose() throws SQLException, ProxoolException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); Connection c1 = DriverManager.getConnection(url, info); c1.close(); assertTrue("isClosed()", c1.isClosed()); } /** * Check that isClosed() returns true after we have closed a connection * @throws SQLException if anything goes wrong * @throws ProxoolException if anything goes wrong */ public void testHashCode() throws SQLException, ProxoolException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); Connection c1 = DriverManager.getConnection(url, info); LOG.debug(c1 + " = " + c1.hashCode()); c1.close(); LOG.debug(c1 + " = " + c1.hashCode()); Connection c2 = DriverManager.getConnection(url, info); LOG.debug(c2 + " = " + c2.hashCode()); c2.close(); LOG.debug(c2 + " = " + c2.hashCode()); } /** * Check tha equals() works right * @throws SQLException if anything goes wrong * @throws ProxoolException if anything goes wrong */ public void testEquals() throws SQLException, ProxoolException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "1"); Connection c1 = DriverManager.getConnection(url, info); assertTrue("c1 == c1", c1.equals(c1)); c1.close(); assertTrue("c1 == c1", c1.equals(c1)); Connection c2 = DriverManager.getConnection(url, info); assertTrue("c1 == c2", c1.equals(c2)); c2.close(); assertTrue("c1 == c2", c1.equals(c2)); } /** * Check whether {@link ProxoolFacade#getId(java.sql.Connection)} returns * sensible values * @throws ProxoolException if anything goes wrong * @throws SQLException if anything goes wrong */ public void testId() throws ProxoolException, SQLException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT, "2"); Connection c1 = DriverManager.getConnection(url, info); assertEquals("c1.getId()", 1, ProxoolFacade.getId(c1)); Connection c2 = DriverManager.getConnection(url, info); assertEquals("c2.getId()", 2, ProxoolFacade.getId(c2)); c1.close(); assertEquals("c1.getId()", 1, ProxoolFacade.getId(c1)); c2.close(); assertEquals("c2.getId()", 2, ProxoolFacade.getId(c2)); } /** * Check whether {@link ProxoolFacade#getAlias(java.sql.Connection)} returns * sensible values * @throws ProxoolException if anything goes wrong * @throws SQLException if anything goes wrong */ public void testAlias() throws ProxoolException, SQLException { String testName = "alias"; String alias = testName; // Register pool String url = TestHelper.buildProxoolUrl(alias, TestConstants.HYPERSONIC_DRIVER, TestConstants.HYPERSONIC_TEST_URL); Properties info = new Properties(); info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); Connection c1 = DriverManager.getConnection(url, info); assertEquals("c1.getAlias()", alias, ProxoolFacade.getAlias(c1)); c1.close(); assertEquals("c1.getAlias()", alias, ProxoolFacade.getAlias(c1)); } } libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/applicationContext.xml0000644000175000017500000000644610730503130032057 0ustar twernertwerner false org.hibernate.dialect.HSQLDialect false true org.hibernate.hql.classic.ClassicQueryTranslatorFactory libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/hibernate.xml0000644000175000017500000000064710730503130030145 0ustar twernertwerner hibernateConfiguredConnection org.hsqldb.jdbcDriver jdbc:hsqldb:test libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/hypersonic.xml0000644000175000017500000000073510730503130030365 0ustar twernertwerner test org.hsqldb.jdbcDriver jdbc:hsqldb:test 3 libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/log4j-chainsaw-debug.xml0000644000175000017500000000072710730503130032101 0ustar twernertwerner libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/log4j-chainsaw.xml0000644000175000017500000000072610730503131031015 0ustar twernertwerner libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/log4j-file.xml0000644000175000017500000000131510730503131030132 0ustar twernertwerner libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/log4j-test.xml0000644000175000017500000000073610730503131030200 0ustar twernertwerner libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/performance.xml0000644000175000017500000000220510730503130030475 0ustar twernertwerner ]> libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/script.xml0000644000175000017500000000220410730503130027477 0ustar twernertwerner ]> libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/testconfig-hsqldb.properties0000644000175000017500000000056010730503131033213 0ustar twernertwernerHYPERSONIC_DRIVER = org.hsqldb.jdbcDriver HYPERSONIC_USER = sa HYPERSONIC_PASSWORD = HYPERSONIC_TEST_SQL = SELECT COUNT(1) FROM INFORMATION_SCHEMA.SYSTEM_TABLES HYPERSONIC_URL_PREFIX = jdbc:hsqldb:db/ HYPERSONIC_TEST_URL = jdbc:hsqldb:db/test HYPERSONIC_TEST_URL2 = jdbc:hsqldb:db/2 FATAL_SQL_STATEMENT = drop table Z FATAL_SQL_EXCEPTION = Table not found libproxool-java-0.9.1.orig/src/java-test/org/logicalcobwebs/proxool/thread.xml0000644000175000017500000000255310730503130027451 0ustar twernertwerner ]> libproxool-java-0.9.1.orig/BUILD.txt0000644000175000017500000000025210730503117017122 0ustar twernertwernerBuilding Proxool ------------- $Revision: 1.2 $ $Date: 2002/09/24 09:34:38 $ $Author: billhorsman $ Please refer to doc/build.html for instructions on building Proxool.libproxool-java-0.9.1.orig/CHANGES.txt0000644000175000017500000004745211053760610017352 0ustar twernertwernerChanges to Proxool ---------------- $Revision: 1.50 $ $Date: 2008/08/23 10:08:08 $ $Author: billhorsman $ 0.9.1 - Fixed bundling of Cglib in binary release. Cglib is "repackaged" using JarJar. 0.9.0 - Changed the warning message when a statement is closed which isn't known to be open. This can happen if you close a statement twice and the message now suggests that as a cause. - Changed the signature of the ConnectionListenerIF.onDeath() method to include a reasonCode defining exactly why the connection is about to die. This gives you the chance to decide whether to commit or rollback. See the onDeath() method for a list of possible codes. 0.9.0RC3 - New naming policy for Cglib stops conflicts with other Cglib instances that are running (even ones in different packages). Without using our own naming policy we end up with exceptions like: java.lang.LinkageError: duplicate class definition: $java/lang/Object$$FastClassByCGLIB$$3f697993 - Added ProxoolFacade.disableShutdownHook so that you can choose to explicitly shutdown Proxool programatically. This is useful because the order that the JVM calls shutdown hooks isn't easily controlled and you might want to shutdown Proxool *after* you've done some cleaning up yourself. Suggested by Alex Lemaire. - Fixed bug in ProxoolDataSource to add in maximum-active-time. Credit to Paolo Di Tommaso. - Fixed bug in AdminServlet where select HTML tag was not closed properly. Credit to Paolo Di Tommaso. 0.9.0RC2 - The Statement.getConnection() method now returns the wrapped connection rather than the delegate, aloowing you to close() it safely. - Repackaged Cglib 2.1_3 (including its own repackaged version of ASM). Cglib is now repackaged using JarJar (see the repackage-cglib Ant target in the source distribution). One of the goals of this upgrade is to get Proxool to work with JDK 1.6 - more testing is needed before we can know the status of that. (Note that you can't build Proxool from source with 1.6 yet because if unimplemented methods in DataSource). - You can now configure the DataSource with delegate properties. Use the delegateProperties property. 0.9.0RC1 (3 March 2006) - New DataSource implementation. This has been tested with Tomcat 5.5. DataSource configuration is so specific to the container that it is safer to only state where it has been tested. We have no reason to suspect that it would not work in other containers. - All connections are now wrapped in disposable wrappers. This means that once you have closed a connection (thereby returning it to the pool) you can no longer do anything to it that might influence its behaviour for the next client that picks it up. It also means that if a connection is closed automatically by Proxool then the client gets an exception if it tries to do anything other than call close() or isClosed(). - Connections, Statements, PreparedStatements, and CallableStatements now implement all the public intefaces that the delegate connection does. This means that you can, for instance, cast a Connection directly to the driver specific one. Or more precisely, any of the interfaces that the driver object implements. You can only cast your exception into an interface - concrete classes aren't supported at this time. - You can now inject interfaces for proxied objects that expose public methods that aren't declared in an interface. So if your vendor Connection, Statement, PreparedStatement or CallableStatement have any public methods that aren't declared in an interface (and therefore not exposed automatically) you can just write your own interface that declares the same signature. Even though the vendor object doesn't implement your interface directly, the proxied object will behave as if it does. - ProxoolFacade now has killConnection that accepts the Connection object itself, so you don't have to know the pool alias and connection ID. - ProxoolFacade now has getId() which will give you the ID for any connection. - ProxoolFacade now has getAlias() which will give you the pool alias for any connection. - ProxoolFacade now has a no-parameter overloaded version of shutdown() for ease of integration with the Spring Framework. - ProxoolDriver no longer logs all SQLExceptions. It's up to the client to log exceptions as it sees fit. (With some changes to the tests, this means that we no longer get any stack traces output during testing when we encounter *expected* errors). - AdminServlet has been updated. Nicer layout. Separate tabs for definition, snapshot and statistics. Uses a list box for aliases in case there are a lot. - When you ask for a detailed snapshot (see ProxoolFacade.getSnapshot()) then it only attempts to get one for 10 seconds before giving up. A detailed snapshot needs to get a lock on the pool concerned and if the pool is really busy that might take a while. Belt and braces really. - Fixes for when a connection that exceeds the maximum-active-time and then the connection encounters errors during removal. It ended up getting removed twice and that meant that the pool appeared to be smaller than it was. - If a connection is removed because it was active for too long the SQL that it was performing is logged (if "trace" is enabled). - If trace is enabled then the AdminServlet displays the SQL that each connection has performed (or is in process of performing). This is only overwritten when the connection is served the next time. - Jakarta's Commons Logging is now longer bundled with the source and is now a dependency. We had forked this component (at their version 1.02) to make it simpler for us to deploy but there are advantages, particular with respect to configuration, to just using the component direct from Jakarta. 0.8.3 - 14 December 2003 - Switched to Cglib 2.0 and ASM 1.4. Repackaged them both to org.logicalcobwebs.clgib and org.logicalcobwebs.asm respectively. This means that you no longer need to include cglib in your classpath. (Note: other projects may still require it - the repackaged version is just for use by Proxool). This removes our dependency on any version of Cglib or ASM and avoids any potential Jar conflicts. - Made house keeper connection test more robust - credit John Hume - Removed JDK 1.4 specific code in ShutdownHook 0.8.2 - 5 November 2003 - Fixed bug where delegate properties weren't being passed onto the delegate driver. If you weren't passing any properties other than username and password to the delegate driver then this didn't cause a problem anyway. (Note that Proxool properties were being recognised correctly.) Added a new unit test specifically for this problem. - Throw a friendlier exception if you try and add a statistics listener to a pool with no statistics - Statistics now creates write locks less often. This was causing a problem during heavy loads even though the process of collecting statistics itself was very fast. If you had statistics turned off (the default) then this wasn't a problem anyway. 0.8.1 - 27 October 2003 - NullPointerException that occured during SQL logging for certain methods of excecuting statements has been fixed. Also, logging is optimised to do less work if nothing is listening. (No ConnectionListeners registered and log level not equal to debug or trace is off). - Fixed typos in ShutdownHook. And now silently ignore IllegalStateException during removal of shutdownHook that occurs during JVM shut down. 0.8.0 - 26 October 2003 - We now use Cglib's proxy library. Together with dropping the use of Timer and only referencing ShutdownHooks at runtime we are now able to support JDKs 1.2, 1.3 and 1.4 out of the box (Without Ant applied patches, which were horrible). - Proxool is now available as a JMX component. - New getDelegateConnection() method on ProxoolFacade gives you access to the delegate (third party) driver if you really need it. This makes your project dependent on both Proxool (to a small extent) and your third party driver (to a bigger extent) so should be done only if necessary. - If ProxoolDriver gets garbage collected for any reason (outside our control) then we no longer shutdown the pool it relates to. - AdminServlet now displays times for maximum-conneciton-lifetime, house-keeping-sleep-time, and maximum-active-time properly regardless of your timezone. This was a display bug only and didn't effect the behaviour of the pool itself. - Connections that are about to be expired no longer bother to reset themselves (because they'll never be used again anyway). This was causing problems if the connection had connectivity problems to the database which then caused problems during the reset. - Added fatal-sql-exception-wrapper-class property. If a fatal exception is detected then it is wrapped up inside the exception defined by this property. This can make exception handling easier in frameworks like Struts. Two wrappers are provided (FataSQLException and FatalRuntimeException) but you can also define your own. - Added test-before-use and test-after-use properties. They will trigger a test of the connection (as defined by house-keeper-test-sql) just before a connection is handed out and just after it is closed (put back in the pool) respectively. These are both off by default. - Fixed ConcurrentModificationException that happened in some environments during automatic statement closure. - Fixed bug where if there was an Error during prototyping (not an SQLException, not a RuntimeException but something serious like NoClassDefFoundError) then the prototyper would keep attempting to make connections as fast as it could (and never succeed in making any). Much better for the prototyper to give up in that situation and try again when it is next asked (which, by default, would be 30 seconds later). - Fix to documentation. Defining more than one type of fatal SQL exception is done with a comma delimited list. - Fix to ProxoolFacade.redefine() which was in fact doing an update instead of a redefine. This didn't have any consequences unless you were calling this method explicitly in your code. - Made the 'Attempt to use a pool with incomplete definition' exception a bit more informative. It is often because you are refering to an unregistered pool by its alias. - SQL command logging (using the 'trace' property) now embeds the parameters into the SQL (if the SQL is parametised). This means that the log is almost like a journal - with the exception that any callable statements that return data retain the ? (question marks) that contain the output parameters. - Batched statements are now correctly reported with the trace feature. 0.7.2 - 28 April 2003 - Moved DataSourceTest into Sandbox so that the Ant test target runs correctly. - Fixed a bug in ConfigurationListener that meant that if you passed a Properties object to the Driver when asking for a connection to an existing pool it incorrectly called ConfigurationListenerIF.definitionUpdated when there was no change, and didn't call it when there was. 0.7.1 - 19 April 2003 - Added a lot of concurrency code - mainly using concurrent package written by Doug Lea. - Fixed display bug in AdminServlet - average active time was being displayed in milliseconds instead of seconds. - Refactoring of how definitions are updated and redefined. Use ProxoolFacade.updateConnectionPool to make incremental changes and ProxoolFacade.redefineConnectionPool to reset the definition and start again. (If you pass a Properties object to the DriverManager when asking for a connection this will call redefineConnectionPool.) - if you change the url or any of the delegate properties for a pool's definition then all existing connections are automatically killed so that new ones are created that conform to the new definition. - Change to ConfigurationListenerIF API. defintionChanged is now called definitionChanged (stupid spelling error). - ConnectionListenerIF.onDeath now gets called for all connections closed during shutdown. - Pools manually removed (using ProxoolFacade.removeConnectionPool) are no longer attempted to be removed during shutdown. - Maximum-new-connections property has been deprecated in favour of the more descriptive simultaneous-build-throttle property. - Refactoring of house keeper and prototyper so that the number of threads used by Proxool is more scalable. (Proxool used to create two threads per pool). - Moved AdminServlet to servlet sub-package to make way for upcoming JMX admin implementation. - Fixed bug where ConfigurationListenerIF.definitionUpdated was getting called when you passed a Properties object to the Driver regardless if whether the definition had changed. 0.7 - 21 February 2003 - We have dropped the dependency on commons-logging.jar by copying the code into our own project (retaining credit to the Jakarta team, naturally). - New admin package provides statistical and snapshot information so you can measure how well Proxool, and your database, is doing. - New AdminServlet provides statistical information for your web application. - The JDK 1.2 patch code has been brought up to date and now passes all the unit tests. - The listener code has been redone. Proxool now allows multiple listeners per pool. setFooListener has now been deprecated in favour of addFooListener. And it's now thread safe (just in case you add or remove a listener while the pool is running). - The new ServletConfigurator will help you to configure and shutdown your pools simply by adding a few lines to your servlet configuration (web.xml) file and perhaps writing an XML file. No changes to your Java code. - By using ShutdownHooks (with JDK1.3 or later) we get a cleaner, more reliable shutdown of the pools when the JVM stops. - Removed ReloadMonitor (added in 0.5) because it made use of SystemProperties and this is prohbited by J2SE. You are now responsible for ensuring Proxool is shutdown if your application is reloaded within the same environment (as can sometimes happen in a web application). See ProxoolFacade.shutdown(). - Fixed bug when you asked DatabaseMetaData for the connection. It now gives you back the Proxool connection, not the underlying delegate connection. - Fixed bug where if you registered, removed and then re-registered a pool then the new pool would not notice the Properties passed to it. - If a connection encounters a fatal SQLException (as defined by the fatal-sql-exception property) it now wakes up the house keeper thread so other connections are tested as soon as possible (with the house-keeper-test-sql) rather than waiting for the next scheduled sweep. 0.6 - 23 January 2003 - ProxoolFacade API has changed slightly. Some of the methods no longer throw an SQLException but a ProxoolException instead. This might lead to some small changes in your code. - There used to be some ambiguity about whether you referred to a pool by its alias or its full url (when using ProxoolFacade). This has now been fixed. This means you can now change the url (to use a different database for instance) without creating a new pool. - Version information is now logged so you can tell what version of Proxool you are using. - ConnectionPoolStatisticsIF now reports the time the pool was started. - We now use FastArrayList (from Jakarta Commons) instead of the JDK's Vector for improved collection support. - New XMLConfigurator and PropertyConfigurator to make it easy to configure proxool from a file. - New ConfigurationListenerIF interface allows you to implement persistent configuration - Bug fix for JDBC drivers that implement the Statement interface indirectly (that is, extend a class that implements it rather than implementing it directly). (Credit to Martin Crawford). - Unclosed Statements are now automatically closed when the Connection is closed, in accordance with the JDBC spec. - Rollback is called on all connections when they are closed (that is, returned to the pool). This has no effect if autoCommit it true (default) or any pending transactions have been committed or already rolled back. This will only have an effect if you currently close connections with pending transactions. - New ProxoolFacade#getDelegateStatement allows you to get to the underlying JDBC Driver's original Statement if you really need to. (This isn't recommended unless you have no other choice). - You can now update the URL for a pool, not just the properties. See ProxoolFacade#updateConnectionPool. 0.5 - 3 December 2002) - Fix finalisation of old instances. If you deploy to some environments in a certain way then it is possible for the class to be reloaded without the finalize() method being called. This will result in spurious house keeping threads remaining. The new ReloadMonitor avoids this. - Various improvements to the logging to make it more informative and cleaner. - Checkstyle improvements. We now enforce variable names and line length. Javadoc enforcement to come soon. - Made the onBirth() method of ConnectionListenerIF interface failsafe. And removed obsolete cleanupClob() method (which was never called anyway).. - Removed redundant logFilename stuff from ConnectionPoolDefinition. All logging is handled by Jakarta Commons's Logging anyway. - Fix when removing pools that meant that when you tried to add them again Proxool thought it was a duplicate (Credit to Dan Milstein). - Improvements to the way Proxool detects changes to the pool definition when resending the Properties object when you get a connection. Now detects when it has changed which means that we don't do unnecessary configuration and log is improved (we now log properties as they are set or updated). - Fix to the ProxyConnection within the equals() method that was causing identical conections to be incorrectly reported as unequal (which leads to problems when adding them to some collections). - Improvements to test classes. Lots more tests. - Added support for resetting connection properties when it is returned to the pool (autoCommit, catalog, readOnly, transactionIsolation, typeMap and holdability). These properties are reset to the values when the connection was made everytime it is returned. (credit to Tim Morley) - Connection.isClosed() now returns true when it is back in the pool. - New trace property allows you to log each execution, the SQL, the parameters used, and the execution time (DEBUG level). Use proxool.trace=true property. You can also get this information if you register a ConnectionListenerIF (use ProxoolFacade's setConnectionListener() method). This won't effect performance if you're not listening or have trace off. - Prototyping is now off by default. To enable prototyping you need to set the proxool.prototype-count property to something sensible (like 5, for instance). [Prototyping is where spare connections are when the number of available connections approaches zero.] - Fix for catching fatal SQL exceptions. This is a feature that throws away connections that encounter certain types of exception. 0.4 - 19 September 2002 - Rethink of how we organise our source code so that we can easily build to include different optional components. - Use the Jakarta Commons' ultra-thin log wrapper. This allows you to plugin whatever logging component you like. - Switched to use of the Proxy class so that we are not tied to a particular version of the JDK. However, this does mean a bit of patching to work with JDK 1.2 (Proxy was introduced in 1.3). Fortunately, this patch is handled easily using Ant. - Test classes now make use of Hypersonic. A pure Java database with a very small footprint. This means we can run the tests without having to rely on the existence of a separate database. - Layout and code style changes in accordance with CheckStyle - New XMLConfigurator using JAXP to configure your connection pools. - Improvments in Junit testing. libproxool-java-0.9.1.orig/LICENCE.txt0000644000175000017500000000506710730503132017333 0ustar twernertwernerProxool's Licence -------------- $Revision: 1.4 $ $Date: 2003/03/03 09:20:13 $ $Author: billhorsman $ ==================================================================== Copyright (c) 2002 - 2003 Proxool. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the Proxool project (The latest version is available at http://proxool.sourceforge.net/)." 4. The name "Proxool" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact bill@logicalcobwebs.co.uk. 5. Products derived from this software may not be called "Proxool" nor may "Proxool" appear in their names without prior written permission of the Proxool Project. 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the Proxool project (The latest version is available at http://proxool.sourceforge.net/)." THIS SOFTWARE IS PROVIDED BY THE PROXOOL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROXOOL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================== This software consists of voluntary contributions made by many individuals on behalf of the Proxool Project. For more information on the Proxool Project please see The latest version is available at http://proxool.sourceforge.net. libproxool-java-0.9.1.orig/README.txt0000644000175000017500000000116710730503117017226 0ustar twernertwernerAbout Proxool ------------ $Revision: 1.4 $ $Date: 2002/11/19 12:14:58 $ $Author: billhorsman $ A Java SQL Driver that provides a connection pool wrapper around another Driver of your choice. Very simple to migrate existing code. Fully configurable. Fast, mature and robust. Transparently adds connection pooling to your existing JDBC driver. You can take a look at BUILD.txt, CHANGES.txt and LICENCE.txt but you might have better luck looking at the documentation at doc/index.html. I would welcome any comments you would like to make on Proxool. Good or bad. Bill Horsman 19 September 2002 billhorsman@users.sourceforge.net libproxool-java-0.9.1.orig/build.xml0000644000175000017500000003312711053760610017354 0ustar twernertwerner libproxool-java-0.9.1.orig/proxool-ant.properties0000644000175000017500000000240110730503120022112 0ustar twernertwerner# Properties file for Proxool Ant Build # ----------------------------- # $Revision: 1.13 $ # $Date: 2006/03/24 00:07:12 $ # $Author: billhorsman $ # # You can set any of these properties from the command line: # # ant [target-name] -Dname=value # # or change them in this file if you prefer. The precedence is # whatever gets set first is the final value. So, in order, # command line, this file, the defaults from the build.xml. # Build Directory - where to build classes and jar files # name: build-dir # range: valid path relative to build.xml # default: build # Debug - whether to compile with debug information # name: debug # range: true, false # default: true # Path to Log4J configuration # name: log4jPath # range: path to valid Log4J XML configuration file # default: src/java-test/org/logicalcobwebs/proxool/log4j-test.xml # Sandbox - whether to include the experimental sandbox code # name: sandbox # range: true, false # default: false # Test - whether to include the test classes in the code # name: test # range: true, false # default: false # Test Suite - what to run when calling the "test" target # name: test-suite # range: any test class or suite within the project # default: org.logicalcobwebs.proxool.GlobalTest version=0.9.0RC2