at.spardat.xma.datasource.TabularDataSourceClient Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
// @(#) $Id: TabularDataSourceClient.java 2089 2007-11-28 13:56:13Z s3460 $
package at.spardat.xma.datasource;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import at.spardat.enterprise.cache.DefaultCache;
import at.spardat.enterprise.cache.ICache;
import at.spardat.enterprise.cache.ICacheDescriptor;
import at.spardat.enterprise.exc.SysException;
import at.spardat.xma.boot.cache.FileCache;
import at.spardat.xma.boot.cache.IFileCache;
import at.spardat.xma.boot.cache.IFileCacheResource;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.transport.XMA_URI;
import at.spardat.xma.exception.Codes;
import at.spardat.xma.session.XMASession;
import at.spardat.xma.session.XMASessionClient;
/**
* This is the client side implementation of the ITabularDataSource plugin.
* This implementation is part of the XMA runtime. It uses the file cache to load
* the table from the server. In the server side web application, it requires
* a servlet named tabular, which must serve the table.
*
* @author YSD, 23.04.2003 09:27:16
*/
public class TabularDataSourceClient implements ITabularDataSource {
/**
* In-memory cache for tables.
*/
private ICache inMemCache_;
/**
* Removes the resource specified by spec from memory and from file cache.
* @param spec
* @param session
* @return true if resource was successfully removed - otherwise false
* @since version_number
* @author s3460
*/
public boolean invalidate(String spec, XMASession session){
TableSpec tSpec = getTableSpec(spec,session);
URL url = tableSpecToXMA_URI(tSpec, session).getHTTP_URI();
//remove from memory cache
getCache(session).remove(tSpec.toString());
try {//remove from file system (cache)
FileCache.getInstance().invalidateResource(url);
return true;
} catch (IOException e) {
((XMASessionClient)session).getLogger().log(LogLevel.WARNING,url.toString(),e);
return false;
}
}
/**
* Creates a TableSpec from spec.
* If spec is not valid an Exception is thrown (SysException).
* @param spec
* @param session
* @return
* @since version_number
* @author s3460
*/
private TableSpec getTableSpec(String spec, XMASession session){
TableSpec tSpec = new TableSpec (spec);
if (!tSpec.isValid()) {
throw new SysException ("invalid table spec '" + spec + "'").setCode(Codes.DS_CLIENT_INVALID_TABLE_SPEC);
}
tSpec.addContextParams (session);
return tSpec;
}
/**
* Creates the XMA_URI of a resource from a TableSpec object.
* @param tSpec
* @param session
* @return
* @since version_number
* @author s3460
*/
private XMA_URI tableSpecToXMA_URI (TableSpec tSpec, XMASession session){
XMA_URI xmaUri = ((XMASessionClient)session).getUri();
xmaUri.setResource("tabular"); // name of the servlet
/**
* copy all spec-components as query parameters into the URL
*/
Iterator iter = tSpec.iterator();
while (iter.hasNext()) {
String key = (String) iter.next();
xmaUri.addParameter(key, tSpec.getProperty(key));
}
return xmaUri;
}
/**
* Loads a table from the file cache. This method requires a servlet named tabular in
* the server side installation of XMA.
*
* @see at.spardat.xma.datasource.ITabularDataSource#getTable(java.lang.String, at.spardat.xma.session.XMASession)
*/
public ITabularData getTable (String spec, XMASession session) {
IFileCache fileCache = FileCache.getInstance();
ICache inMemCache = getCache(session);
TableSpec tSpec = getTableSpec(spec,session);
String tSpecAsString = tSpec.toString();
ITabularData tabularData = null;
/**
* first step: look up the in-memory-cache
*/
tabularData = (ITabularData) inMemCache.lookup(tSpecAsString);
/**
* look up the file cache if the table is not in the in-memory-cache
*/
if (tabularData == null) {
XMA_URI xmaUri = tableSpecToXMA_URI(tSpec, session);
/**
* Load it
*/
IFileCacheResource rsc = null;
InputStream isFromCache = null;
try {
rsc = fileCache.openResource (((XMASessionClient)session), xmaUri.getHTTP_URI());
isFromCache = rsc.getInputStream();
tabularData = TabularData.readFrom (isFromCache); // this method closes the stream
} catch (Exception ex) {
throw new SysException (ex, "Accessing tabular data '" + spec + "' fails.").setCode(Codes.DS_CLIENT_LOAD_TABLE_FROM_CACHE);
}
/**
* also insert the loaded table in the in-memory-cache
*/
inMemCache.insert (tSpecAsString, tabularData);
}
/**
* output some statistics if system property XMA_TABULAR_CACHE_DEBUG is set
*/
if (System.getProperty("XMA_TABULAR_CACHE_DEBUG") != null) {
((DefaultCache)inMemCache).print();
}
return tabularData;
}
/**
* @see at.spardat.xma.datasource.ITabularDataSource#getDomTable(java.lang.String, at.spardat.xma.session.XMASession)
*/
public ITabularDomData getDomTable (String spec, XMASession session) {
ITabularData table = getTable (spec, session);
if (!(table instanceof ITabularDomData)) throw new IllegalStateException (spec + " is not a domain table");
return (ITabularDomData)table;
}
/**
* Accessor for the in-memory cache
*/
private ICache getCache (XMASession session) {
if (inMemCache_ == null) {
/**
* determine maxAge and maxSize of in-memory cache by accessing
* runtime properties
*/
int numMinutes = 10;
int maxSize = 70;
// overwrite by runtime properties
if (session instanceof XMASessionClient) {
XMASessionClient cSession = (XMASessionClient)session;
String sMinutes = cSession.getRuntimeProperty ("ClMemCacheMaxAgeMinutes", "10");
String sMaxSize = cSession.getRuntimeProperty ("ClMemCacheMaxSize", "70");
try { numMinutes = Integer.parseInt(sMinutes); } catch (Exception x) {};
try { maxSize = Integer.parseInt(sMaxSize); } catch (Exception x) {};
}
final int fnumMinutes = numMinutes;
final int fmaxSize = maxSize;
inMemCache_ = new DefaultCache (new ICacheDescriptor () {
public long getMaxAgeMillis() { return ICacheDescriptor.MILLIS_PER_MINUTE * fnumMinutes; } // 10 minutes
public int getMaxSize() { return fmaxSize; } // max 70 tables
public String getName() { return "tabular"; }
public boolean isTransparent() { return false; } // load is not called
public Object load(Object key) { throw new IllegalStateException(); }
public int getMaxAgeSpreadPct() { return 10; } // 10 percent spread
});
}
return inMemCache_;
}
/**
* Removes all cached tables from the in-memory-cache.
*/
public void emptyInMemoryCache () {
if (inMemCache_ != null) {
inMemCache_.removeAll();
}
}
}