KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jaspersoft > jasperserver > api > metadata > olap > service > impl > OlapConnectionServiceImpl


1 /****************************************************************
2  *
3  * JasperServer.
4  * All rights reserved.
5  * Copyright (C) 2005 JasperSoft Corporation
6  *
7  * JasperSoft Corporation
8  * 303 Second Street, Suite 450 North
9  * San Francisco, CA 94107
10  * http://www.jaspersoft.com
11  * $Id: OlapConnectionServiceImpl.java 4674 2006-09-22 19:22:43Z sbirney $
12  *
13  */

14
15 package com.jaspersoft.jasperserver.api.metadata.olap.service.impl;
16
17 import java.io.BufferedReader JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.InputStreamReader JavaDoc;
21 import java.net.URL JavaDoc;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 import com.jaspersoft.jasperserver.api.JSException;
27 import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
28 import com.jaspersoft.jasperserver.api.metadata.common.domain.Folder;
29 import com.jaspersoft.jasperserver.api.metadata.common.domain.client.FolderImpl;
30 import com.jaspersoft.jasperserver.api.metadata.common.domain.Resource;
31 import com.jaspersoft.jasperserver.api.metadata.common.domain.ResourceReference;
32 import com.jaspersoft.jasperserver.api.metadata.common.domain.FileResource;
33 import com.jaspersoft.jasperserver.api.metadata.common.domain.FileResourceData;
34 import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportDataSource;
35 import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.JdbcReportDataSource;
36 import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.JndiJdbcReportDataSource;
37 import com.jaspersoft.jasperserver.api.metadata.common.service.RepositoryService;
38
39 import com.jaspersoft.jasperserver.api.metadata.olap.domain.OlapClientConnection;
40 import com.jaspersoft.jasperserver.api.metadata.olap.domain.MondrianConnection;
41 import com.jaspersoft.jasperserver.api.metadata.olap.domain.OlapUnit;
42 import com.jaspersoft.jasperserver.api.metadata.olap.domain.XMLAConnection;
43 import com.jaspersoft.jasperserver.api.metadata.olap.service.OlapConnectionService;
44 import com.jaspersoft.jasperserver.api.common.domain.ValidationResult;
45 import com.jaspersoft.jasperserver.api.common.domain.impl.ValidationDetailImpl;
46 import com.jaspersoft.jasperserver.api.common.domain.impl.ValidationResultImpl;
47
48 import mondrian.rolap.RolapConnectionProperties;
49 import mondrian.olap.Util;
50 import mondrian.olap.DriverManager;
51
52 import com.tonbeller.jpivot.olap.model.OlapModel;
53 import com.tonbeller.jpivot.core.Model;
54 import com.tonbeller.jpivot.core.ModelFactory;
55 import com.tonbeller.jpivot.mondrian.MondrianModel;
56
57 import com.tonbeller.jpivot.tags.MondrianOlapModelTag;
58 import com.tonbeller.jpivot.xmla.XMLA_Model;
59 import com.tonbeller.jpivot.xmla.XMLA_OlapModelTag;
60
61 /**
62  * @author sbirney
63  */

64
65 public class OlapConnectionServiceImpl implements OlapConnectionService {
66
67     private static final Log log = LogFactory
68             .getLog(OlapConnectionServiceImpl.class);
69
70     /*
71      * (non-Javadoc)
72      *
73      * @see com.jaspersoft.jasperserver.api.metadata.olap.service.OlapConnectionService.createOlapModel()
74      *
75      * @return a newly constructed and configured OlapModel initialize is not
76      * yet called.
77      */

78     public OlapModel createOlapModel(ExecutionContext context, OlapUnit olapUnit) {
79         OlapClientConnection clientConn = (OlapClientConnection) dereference(
80                 context, olapUnit.getOlapClientConnection());
81         if (clientConn instanceof XMLAConnection) {
82             return createXmlaModel(context, olapUnit);
83         }
84         String JavaDoc mdx = olapUnit.getMdxQuery();
85         MondrianConnection conn = (MondrianConnection) clientConn;
86         /*
87          * FIXME Need to be able to configure the extensions
88          *
89          * URL url; if (config == null) url = getDefaultConfig(); else url =
90          * pageContext.getServletContext().getResource(config);
91          */

92         MondrianModel model = null;
93         try {
94             model = (MondrianModel) ModelFactory
95                     .instance(getDefaultMondrianConfig());
96         } catch (Exception JavaDoc e) {
97             throw new JSException(e);
98         }
99
100         model.setMdxQuery(mdx);
101         model.setConnectProperties(getMondrianConnectProperties(context, conn));
102
103         /*
104          * FIXME use of other values?
105          *
106          * mm.setDynresolver(cfg.getDynResolver());
107          * mm.setDynLocale(cfg.getDynLocale()); if
108          * ("false".equalsIgnoreCase(cfg.getConnectionPooling()))
109          * mm.setConnectionPooling(false);
110          * mm.setExternalDataSource(cfg.getExternalDataSource());
111          */

112         return model;
113     }
114
115     protected URL JavaDoc getDefaultMondrianConfig() {
116         return MondrianOlapModelTag.class
117                 .getResource("/com/tonbeller/jpivot/mondrian/config.xml");
118     }
119
120     protected URL JavaDoc getDefaultXMLAConfig() {
121         return XMLA_OlapModelTag.class.getResource("config.xml");
122     }
123
124     public OlapModel createXmlaModel(ExecutionContext context, OlapUnit xmlaUnit) {
125         String JavaDoc mdx = xmlaUnit.getMdxQuery();
126         XMLAConnection xmlaConn = (XMLAConnection) dereference(context,
127                 xmlaUnit.getOlapClientConnection());
128
129         URL JavaDoc url;
130         /*
131          * if (config == null) url = getClass().getResource("config.xml"); else
132          * url = pageContext.getServletContext().getResource(config);
133          */

134         url = getDefaultXMLAConfig();
135
136         // let Digester create a model from config input
137
// the config input stream MUST refer to the XMLA_Model class
138
// <model class="com.tonbeller.bii.xmla.XMLA_Model"> is required
139
Model model;
140         try {
141             model = ModelFactory.instance(url);
142         } catch (Exception JavaDoc e) {
143             throw new JSException(e);
144         }
145
146         if (!(model instanceof XMLA_Model))
147             throw new JSException(
148                     "invalid class attribute for model tag, resource="
149                             + getDefaultXMLAConfig());
150
151         XMLA_Model xmlaModel = (XMLA_Model) model;
152
153         xmlaModel.setCatalog(xmlaConn.getCatalog());
154         xmlaModel.setDataSource(xmlaConn.getDataSource());
155         xmlaModel.setMdxQuery(mdx);
156         xmlaModel.setID(xmlaConn.getCatalog() + "-" + xmlaUnit.hashCode()); // ???
157
xmlaModel.setUri(xmlaConn.getURI());
158         xmlaModel.setUser(xmlaConn.getUsername());
159         xmlaModel.setPassword(xmlaConn.getPassword());
160         return xmlaModel;
161     }
162
163     public ValidationResult validate(ExecutionContext context, OlapUnit unit) {
164         ValidationResultImpl result = new ValidationResultImpl();
165         validateMDX(context, result, unit);
166         // TODO: validate the datasource as well
167
return result;
168     }
169
170     protected void validateMDX(ExecutionContext context,
171             ValidationResultImpl result, OlapUnit unit) {
172         MondrianConnection resource = getConnectionResource(context, unit);
173         if (resource == null)
174             return;
175         try {
176             mondrian.olap.Connection monConnection = getMondrianConnection(
177                     context, resource);
178             monConnection.parseQuery(unit.getMdxQuery());
179         } catch (Exception JavaDoc e) {
180             ValidationDetailImpl detail = new ValidationDetailImpl();
181             detail.setValidationClass(OlapUnit.class);
182             detail.setName(unit.getName());
183             detail.setLabel(unit.getLabel());
184             detail.setResult(ValidationResult.STATE_ERROR);
185             detail.setException(e);
186             detail.setMessage(e.getMessage());
187             result.addValidationDetail(detail);
188             log.warn("Validation Failed for Olap Unit: " + unit.getName()
189                     + "\n" + e.getStackTrace());
190             log.error(e);
191             e.printStackTrace();
192         }
193
194     }
195
196     public MondrianConnection getConnection(ExecutionContext context,
197             String JavaDoc resourceName) {
198         return (MondrianConnection) getRepository().getResource(context,
199                 resourceName);
200     }
201
202     /*
203      * mondrianConnection
204      */

205     public MondrianConnection getConnectionResource(ExecutionContext context,
206             OlapUnit unit) {
207         Resource clientConn = dereference(context, unit
208                 .getOlapClientConnection());
209         if (clientConn instanceof MondrianConnection) {
210             return (MondrianConnection) clientConn;
211         }
212         if (clientConn instanceof XMLAConnection) {
213             // TODO: have to find the matching MondrianXMLADefinition (see
214
// XmlaHandlerImpl)
215
}
216         return null;
217     }
218
219     public mondrian.olap.Connection getMondrianConnection(
220             ExecutionContext context, String JavaDoc connResourceName) {
221         MondrianConnection conn = getConnection(context, connResourceName);
222         return getMondrianConnection(context, conn);
223     }
224
225     private mondrian.olap.Connection getMondrianConnection(
226             ExecutionContext context, MondrianConnection conn) {
227         Util.PropertyList connectProps = getMondrianConnectProperties(context,
228                 conn);
229         log.debug("CONNECT PROPS ARE: " + connectProps.toString());
230         return DriverManager.getConnection(connectProps, null, false);
231     }
232
233     public Util.PropertyList getMondrianConnectProperties(
234             ExecutionContext context, MondrianConnection conn) {
235         RepositoryService rep = getRepository();
236         // assemble a mondrian connection PropertyList
237
ReportDataSource dataSource = (ReportDataSource) dereference(context,
238                 conn.getDataSource());
239         FileResource schema = (FileResource) dereference(context, conn
240                 .getSchema());
241
242         Util.PropertyList connectProps = new Util.PropertyList();
243
244         connectProps.put(RolapConnectionProperties.Provider, "mondrian");
245
246         StringBuffer JavaDoc schemaString = new StringBuffer JavaDoc();
247         InputStream JavaDoc data;
248         if (schema.hasData()) {
249             data = schema.getDataStream();
250         } else {
251             log.debug("SCHEMA URI STRING = " + schema.getURIString());
252             FileResourceData resourceData = rep.getResourceData(context, schema
253                     .getURIString());
254             data = resourceData.getDataStream();
255         }
256
257         BufferedReader JavaDoc in = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(data));
258         String JavaDoc line;
259         try {
260             while ((line = in.readLine()) != null) {
261                 schemaString.append(line);
262             }
263         } catch (IOException JavaDoc e) {
264             throw new RuntimeException JavaDoc(e);
265         }
266         connectProps.put(RolapConnectionProperties.CatalogName, conn.getName());
267         // writing a DynamicSchemaProcessor looks like the way to update schema
268
// on the fly
269
connectProps.put(RolapConnectionProperties.DynamicSchemaProcessor,
270                 "NONE");
271         connectProps.put(RolapConnectionProperties.CatalogContent, schemaString
272                 .toString());
273         log.debug("CatalogContent is "
274                 + connectProps.get(RolapConnectionProperties.CatalogContent));
275
276         if (dataSource instanceof JdbcReportDataSource) {
277             JdbcReportDataSource jdbcDataSource = (JdbcReportDataSource) dataSource;
278             connectProps.put(RolapConnectionProperties.Jdbc, jdbcDataSource
279                     .getConnectionUrl());
280             String JavaDoc driverClassName = jdbcDataSource.getDriverClass();
281             connectProps.put(RolapConnectionProperties.JdbcDrivers,
282                     driverClassName);
283
284             try {
285                 // load the driver- it may not have been done, mondrian expects
286
// it
287
log.info("Loading jdbc driver: " + driverClassName);
288                 Class.forName(driverClassName);
289             } catch (ClassNotFoundException JavaDoc cnfe) {
290                 log.error("CANNOT LOAD DRIVER: " + driverClassName);
291             }
292
293             if (jdbcDataSource.getUsername() != null
294                     && jdbcDataSource.getUsername().trim().length() > 0) {
295                 connectProps.put(RolapConnectionProperties.JdbcUser,
296                         jdbcDataSource.getUsername());
297             }
298
299             if (jdbcDataSource.getPassword() != null
300                     && jdbcDataSource.getPassword().trim().length() > 0) {
301                 connectProps.put(RolapConnectionProperties.JdbcPassword,
302                         jdbcDataSource.getPassword());
303             }
304
305         } else {
306             // We have a JNDI data source
307
JndiJdbcReportDataSource jndiDataSource = (JndiJdbcReportDataSource) dataSource;
308             
309             String JavaDoc jndiURI = (jndiDataSource.getJndiName() != null && !jndiDataSource.getJndiName().startsWith("java:")) ?
310                                 "java:comp/env/" : "";
311             jndiURI = jndiURI + jndiDataSource.getJndiName();
312             connectProps.put(RolapConnectionProperties.DataSource,
313                     jndiURI);
314         }
315         // TODO get from web context and metadata
316
// + "RoleXX='California manager';";
317
return connectProps;
318     }
319
320     /* should something like this be part of the repository api? */
321     public Resource dereference(ExecutionContext context, ResourceReference ref) {
322         RepositoryService rep = getRepository();
323         if (ref.isLocal())
324             return ref.getLocalResource();
325         return rep
326                 .getResource(context, ref.getReferenceLookup().getURIString());
327     }
328
329     /**
330      * saveResource creates path of folders as necessary and put the resource in
331      * the bottommost folder does not update if the target already exists. maybe
332      * this can be added to the RepositoryService API?
333      */

