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