All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.spardat.xma.datasource.TabularDataSourceClient Maven / Gradle / Ivy

/*******************************************************************************
 * 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();
        }
    }
			    	    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy