1 11 package com.tonbeller.jpivot.mondrian.script; 12 13 import groovy.lang.Binding; 14 import groovy.util.GroovyScriptEngine; 15 16 import java.io.InputStream ; 17 import java.net.URL ; 18 import java.sql.Connection ; 19 import java.sql.DriverManager ; 20 import java.sql.ResultSet ; 21 import java.sql.ResultSetMetaData ; 22 import java.sql.SQLException ; 23 import java.sql.Statement ; 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.List ; 27 import java.util.ListIterator ; 28 import java.util.Map ; 29 30 import javax.naming.Context ; 31 import javax.naming.InitialContext ; 32 import javax.naming.NamingException ; 33 import javax.sql.DataSource ; 34 35 import mondrian.rolap.RolapConnectionProperties; 36 37 import org.apache.commons.digester.Digester; 38 import org.apache.log4j.Logger; 39 40 import com.tonbeller.jpivot.mondrian.MondrianDrillThroughTableModel; 41 import com.tonbeller.wcf.table.AbstractTableModel; 42 import com.tonbeller.wcf.table.DefaultCell; 43 import com.tonbeller.wcf.table.DefaultTableRow; 44 import com.tonbeller.wcf.table.TableRow; 45 46 52 53 public class ScriptableMondrianDrillThroughTableModel extends AbstractTableModel { 54 private static Logger logger = Logger.getLogger(MondrianDrillThroughTableModel.class); 55 private String title = "Drill Through Table"; 56 private String caption = ""; 57 private String sql = ""; 58 private String jdbcUser; 59 private String jdbcUrl; 60 private String jdbcPassword; 61 private String jdbcDriver; 62 private String dataSourceName; 63 private String catalogExtension; 64 private int maxResults; 65 private String scriptRootUrl; 66 private List scripts = new ArrayList (); 67 private GroovyScriptEngine scriptEngine = null; 68 69 private DataSource dataSource; 70 private static Context jndiContext; 71 72 private boolean ready = false; 73 74 private TableRow[] rows = new TableRow[0]; 75 private String [] columnTitles = new String [0]; 76 77 public ScriptableMondrianDrillThroughTableModel() { 78 } 79 80 public int getRowCount() { 81 if (!ready) { 82 executeQuery(); 83 } 84 return rows.length; 85 } 86 87 public TableRow getRow(int rowIndex) { 88 if (!ready) { 89 executeQuery(); 90 } 91 return rows[rowIndex]; 92 } 93 94 public String getTitle() { 95 return title; 96 } 97 98 101 public String getSql() { 102 return sql; 103 } 104 105 108 public void setSql(String sql) { 109 this.sql = sql; 110 this.ready = false; 111 } 112 113 116 public void setTitle(String title) { 117 this.title = title; 118 } 119 120 125 public int getColumnCount() { 126 if (!ready) { 127 executeQuery(); 128 } 129 return columnTitles.length; 130 } 131 132 public String getColumnTitle(int columnIndex) { 133 if (!ready) { 134 executeQuery(); 135 } 136 return columnTitles[columnIndex]; 137 } 138 139 143 private void executeQuery() { 144 Connection con = null; 145 try { 146 InputStream catExtIs = ScriptableMondrianDrillThroughTableModel.class.getClassLoader().getResourceAsStream( 147 "/" + catalogExtension); 148 if (catExtIs != null) { 149 Digester catExtDigester = new Digester(); 150 catExtDigester.push(this); 151 catExtDigester.addSetProperties("extension"); 152 catExtDigester.addObjectCreate("extension/script", "com.tonbeller.jpivot.mondrian.script.ScriptColumn"); 153 catExtDigester.addSetProperties("extension/script"); 154 catExtDigester.addSetNext("extension/script", "addScript"); 155 catExtDigester.parse(catExtIs); 156 157 URL scriptsBaseURL = Thread.currentThread().getContextClassLoader().getResource(scriptRootUrl); 158 scriptEngine = new GroovyScriptEngine(new URL [] { scriptsBaseURL}); 159 } 160 con = getConnection(); 161 Statement s = con.createStatement(); 162 s.setMaxRows(maxResults); 163 ResultSet rs = s.executeQuery(sql); 164 ResultSetMetaData md = rs.getMetaData(); 165 int numCols = md.getColumnCount(); 166 List columnTitlesList = new ArrayList (); 167 for (int i = 0; i < numCols; i++) { 169 columnTitlesList.add(i, md.getColumnName(i + 1)); 171 } 172 for (ListIterator sIt = scripts.listIterator(); sIt.hasNext();) { 174 final ScriptColumn sc = (ScriptColumn) sIt.next(); 175 columnTitlesList.add(sc.getPosition() - 1, sc.getTitle()); 176 } 177 columnTitles = (String []) columnTitlesList.toArray(new String [0]); 178 List tempRows = new ArrayList (); 180 Map scriptInput = new HashMap (); 181 Binding binding = new Binding(); 182 while (rs.next()) { 183 List rowList = new ArrayList (); 184 scriptInput.clear(); 185 for (int i = 0; i < numCols; i++) { 187 rowList.add(i, rs.getObject(i + 1)); 188 scriptInput.put(columnTitles[i], rs.getObject(i + 1)); 189 } 190 binding.setVariable("input", scriptInput); 191 for (ListIterator sIt = scripts.listIterator(); sIt.hasNext();) { 193 final ScriptColumn sc = (ScriptColumn) sIt.next(); 194 scriptEngine.run(sc.getFile(), binding); 195 final Object output = binding.getVariable("output"); 196 if (output instanceof Map ) { 197 Map outMap = (Map ) output; 198 rowList 199 .add(sc.getPosition() - 1, new DefaultCell((String ) outMap.get("URL"), (String ) outMap.get("Value"))); 200 } else if (output instanceof String ) { 201 rowList.add(sc.getPosition() - 1, (String ) output); 202 } else { 203 throw new Exception ("Unknown groovy script return type (not a Map nor String)."); 204 } 205 } 206 tempRows.add(new DefaultTableRow(rowList.toArray())); 207 } 208 rs.close(); 209 rows = (TableRow[]) tempRows.toArray(new TableRow[0]); 210 } catch (Exception e) { 211 e.printStackTrace(); 212 logger.error("?", e); 213 rows = new TableRow[1]; 215 columnTitles = new String [1]; 216 columnTitles[0] = "An error occured"; 217 Object [] row = new Object [1]; 218 row[0] = e.toString(); 219 rows[0] = new DefaultTableRow(row); 220 ready = false; 221 return; 222 } finally { 223 try { 224 con.close(); 225 } catch (Exception e1) { 226 } 228 } 229 ready = true; 230 } 231 232 237 private Connection getConnection() throws SQLException { 238 if (dataSourceName == null) { 239 240 if (jdbcUrl == null) { throw new RuntimeException ("Mondrian Connect string '" + "' must contain either '" 241 + RolapConnectionProperties.Jdbc + "' or '" + RolapConnectionProperties.DataSource + "'"); } 242 return DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword); 243 } else { 244 return getDataSource().getConnection(); 245 } 246 } 247 248 private DataSource getDataSource() { 249 if (dataSource == null) { 250 try { 252 dataSource = (DataSource ) getJndiContext().lookup(dataSourceName); 253 } catch (NamingException e) { 254 throw new RuntimeException ("Error while looking up data source (" + dataSourceName + ")", e); 255 } 256 } 257 return dataSource; 258 } 259 260 private Context getJndiContext() throws NamingException { 261 if (jndiContext == null) { 262 jndiContext = new InitialContext (); 263 } 264 return jndiContext; 265 } 266 267 270 public String getJdbcDriver() { 271 return jdbcDriver; 272 } 273 274 277 public void setJdbcDriver(String jdbcDriver) { 278 this.jdbcDriver = jdbcDriver; 279 } 280 281 284 public String getJdbcPassword() { 285 return jdbcPassword; 286 } 287 288 291 public void setJdbcPassword(String jdbcPassword) { 292 this.jdbcPassword = jdbcPassword; 293 } 294 295 298 public String getJdbcUrl() { 299 return jdbcUrl; 300 } 301 302 305 public void setJdbcUrl(String jdbcUrl) { 306 this.jdbcUrl = jdbcUrl; 307 } 308 309 312 public String getJdbcUser() { 313 return jdbcUser; 314 } 315 316 319 public void setJdbcUser(String jdbcUser) { 320 this.jdbcUser = jdbcUser; 321 } 322 323 326 public String getCaption() { 327 return caption; 328 } 329 330 333 public void setCaption(String caption) { 334 this.caption = caption; 335 } 336 337 340 public String getDataSourceName() { 341 return dataSourceName; 342 } 343 344 347 public void setDataSourceName(String string) { 348 dataSourceName = string; 349 } 350 351 354 public String getCatalogExtension() { 355 return catalogExtension; 356 } 357 358 361 public void setCatalogExtension(String string) { 362 catalogExtension = string; 363 } 364 365 368 public int getMaxResults() { 369 return maxResults; 370 } 371 372 375 public void setMaxResults(int maxResults) { 376 this.maxResults = maxResults; 377 } 378 379 382 public List getScripts() { 383 return scripts; 384 } 385 386 389 public void setScripts(List scripts) { 390 this.scripts = scripts; 391 } 392 393 public void addScript(ScriptColumn column) { 394 this.scripts.add(column); 395 } 396 397 400 public String getScriptRootUrl() { 401 return scriptRootUrl; 402 } 403 404 407 public void setScriptRootUrl(String scriptRootUrl) { 408 this.scriptRootUrl = scriptRootUrl; 409 } 410 411 } 412 | Popular Tags |