334     public void saveResource(ExecutionContext context, String JavaDoc path,
335             Resource resource) {
336         RepositoryService rep = getRepository();
337
338         // check if the target already exists
339
String JavaDoc targetUri = path
340                 + (path.endsWith(Folder.SEPARATOR) ? "" : Folder.SEPARATOR)
341                 + resource.getName();
342         Resource targetResource = rep.getResource(context, targetUri);
343         if (targetResource != null) {
344             return;
345         }
346
347         Folder folder = mkdirs(context, path);
348         resource.setParentFolder(folder);
349         rep.saveResource(context, resource);
350     }
351
352     public Folder mkdirs(ExecutionContext context, String JavaDoc path) {
353         RepositoryService rep = getRepository();
354
355         // travel down the elements of the path
356
String JavaDoc[] splitPath = path.split(Folder.SEPARATOR);
357         String JavaDoc folderName = ""; // start with root
358
Folder parentFolder = null; // root's parent is null
359
Folder folder = rep.getFolder(context, folderName);
360         for (int i = 0; i < splitPath.length; i++) {
361             log.debug("Current path element is " + splitPath[i]);
362             if ("".equals(splitPath[i])) {
363                 continue; // ignore extra slashes
364
}
365             log.debug("Folder name '" + folderName + "' yields folder '"
366                     + folder + "'");
367             folderName += ("/" + splitPath[i]);
368             parentFolder = folder; // remember parent
369
folder = rep.getFolder(context, folderName);
370             if (folder == null) {
371                 folder = new FolderImpl();
372                 folder.setName(splitPath[i]);
373                 folder.setLabel(splitPath[i]);
374                 folder.setDescription(splitPath[i] + " folder");
375                 folder.setParentFolder(parentFolder);
376                 rep.saveFolder(context, folder);
377             }
378         }
379         log.debug("Folder name '" + folderName + "' yields folder '" + folder
380                 + "'");
381         return folder;
382     }
383
384     // PROPERTIES
385

386     private RepositoryService mRepository;
387
388     public RepositoryService getRepository() {
389         return mRepository;
390     }
391
392     public void setRepository(RepositoryService repository) {
393         mRepository = repository;
394     }
395
396 }
397
Popular Tags