/*
* Copyright (c) 2001 - 2008 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.catalog;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.geoserver.catalog.util.ReaderUtils;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.data.test.MockData;
import org.geoserver.test.GeoServerTestSupport;
import org.geotools.data.DataAccess;
import org.geotools.factory.GeoTools;
import org.geotools.feature.NameImpl;
import org.opengis.feature.Feature;
import org.opengis.feature.type.FeatureType;
import org.w3c.dom.Element;
/**
* Tests for {@link ResourcePool}.
*
* @author Ben Caradoc-Davies, CSIRO Exploration and Mining
*/
public class ResourcePoolTest extends GeoServerTestSupport {
/**
* Test that the {@link FeatureType} cache returns the same instance every time. This is assumed
* by some nasty code in other places that tampers with the CRS. If a new {@link FeatureType} is
* constructed for the same {@link FeatureTypeInfo}, Bad Things Happen (TM).
*/
public void testFeatureTypeCacheInstance() throws Exception {
ResourcePool pool = new ResourcePool(getCatalog());
FeatureTypeInfo info = getCatalog().getFeatureTypeByName(
MockData.LAKES.getNamespaceURI(), MockData.LAKES.getLocalPart());
FeatureType ft1 = pool.getFeatureType(info);
FeatureType ft2 = pool.getFeatureType(info);
FeatureType ft3 = pool.getFeatureType(info);
assertSame(ft1, ft2);
assertSame(ft1, ft3);
}
public void testAttributeCache() throws Exception {
final Catalog catalog = getCatalog();
ResourcePool pool = new ResourcePool(catalog);
// clean up the lakes type
FeatureTypeInfo oldInfo = catalog.getFeatureTypeByName(
MockData.LAKES.getNamespaceURI(), MockData.LAKES.getLocalPart());
List<LayerInfo> layers = catalog.getLayers(oldInfo);
for (LayerInfo layerInfo : layers) {
catalog.remove(layerInfo);
}
catalog.remove(oldInfo);
// rebuild as new
CatalogBuilder builder = new CatalogBuilder(catalog);
builder.setStore(catalog.getStoreByName(MockData.CITE_PREFIX, MockData.CITE_PREFIX, DataStoreInfo.class));
FeatureTypeInfo info = builder.buildFeatureType(new NameImpl(MockData.LAKES.getNamespaceURI(), MockData.LAKES.getLocalPart()));
// non persisted state, caching should not occurr
List<AttributeTypeInfo> att1 = pool.getAttributes(info);
List<AttributeTypeInfo> att2 = pool.getAttributes(info);
assertNotSame(att1, att2);
assertEquals(att1, att2);
// save it, making it persistent
catalog.add(info);
// first check caching actually works against persisted type infos
List<AttributeTypeInfo> att3 = pool.getAttributes(info);
List<AttributeTypeInfo> att4 = pool.getAttributes(info);
assertSame(att3, att4);
assertNotSame(att1, att3);
assertEquals(att1, att3);
}
boolean cleared = false;
public void testCacheClearing() throws IOException {
cleared = false;
ResourcePool pool = new ResourcePool(getCatalog()) {
@Override
public void clear(FeatureTypeInfo info) {
cleared = true;
super.clear(info);
}
};
FeatureTypeInfo info = getCatalog().getFeatureTypeByName(
MockData.LAKES.getNamespaceURI(), MockData.LAKES.getLocalPart());
assertNotNull( pool.getFeatureType( info ) );
info.setTitle("changed");
assertFalse( cleared );
getCatalog().save( info );
assertTrue( cleared );
cleared = false;
assertNotNull( pool.getFeatureType( info ) );
for ( LayerInfo l : getCatalog().getLayers( info ) ) {
getCatalog().remove( l );
}
getCatalog().remove( info );
assertTrue( cleared );
}
boolean disposeCalled;
/**
* Make sure {@link ResourcePool#clear(DataStoreInfo)} and {@link ResourcePool#dispose()} call
* {@link DataAccess#dispose()}
*/
public void testDispose() throws IOException {
disposeCalled = false;
class ResourcePool2 extends ResourcePool {
@SuppressWarnings("serial")
public ResourcePool2(Catalog catalog) {
super(catalog);
dataStoreCache = new DataStoreCache() {
@SuppressWarnings("unchecked")
@Override
protected void dispose(String name, DataAccess dataStore) {
disposeCalled = true;
super.dispose(name, dataStore);
}
};
}
}
Catalog catalog = getCatalog();
ResourcePool pool = new ResourcePool2(catalog);
catalog.setResourcePool(pool);
DataStoreInfo info = catalog.getDataStores().get(0);
// force the datastore to be created
DataAccess<? extends FeatureType, ? extends Feature> dataStore = pool.getDataStore(info);
assertNotNull(dataStore);
assertFalse(disposeCalled);
pool.clear(info);
assertTrue(disposeCalled);
// force the datastore to be created
dataStore = pool.getDataStore(info);
assertNotNull(dataStore);
disposeCalled = false;
pool.dispose();
assertTrue(disposeCalled);
}
public void testGeoServerReload() throws Exception {
Catalog cat = getCatalog();
FeatureTypeInfo lakes = cat.getFeatureTypeByName(MockData.LAKES.getNamespaceURI(),
MockData.LAKES.getLocalPart());
assertFalse("foo".equals(lakes.getTitle()));
File info = getResourceLoader().find("featureTypes", "cite_Lakes", "info.xml");
FileReader in = new FileReader(info);
Element dom = ReaderUtils.parse(in);
Element title = ReaderUtils.getChildElement(dom, "title");
title.getFirstChild().setNodeValue("foo");
OutputStream output = new FileOutputStream(info);
try {
TransformerFactory.newInstance().newTransformer()
.transform(new DOMSource(dom), new StreamResult(output));
} finally {
output.close();
}
getGeoServer().reload();
lakes = cat.getFeatureTypeByName(MockData.LAKES.getNamespaceURI(),
MockData.LAKES.getLocalPart());
assertEquals("foo", lakes.getTitle());
}
public void testConfigureFeatureTypeCacheSize() {
GeoServer gs = getGeoServer();
GeoServerInfo global = gs.getGlobal();
global.setFeatureTypeCacheSize(200);
gs.save(global);
Catalog catalog = getCatalog();
assertEquals(200, catalog.getResourcePool().featureTypeCache.getHardReferencesCount());
}
public void testDropCoverageStore() throws Exception {
// build the store
Catalog cat = getCatalog();
CatalogBuilder cb = new CatalogBuilder(cat);
CoverageStoreInfo store = cb.buildCoverageStore("dem");
store.setURL(MockData.class.getResource("tazdem.tiff").toExternalForm());
store.setType("GeoTIFF");
cat.add(store);
// build the coverage
cb.setStore(store);
CoverageInfo ci = cb.buildCoverage();
cat.add(ci);
// build the layer
LayerInfo layer = cb.buildLayer(ci);
cat.add(layer);
// grab a reader just to inizialize the code
ci.getGridCoverage(null, null);
ci.getGridCoverageReader(null, GeoTools.getDefaultHints());
// now drop the store
CascadeDeleteVisitor visitor = new CascadeDeleteVisitor(cat);
visitor.visit(store);
// and reload (GEOS-4782 -> BOOM!)
getGeoServer().reload();
}
}