001 /* 002 // $Id: //open/mondrian/src/main/mondrian/web/servlet/MDXQueryServlet.java#28 $ 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 // Sean McCullough, 13 February, 2002, 10:25 PM 012 */ 013 014 package mondrian.web.servlet; 015 016 import java.io.IOException; 017 import java.util.List; 018 import java.util.Enumeration; 019 020 import javax.servlet.ServletConfig; 021 import javax.servlet.ServletException; 022 import javax.servlet.http.HttpServlet; 023 import javax.servlet.http.HttpServletRequest; 024 import javax.servlet.http.HttpServletResponse; 025 026 import mondrian.olap.*; 027 import mondrian.spi.CatalogLocator; 028 import mondrian.spi.impl.ServletContextCatalogLocator; 029 import mondrian.web.taglib.ResultCache; 030 031 import org.eigenbase.xom.StringEscaper; 032 033 /** 034 * <code>MDXQueryServlet</code> is a servlet which receives MDX queries, 035 * executes them, and formats the results in an HTML table. 036 * 037 * @author Sean McCullough 038 * @since 13 February, 2002 039 * @version $Id: //open/mondrian/src/main/mondrian/web/servlet/MDXQueryServlet.java#28 $ 040 */ 041 public class MDXQueryServlet extends HttpServlet { 042 private String connectString; 043 private CatalogLocator locator; 044 045 /** Initializes the servlet. 046 */ 047 public void init(ServletConfig config) throws ServletException { 048 super.init(config); 049 connectString = config.getInitParameter("connectString"); 050 Enumeration initParameterNames = config.getInitParameterNames(); 051 while (initParameterNames.hasMoreElements()) { 052 String name = (String) initParameterNames.nextElement(); 053 String value = config.getInitParameter(name); 054 MondrianProperties.instance().setProperty(name, value); 055 } 056 locator = new ServletContextCatalogLocator(config.getServletContext()); 057 } 058 059 /** Destroys the servlet. 060 */ 061 public void destroy() { 062 063 } 064 065 /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods. 066 * @param request servlet request 067 * @param response servlet response 068 */ 069 protected void processRequest(HttpServletRequest request, HttpServletResponse response) 070 throws ServletException, java.io.IOException { 071 String queryName = request.getParameter("query"); 072 request.setAttribute("query", queryName); 073 if (queryName != null) { 074 processTransform(request,response); 075 return; 076 } 077 String queryString = request.getParameter("queryString"); 078 request.setAttribute("queryString", queryString); 079 mondrian.olap.Connection mdxConnection = null; 080 StringBuffer html = new StringBuffer(); 081 082 // execute the query 083 try { 084 mdxConnection = DriverManager.getConnection(connectString, locator); 085 Query q = mdxConnection.parseQuery(queryString); 086 Result result = mdxConnection.execute(q); 087 List<Position> slicers = result.getSlicerAxis().getPositions(); 088 html.append("<table class='resulttable' cellspacing=1 border=0>"); 089 html.append(Util.nl); 090 091 List<Position> columns = result.getAxes()[0].getPositions(); 092 List<Position> rows = null; 093 if (result.getAxes().length == 2) 094 rows = result.getAxes()[1].getPositions(); 095 096 int columnWidth = columns.get(0).size(); 097 int rowWidth = 0; 098 if (result.getAxes().length == 2) 099 rowWidth = result.getAxes()[1].getPositions().get(0).size(); 100 101 for (int j = 0; j < columnWidth; j++) { 102 html.append("<tr>"); 103 104 // if it has more than 1 dimension 105 if (j == 0 && result.getAxes().length > 1) { 106 // Print the top-left cell, and fill it with slicer members. 107 html.append("<td nowrap class='slicer' rowspan='").append( 108 columnWidth).append("' colspan='").append(rowWidth) 109 .append("'>"); 110 for (Position position : slicers) { 111 int k = 0; 112 for (Member member : position) { 113 if (k > 0) { 114 html.append("<br/>"); 115 } 116 html.append(member.getUniqueName()); 117 k++; 118 } 119 /* 120 for (int k = 0; k < position.size(); k++) { 121 if (k > 0) { 122 html.append("<br/>"); 123 } 124 Member member = position.getMember(k); 125 html.append(member.getUniqueName()); 126 } 127 */ 128 } 129 html.append(" </td>").append(Util.nl); 130 } 131 132 // Print the column headings. 133 for (int i = 0; i < columns.size(); i++) { 134 Position position = columns.get(i); 135 //Member member = columns[i].getMember(j); 136 Member member = position.get(j); 137 int width = 1; 138 while ((i + 1) < columns.size() && 139 columns.get(i + 1).get(j) == member) { 140 i++; 141 width++; 142 } 143 html.append("<td nowrap class='columnheading' colspan='") 144 .append(width).append("'>") 145 .append(member.getUniqueName()).append("</td>"); 146 } 147 html.append("</tr>").append(Util.nl); 148 } 149 //if is two axes, show 150 if (result.getAxes().length > 1) { 151 for (int i = 0; i < rows.size(); i++) { 152 html.append("<tr>"); 153 final Position row = rows.get(i); 154 for (Member member : row) { 155 html.append("<td nowrap class='rowheading'>").append( 156 member.getUniqueName()).append("</td>"); 157 } 158 for (int j = 0; j < columns.size(); j++) { 159 showCell(html,result.getCell(new int[]{j,i})); 160 } 161 html.append("</tr>"); 162 } 163 } else { 164 html.append("<tr>"); 165 for (int i = 0; i < columns.size(); i++) { 166 showCell(html,result.getCell(new int[]{i})); 167 } 168 html.append("</tr>"); 169 } 170 html.append("</table>"); 171 } catch (Throwable e) { 172 final String[] strings = Util.convertStackToString(e); 173 html.append("Error:<pre><blockquote>"); 174 for (String string : strings) { 175 StringEscaper.htmlEscaper.appendEscapedString(string, html); 176 } 177 html.append("</blockquote></pre>"); 178 } finally { 179 if (mdxConnection != null) { 180 mdxConnection.close(); 181 } 182 } 183 184 request.setAttribute("result", html.toString()); 185 response.setHeader("Content-Type", "text/html"); 186 getServletContext().getRequestDispatcher("/adhoc.jsp").include(request, response); 187 } 188 189 private void showCell(StringBuffer out, Cell cell) { 190 out.append("<td class='cell'>").append(cell.getFormattedValue()).append( 191 "</td>"); 192 } 193 private void processTransform(HttpServletRequest request, HttpServletResponse response) 194 throws ServletException, IOException { 195 String queryName = request.getParameter("query"); 196 ResultCache rc = ResultCache.getInstance(request.getSession(), getServletContext(), queryName); 197 Query query = rc.getQuery(); 198 query = query.safeClone(); 199 rc.setDirty(); 200 String operation = request.getParameter("operation"); 201 if (operation.equals("expand")) { 202 String memberName = request.getParameter("member"); 203 boolean fail = true; 204 Member member = query.getSchemaReader(true).getMemberByUniqueName( 205 Util.parseIdentifier(memberName), fail); 206 if (true) { 207 throw new UnsupportedOperationException( 208 "query.toggleDrillState(member) has been de-supported"); 209 } 210 } else { 211 throw Util.newInternal("unkown operation '" + operation + "'"); 212 } 213 rc.setQuery(query); 214 String redirect = request.getParameter("redirect"); 215 if (redirect == null) { 216 redirect = "/adhoc.jsp"; 217 } 218 response.setHeader("Content-Type", "text/html"); 219 getServletContext().getRequestDispatcher(redirect).include(request, response); 220 } 221 222 /** Handles the HTTP <code>GET</code> method. 223 * @param request servlet request 224 * @param response servlet response 225 */ 226 protected void doGet(HttpServletRequest request, HttpServletResponse response) 227 throws ServletException, java.io.IOException { 228 processRequest(request, response); 229 } 230 231 /** Handles the HTTP <code>POST</code> method. 232 * @param request servlet request 233 * @param response servlet response 234 */ 235 protected void doPost(HttpServletRequest request, HttpServletResponse response) 236 throws ServletException, java.io.IOException { 237 processRequest(request, response); 238 } 239 240 /** Returns a short description of the servlet. 241 */ 242 public String getServletInfo() { 243 return "Process an MDX query and return the result formatted as an HTML table"; 244 } 245 246 } 247 248 // End MDXQueryServlet.java