Wow that is a tangle!

I am still keen to have a GeoTools.cleanup() method; and perhaps a 
GeoTools.registerCleanup( Cleanup ) so that our "dependencies" can register 
themselves to be cleaned.

Boy I am stick of Factory SPI :-(

Please commit on trunk as you say; we are fixing mistakes/sanity.

Jody

On 19/05/2010, at 11:48 PM, Andrea Aime wrote:

> Hi,
> so as you I've been working on allowing web applications to properly undeploy 
> without leaking permanent generation memory. I have a first
> cut that solves all the problems I've been able to find so far.
> 
> Unfortunately it still does not allow GS to actually undeploy cleanly,
> but it's a step in the right direction and makes debugging whatever
> else is missing easier.
> 
> The set of issues I've been looking into is detailed in this
> page:
> http://wiki.apache.org/tomcat/MemoryLeakProtection
> 
> Basically our referencing/coverage subsystems violated every rule in
> that page, and I guess more, since GS still does not deploys cleanly
> and I'm at a loss at finding more reasons for that ;-)
> 
> Anyways, the attached patch contains changes that either handle
> the issue or make it easier to look for further problems.
> In particular:
> - cleans up all the thread locals I could actually get rid of
> - it exposes a CRS.cleaupThreadLocals() for the two thread locals
>  that I could not get rid of and that cannot be easily removed
>  either. A web application must add a filter that calls that
>  method after each request (annoying, I know)
> - adds methods to empty all SPI registries before shutdown
> - changes CRS2GeoTiffMetadataAdapter to use the factories exposed
>  by the referencing subsystem instead of creating its own
>  transform factory (which in turn holds another SPI registry).
>  Don't worry for this one, the transform factory returned
>  by the finder is cached itself, so it's really just removing
>  a duplication
> - removes the ThreadedEPSGFactory shutdown hook, a thread
>  that is registered globally in the JVM for the purpose of
>  shutting down the EPSG database connections... something
>  that is completely not needed, as the connections simple cease
>  existing and the embedded databases are all working read only
>  (so they can be killed abruptly without issues)
> 
> As for adding a method in GeoTools that makes all the necessary
> calls to shut down the application, it can get tricky due
> to dependencies (it should be in a central module, but from
> that central module you don't see all the necessary dependencies).
> So what about a page explaining what one should do instead?
> Is there a place in the sphinx docs for that?
> 
> I plan to commit the changes tomorrow on trunk only
> unless someone objects
> 
> Cheers
> Andrea
> 
> -- 
> Andrea Aime
> OpenGeo - http://opengeo.org
> Expert service straight from the developers.
> diff --git 
> a/modules/library/coverage/src/main/java/org/geotools/coverage/grid/io/imageio/geotiff/GeoTiffMetadata2CRSAdapter.java
>  
> b/modules/library/coverage/src/main/java/org/geotools/coverage/grid/io/imageio/geotiff/GeoTiffMetadata2CRSAdapter.java
> index 11abf7f..0ca06ef 100644
> --- 
> a/modules/library/coverage/src/main/java/org/geotools/coverage/grid/io/imageio/geotiff/GeoTiffMetadata2CRSAdapter.java
> +++ 
> b/modules/library/coverage/src/main/java/org/geotools/coverage/grid/io/imageio/geotiff/GeoTiffMetadata2CRSAdapter.java
> @@ -50,6 +50,7 @@ import javax.measure.unit.Unit;
> import 
> org.geotools.coverage.grid.io.imageio.geotiff.codes.GeoTiffCoordinateTransformationsCodes;
> import org.geotools.coverage.grid.io.imageio.geotiff.codes.GeoTiffGCSCodes;
> import org.geotools.coverage.grid.io.imageio.geotiff.codes.GeoTiffPCSCodes;
> +import org.geotools.factory.CommonFactoryFinder;
> import org.geotools.factory.Hints;
> import org.geotools.metadata.iso.citation.CitationImpl;
> import org.geotools.referencing.CRS;
> @@ -154,7 +155,7 @@ public final class GeoTiffMetadata2CRSAdapter {
>        * Cached {...@link MathTransformFactory} for building {...@link 
> MathTransform}
>        * objects.
>        */
> -     private final static MathTransformFactory mtFactory = new 
> DefaultMathTransformFactory();
> +     private MathTransformFactory mtFactory = 
> ReferencingFactoryFinder.getMathTransformFactory(null);
> 
>       /**
>        * The default value for {...@link #maxStrongReferences} .
> @@ -1799,4 +1800,5 @@ public final class GeoTiffMetadata2CRSAdapter {
>       public Hints getHints() {
>               return hints;
>       }
> +     
> }
> diff --git 
> a/modules/library/main/src/main/java/org/geotools/data/DataAccessFinder.java 
> b/modules/library/main/src/main/java/org/geotools/data/DataAccessFinder.java
> index 59101c1..41fd626 100644
> --- 
> a/modules/library/main/src/main/java/org/geotools/data/DataAccessFinder.java
> +++ 
> b/modules/library/main/src/main/java/org/geotools/data/DataAccessFinder.java
> @@ -242,4 +242,15 @@ public final class DataAccessFinder {
>         DataStoreFinder.scanForPlugins();
>         getServiceRegistry().scanForPlugins();
>     }
> +    
> +    /**
> +     * Resets the factory finder and prepares for a new full scan of the SPI 
> subsystems
> +     */
> +    public static void reset() {
> +        FactoryRegistry copy = registry;
> +        registry = null;
> +        if(copy != null) {
> +            copy.deregisterAll();
> +        }
> +    }
> }
> diff --git 
> a/modules/library/main/src/main/java/org/geotools/data/DataStoreFinder.java 
> b/modules/library/main/src/main/java/org/geotools/data/DataStoreFinder.java
> index 3a6a0fa..b2c254c 100644
> --- 
> a/modules/library/main/src/main/java/org/geotools/data/DataStoreFinder.java
> +++ 
> b/modules/library/main/src/main/java/org/geotools/data/DataStoreFinder.java
> @@ -143,5 +143,16 @@ public final class DataStoreFinder {
>               getServiceRegistry().scanForPlugins();
> 
>       }
> +     
> +     /**
> +          * Resets the factory finder and prepares for a new full scan of 
> the SPI subsystems
> +          */
> +         public static void reset() {
> +             FactoryRegistry copy = registry;
> +             registry = null;
> +             if(copy != null) {
> +                 copy.deregisterAll();
> +             }
> +         }
> 
> }
> diff --git 
> a/modules/library/main/src/main/java/org/geotools/factory/CommonFactoryFinder.java
>  
> b/modules/library/main/src/main/java/org/geotools/factory/CommonFactoryFinder.java
> index 62f0517..7b2e4d8 100644
> --- 
> a/modules/library/main/src/main/java/org/geotools/factory/CommonFactoryFinder.java
> +++ 
> b/modules/library/main/src/main/java/org/geotools/factory/CommonFactoryFinder.java
> @@ -326,4 +326,15 @@ public final class CommonFactoryFinder extends 
> FactoryFinder {
>             registry.scanForPlugins();
>         }
>     }
> +    
> +    /**
> +     * Resets the factory finder and prepares for a new full scan of the SPI 
> subsystems
> +     */
> +    public static void reset() {
> +        FactoryRegistry copy = registry;
> +        registry = null;
> +        if(copy != null) {
> +            copy.deregisterAll();
> +        }
> +    }
> }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/CRS.java 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/CRS.java
> index 165f43d..9ee0573 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/CRS.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/CRS.java
> @@ -64,8 +64,10 @@ import org.geotools.referencing.cs.DefaultEllipsoidalCS;
> import org.geotools.referencing.cs.DefaultCoordinateSystemAxis;
> import org.geotools.referencing.factory.AbstractAuthorityFactory;
> import org.geotools.referencing.factory.IdentifiedObjectFinder;
> +import org.geotools.referencing.operation.DefaultMathTransformFactory;
> import org.geotools.referencing.operation.projection.MapProjection;
> import org.geotools.referencing.operation.transform.IdentityTransform;
> +import org.geotools.referencing.wkt.Formattable;
> import org.geotools.resources.geometry.XRectangle2D;
> import org.geotools.resources.CRSUtilities;
> import org.geotools.resources.i18n.Errors;
> @@ -1679,6 +1681,16 @@ search:             if 
> (DefaultCoordinateSystemAxis.isCompassDirection(axis.getD
>         strictFactory = null;
>         lenientFactory = null;
>     }
> +    
> +    /**
> +     * Cleans up the thread local set in this thread. They can prevent web 
> applications from
> +     * proper shutdown
> +     */
> +    public static void cleanupThreadLocals() {
> +        DefaultMathTransformFactory.cleanupThreadLocals();
> +        Formattable.cleanupThreadLocals();
> +    }
> +
> 
>     /**
>      * Prints to the {...@linkplain System#out standard output stream} some 
> information about
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/ReferencingFactoryFinder.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/ReferencingFactoryFinder.java
> index fc3b34c..92a8330 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/ReferencingFactoryFinder.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/ReferencingFactoryFinder.java
> @@ -709,7 +709,11 @@ loop:       for (int i=0; ; i++) {
>      * Resets the factory finder and prepares for a new full scan of the SPI 
> subsystems
>      */
>     public static void reset() {
> +        FactoryRegistry copy = registry;
>         registry = null;
> +        if(copy != null) {
> +            copy.deregisterAll();
> +        }
>     }
> 
>     /**
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/crs/AbstractDerivedCRS.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/crs/AbstractDerivedCRS.java
> index 0b2ac82..79d4fb9 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/crs/AbstractDerivedCRS.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/crs/AbstractDerivedCRS.java
> @@ -341,7 +341,7 @@ public class AbstractDerivedCRS extends AbstractSingleCRS 
> implements GeneralDeri
>                                   that.conversionFromBase,
>                                   compareMetadata);
>                 } finally {
> -                    _COMPARING.set(Boolean.FALSE);
> +                    _COMPARING.remove();
>                 }
>             }
>         }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/AuthorityFactoryAdapter.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/AuthorityFactoryAdapter.java
> index f333d91..81c705a 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/AuthorityFactoryAdapter.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/AuthorityFactoryAdapter.java
> @@ -1263,4 +1263,19 @@ public class AuthorityFactoryAdapter extends 
> AbstractAuthorityFactory implements
>         }
>         return false;
>     }
> +    
> +    @Override
> +    public void dispose() throws FactoryException {
> +        super.dispose();
> +        disposeAbstractAuthorityFactory(datumFactory);
> +        disposeAbstractAuthorityFactory(csFactory);
> +        disposeAbstractAuthorityFactory(crsFactory);
> +        disposeAbstractAuthorityFactory(operationFactory);
> +    }
> +    
> +    private void disposeAbstractAuthorityFactory(Object factory) throws 
> FactoryException {
> +        if(factory instanceof AbstractAuthorityFactory) {
> +            ((AbstractAuthorityFactory) factory).dispose();
> +        }
> +    }
> }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java
> index 5cf129d..b895884 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java
> @@ -52,10 +52,8 @@ public abstract class DeferredAuthorityFactory extends 
> BufferedAuthorityFactory
> {
>     /**
>      * The timer for {...@linkplain AbstractAuthorityFactory#dispose 
> disposing} backing stores.
> -     *
> -     * @todo Give a name to this timer when we will be allowed to compile 
> for J2SE 1.5.
>      */
> -    private static final Timer TIMER = new Timer(true);
> +    private static Timer TIMER = new Timer("GT authority factory disposer", 
> true);
> 
>     /**
>      * The task for disposing the backing store, or {...@code null} if none.
> @@ -170,6 +168,10 @@ public abstract class DeferredAuthorityFactory extends 
> BufferedAuthorityFactory
>      *        much as twice that time before to be closed.
>      */
>     public synchronized void setTimeout(final long delay) {
> +        // if we have been disposed, don't do anything
> +        if(TIMER == null)
> +            return;
> +        
>         if (disposer != null) {
>             disposer.cancel();
>         }
> @@ -202,6 +204,16 @@ public abstract class DeferredAuthorityFactory extends 
> BufferedAuthorityFactory
>         }
>         super.dispose();
>     }
> +    
> +    /**
> +     * Gets rid of the timer thread at application shutdown
> +     */
> +    public static void exit() {
> +        if(TIMER != null) {
> +            TIMER.cancel();
> +            TIMER = null;
> +        }
> +    }
> 
>     /**
>      * The task for closing the backing store after the timeout.
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/ManyAuthoritiesFactory.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/ManyAuthoritiesFactory.java
> index 8c11327..7a63eda 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/ManyAuthoritiesFactory.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/ManyAuthoritiesFactory.java
> @@ -585,8 +585,8 @@ public class ManyAuthoritiesFactory extends 
> AuthorityFactoryAdapter implements C
>         final Set<String> codes = new LinkedHashSet<String>();
>         final Set<AuthorityFactory> done = new HashSet<AuthorityFactory>();
>         done.add(this); // Safety for avoiding recursive calls.
> -        inProgress.set(Boolean.TRUE);
>         try {
> +            inProgress.set(Boolean.TRUE);
>             for (String authority : getAuthorityNames()) {
>                 authority = authority.trim();
>                 final char separator = getSeparator(authority);
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/DirectEpsgFactory.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/DirectEpsgFactory.java
> index b0ab4ac..6ad5a08 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/DirectEpsgFactory.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/DirectEpsgFactory.java
> @@ -2988,7 +2988,6 @@ public abstract class DirectEpsgFactory extends 
> DirectAuthorityFactory
>      */
>     @Override
>     public synchronized void dispose() throws FactoryException {
> -        final boolean shutdown = 
> SHUTDOWN_THREAD.equals(Thread.currentThread().getName());
>         final boolean isClosed;
>         try {
>             Connection connection = getConnection();
> @@ -3006,16 +3005,14 @@ public abstract class DirectEpsgFactory extends 
> DirectAuthorityFactory
>                 ((PreparedStatement) it.next()).close();
>                 it.remove();
>             }
> -            if (shutdown) {
> -                shutdown(true);
> -            }
> +            shutdown(true);
>             connection.close();
>             dataSource = null;
>         } catch (SQLException exception) {
>             throw new FactoryException(exception);
>         }
>         super.dispose();
> -        if (shutdown) try {
> +        try {
>             shutdown(false);
>         } catch (SQLException exception) {
>             throw new FactoryException(exception);
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/ThreadedEpsgFactory.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/ThreadedEpsgFactory.java
> index bc71efe..71c7523 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/ThreadedEpsgFactory.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/ThreadedEpsgFactory.java
> @@ -137,11 +137,6 @@ public class ThreadedEpsgFactory extends 
> DeferredAuthorityFactory
>     private DataSource datasource;
> 
>     /**
> -     * The shutdown hook, or {...@code null} if none.
> -     */
> -    private Thread shutdown;
> -
> -    /**
>      * Constructs an authority factory using the default set of factories.
>      */
>     public ThreadedEpsgFactory() {
> @@ -457,57 +452,4 @@ public class ThreadedEpsgFactory extends 
> DeferredAuthorityFactory
>         return super.canDisposeBackingStore(backingStore);
>     }
> 
> -    /**
> -     * Ensures that the database connection will be closed on JVM exit. This 
> code will be executed
> -     * even if the JVM is terminated because of an exception or with 
> [Ctrl-C]. Note: we create this
> -     * shutdown hook only if this factory is registered as a service because 
> it will prevent this
> -     * instance to be garbage collected until it is deregistered.
> -     */
> -    private final class ShutdownHook extends Thread {
> -        public ShutdownHook() {
> -            super(DirectEpsgFactory.SHUTDOWN_THREAD);
> -        }
> -
> -        @Override
> -        public void run() {
> -            synchronized (ThreadedEpsgFactory.this) {
> -                try {
> -                    dispose();
> -                } catch (Throwable exception) {
> -                    // Too late for logging, since the JVM is
> -                    // in process of shutting down. Ignore...
> -                }
> -            }
> -        }
> -    }
> -
> -    /**
> -     * Called when this factory is added to the given {...@code category} of 
> the given
> -     * {...@code registry}. The object may already be registered under 
> another category.
> -     */
> -    @Override
> -    public synchronized void onRegistration(final ServiceRegistry registry, 
> final Class category) {
> -        super.onRegistration(registry, category);
> -        if (shutdown == null) {
> -            shutdown = new ShutdownHook();
> -            Runtime.getRuntime().addShutdownHook(shutdown);
> -        }
> -    }
> -
> -    /**
> -     * Called when this factory is removed from the given {...@code 
> category} of the given
> -     * {...@code registry}.  The object may still be registered under 
> another category.
> -     */
> -    @Override
> -    public synchronized void onDeregistration(final ServiceRegistry 
> registry, final Class category) {
> -        if (shutdown != null) {
> -            if (registry.getServiceProviderByClass(getClass()) == null) {
> -                // Remove the shutdown hook only if this instance is not
> -                // anymore registered as a service under any category.
> -                Runtime.getRuntime().removeShutdownHook(shutdown);
> -                shutdown = null;
> -            }
> -        }
> -        super.onDeregistration(registry, category);
> -    }
> }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java
> index 88715a8..e02b282 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java
> @@ -304,7 +304,7 @@ public class AuthorityBackedFactory extends 
> DefaultCoordinateOperationFactory
>                         prepend = createOperation(sourceCRS, 
> source).getMathTransform();
>                         source  = sourceCRS;
>                     } finally {
> -                        processing.set(Boolean.FALSE);
> +                        processing.remove();
>                     } else {
>                         prepend = null;
>                     }
> @@ -313,7 +313,7 @@ public class AuthorityBackedFactory extends 
> DefaultCoordinateOperationFactory
>                         append = createOperation(target, 
> targetCRS).getMathTransform();
>                         target = targetCRS;
>                     } finally {
> -                        processing.set(Boolean.FALSE);
> +                        processing.remove();
>                     } else {
>                         append = null;
>                     }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/operation/DefaultMathTransformFactory.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/operation/DefaultMathTransformFactory.java
> index 1abf672..c6a5fa6 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/operation/DefaultMathTransformFactory.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/operation/DefaultMathTransformFactory.java
> @@ -130,7 +130,7 @@ public class DefaultMathTransformFactory extends 
> ReferencingFactory implements M
>     /**
>      * The operation method for the last transform created.
>      */
> -    private final ThreadLocal<OperationMethod> lastMethod;
> +    private static final ThreadLocal<OperationMethod> lastMethod = new 
> ThreadLocal<OperationMethod>();
> 
>     /**
>      * A pool of math transform. This pool is used in order to
> @@ -159,7 +159,6 @@ public class DefaultMathTransformFactory extends 
> ReferencingFactory implements M
>      */
>     private DefaultMathTransformFactory(final Class<?>[] categories) {
>         registry   = new FactoryRegistry(Arrays.asList(categories));
> -        lastMethod = new ThreadLocal<OperationMethod>();
>         pool       = CanonicalSet.newInstance(MathTransform.class);
>     }
> 
> @@ -708,4 +707,12 @@ public class DefaultMathTransformFactory extends 
> ReferencingFactory implements M
>         }
>         arguments.out.flush();
>     }
> +    
> +    /**
> +     * Cleans up the thread local set in this thread. They can prevent web 
> applications from
> +     * proper shutdown
> +     */
> +    public static void cleanupThreadLocals() {
> +        lastMethod.remove();
> +    }
> }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formattable.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formattable.java
> index 49221ee..e7595c0 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formattable.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formattable.java
> @@ -243,4 +243,13 @@ public class Formattable {
>     static void setIndentation(final int indentation) throws 
> SecurityException {
>         Preferences.userNodeForPackage(Formattable.class).putInt(INDENTATION, 
> indentation);
>     }
> +    
> +    /**
> +     * Cleans up the thread local set in this thread. They can prevent web 
> applications from
> +     * proper shutdown
> +     */
> +    public static void cleanupThreadLocals() {
> +        FORMATTER.remove();
> +    }
> +
> }
> diff --git 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formatter.java
>  
> b/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formatter.java
> index 6d9f05e..706ade2 100644
> --- 
> a/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formatter.java
> +++ 
> b/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/Formatter.java
> @@ -884,6 +884,7 @@ public class Formatter {
>         lineChanged   = false;
>         margin        = 0;
>     }
> +    
> 
>     /**
>      * Set the preferred indentation from the command line. This indentation 
> is used by
> diff --git 
> a/modules/plugin/epsg-hsql/src/main/java/org/geotools/referencing/factory/epsg/ThreadedHsqlEpsgFactory.java
>  
> b/modules/plugin/epsg-hsql/src/main/java/org/geotools/referencing/factory/epsg/ThreadedHsqlEpsgFactory.java
> index 61c5d5d..f1b1972 100644
> --- 
> a/modules/plugin/epsg-hsql/src/main/java/org/geotools/referencing/factory/epsg/ThreadedHsqlEpsgFactory.java
> +++ 
> b/modules/plugin/epsg-hsql/src/main/java/org/geotools/referencing/factory/epsg/ThreadedHsqlEpsgFactory.java
> @@ -41,6 +41,7 @@ import org.geotools.resources.i18n.Loggings;
> import org.geotools.util.Version;
> import org.geotools.util.logging.Logging;
> import org.hsqldb.jdbc.jdbcDataSource;
> +import org.opengis.referencing.FactoryException;
> 
> 
> /**
> @@ -226,6 +227,7 @@ public class ThreadedHsqlEpsgFactory extends 
> ThreadedEpsgFactory {
>                 url.append('/');
>             }
>             url.append(DATABASE_NAME);
> +            url.append(";shutdown=true");
>             source.setDatabase(url.toString());
>             assert directory.equals(getDirectory(source)) : url;
>         }
> ------------------------------------------------------------------------------
> 
> _______________________________________________
> Geotools-devel mailing list
> Geotools-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/geotools-devel


------------------------------------------------------------------------------

_______________________________________________
Geotools-devel mailing list
Geotools-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to