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