001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2002-2005 Julian Hyde
008// Copyright (C) 2005-2009 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.web.taglib;
012
013import mondrian.olap.*;
014import mondrian.spi.impl.ServletContextCatalogLocator;
015
016import org.apache.log4j.Logger;
017
018import org.w3c.dom.Document;
019
020import javax.servlet.ServletContext;
021import javax.servlet.http.*;
022import javax.xml.parsers.ParserConfigurationException;
023
024/**
025 * Holds a query/result pair in the user's session.
026 *
027 * @author Andreas Voss, 22 March, 2002
028 */
029public class ResultCache implements HttpSessionBindingListener {
030    private static final Logger LOGGER = Logger.getLogger(ResultCache.class);
031    private static final String ATTR_NAME = "mondrian.web.taglib.ResultCache.";
032    private Query query = null;
033    private Result result = null;
034    private Document document = null;
035    private ServletContext servletContext;
036    private Connection connection;
037
038    private ResultCache(ServletContext context) {
039        this.servletContext = context;
040    }
041
042
043    /**
044     * Retrieves a cached query. It is identified by its name and the
045     * current session. The servletContext parameter is necessary because
046     * HttpSession.getServletContext was not added until J2EE 1.3.
047     */
048    public static ResultCache getInstance(
049        HttpSession session,
050        ServletContext servletContext,
051        String name)
052    {
053        String fqname = ATTR_NAME + name;
054        ResultCache resultCache = (ResultCache) session.getAttribute(fqname);
055        if (resultCache == null) {
056            resultCache = new ResultCache(servletContext);
057            session.setAttribute(fqname, resultCache);
058        }
059        return resultCache;
060    }
061
062    public void parse(String mdx) {
063        if (connection != null) {
064            query = connection.parseQuery(mdx);
065            setDirty();
066        } else {
067            LOGGER.error("null connection");
068        }
069    }
070
071    public Result getResult() {
072        if (result == null) {
073            long t1 = System.currentTimeMillis();
074            result = connection.execute(query);
075            long t2 = System.currentTimeMillis();
076            LOGGER.debug(
077                "Execute query took " + (t2 - t1) + " millisec");
078        }
079        return result;
080    }
081
082    public Document getDOM() {
083        try {
084            if (document == null) {
085                document = DomBuilder.build(getResult());
086            }
087            return document;
088        } catch (ParserConfigurationException e) {
089            LOGGER.error(e);
090            throw new RuntimeException(e.toString());
091        }
092    }
093
094    /**
095     * Returns the {@link Query}. If you modify the query, call
096     * <code>{@link #setDirty}(true)</code>.
097     */
098    public Query getQuery() {
099        return query;
100    }
101
102    /**
103     * Sets the query. Automatically calls <code>{@link #setDirty}(true)</code>.
104     */
105    public void setQuery(Query query) {
106        this.query = query;
107        setDirty();
108    }
109    /**
110     * set to dirty after you have modified the query to force a recalcuation
111     */
112    public void setDirty() {
113        result = null;
114        document = null;
115    }
116
117    /**
118     * create a new connection to Mondrian
119     */
120    public void valueBound(HttpSessionBindingEvent ev) {
121        String connectString =
122            servletContext.getInitParameter("connectString");
123        LOGGER.debug("connectString: " + connectString);
124        this.connection =
125            DriverManager.getConnection(
126                connectString,
127                new ServletContextCatalogLocator(servletContext));
128        if (this.connection == null) {
129            throw new RuntimeException(
130                "No ROLAP connection from connectString: "
131                    + connectString);
132        }
133    }
134
135    /**
136     * close connection
137     */
138    public void valueUnbound(HttpSessionBindingEvent ev) {
139        if (connection != null) {
140            connection.close();
141        }
142    }
143
144
145}
146
147// End ResultCache.java