1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 package com.sun.star.report.pentaho; 24 25 import com.sun.star.beans.NamedValue; 26 import com.sun.star.beans.PropertyVetoException; 27 import com.sun.star.beans.UnknownPropertyException; 28 import com.sun.star.beans.XPropertyChangeListener; 29 import com.sun.star.beans.XPropertySet; 30 import com.sun.star.beans.XVetoableChangeListener; 31 import com.sun.star.container.XChild; 32 import com.sun.star.embed.XStorage; 33 import com.sun.star.frame.XModel; 34 import com.sun.star.lang.IllegalArgumentException; 35 import com.sun.star.lang.WrappedTargetException; 36 import com.sun.star.lang.XInitialization; 37 import com.sun.star.lang.XServiceInfo; 38 import com.sun.star.lang.XSingleComponentFactory; 39 import com.sun.star.lib.uno.helper.Factory; 40 import com.sun.star.lib.uno.helper.PropertySetMixin; 41 import com.sun.star.lib.uno.helper.WeakBase; 42 import com.sun.star.registry.InvalidRegistryException; 43 import com.sun.star.registry.InvalidValueException; 44 import com.sun.star.registry.XRegistryKey; 45 import com.sun.star.registry.XSimpleRegistry; 46 import com.sun.star.report.DataSourceFactory; 47 import com.sun.star.report.JobProperties; 48 import com.sun.star.report.ReportEngineParameterNames; 49 import com.sun.star.report.ReportExecutionException; 50 import com.sun.star.report.ReportJob; 51 import com.sun.star.report.ReportJobDefinition; 52 import com.sun.star.report.ReportJobFactory; 53 import com.sun.star.report.SDBCReportDataFactory; 54 import com.sun.star.report.SOImageService; 55 import com.sun.star.report.StorageRepository; 56 import com.sun.star.report.XReportDefinition; 57 import com.sun.star.sdb.XDocumentDataSource; 58 import com.sun.star.sdbc.XConnection; 59 import com.sun.star.sdbc.XRowSet; 60 import com.sun.star.task.XJob; 61 import com.sun.star.uno.Exception; 62 import com.sun.star.uno.Type; 63 import com.sun.star.uno.UnoRuntime; 64 import com.sun.star.uno.XComponentContext; 65 66 import java.util.logging.Level; 67 import java.util.logging.Logger; 68 69 import org.apache.commons.logging.Log; 70 import org.apache.commons.logging.LogFactory; 71 72 /** 73 * This class capsulates the class, that implements the minimal component, a factory for creating the service 74 * (<CODE>__getComponentFactory</CODE>) and a method, that writes the information into the given registry key 75 * (<CODE>__writeRegistryServiceInfo</CODE>). 76 */ 77 public class SOReportJobFactory 78 { 79 SOReportJobFactory()80 private SOReportJobFactory() 81 { 82 } 83 84 public static class _SOReportJobFactory extends WeakBase implements XInitialization, XServiceInfo, XJob, XPropertySet, ReportJobFactory 85 { 86 87 private static final Log LOGGER = LogFactory.getLog(_SOReportJobFactory.class); 88 /** 89 * The service name, that must be used to get an instance of this service. 90 */ 91 private static final String __serviceName = 92 "com.sun.star.report.pentaho.SOReportJobFactory"; 93 private final PropertySetMixin m_prophlp; 94 /** 95 * The initial component contextr, that gives access to the service manager, supported singletons, ... It's 96 * often later used 97 */ 98 private final XComponentContext m_cmpCtx; 99 private XConnection activeConnection; 100 private XReportDefinition report; 101 _SOReportJobFactory(final XComponentContext xCompContext)102 public _SOReportJobFactory(final XComponentContext xCompContext) 103 { 104 m_cmpCtx = xCompContext; 105 m_prophlp = new PropertySetMixin(m_cmpCtx, this, 106 new Type(XJob.class), 107 null); // no optionals 108 } 109 110 /** 111 * This method is a member of the interface for initializing an object directly after its creation. 112 * 113 * @param object This array of arbitrary objects will be passed to the component after its creation. 114 * @throws Exception Every exception will not be handled, but will be passed to the caller. 115 */ initialize(final Object[] object)116 public void initialize(final Object[] object) 117 throws com.sun.star.uno.Exception 118 { 119 /* The component describes what arguments its expected and in which 120 * order!At this point you can read the objects and can intialize 121 * your component using these objects. 122 */ 123 } 124 125 /** 126 * This method returns an array of all supported service names. 127 * 128 * @return Array of supported service names. 129 */ getSupportedServiceNames()130 public String[] getSupportedServiceNames() 131 { 132 return getServiceNames(); 133 } 134 135 /** 136 * This method is a simple helper function to used in the static component initialisation functions as well as 137 * in getSupportedServiceNames. 138 * @return 139 */ getServiceNames()140 public static String[] getServiceNames() 141 { 142 return new String[] 143 { 144 __serviceName 145 }; 146 } 147 148 /** 149 * This method returns true, if the given service will be supported by the component. 150 * 151 * @param sServiceName Service name. 152 * @return True, if the given service name will be supported. 153 */ supportsService(final String sServiceName)154 public boolean supportsService(final String sServiceName) 155 { 156 return sServiceName.equals(__serviceName); 157 } 158 159 /** 160 * Return the class name of the component. 161 * 162 * @return Class name of the component. 163 */ getImplementationName()164 public String getImplementationName() 165 { 166 return SOReportJobFactory.class.getName(); 167 } 168 getLocaleFromRegistry(final XSimpleRegistry simpleReg, final String path, final String value)169 private String getLocaleFromRegistry(final XSimpleRegistry simpleReg, final String path, final String value) 170 { 171 String currentLocale = null; 172 try 173 { 174 simpleReg.open(path, true, false); 175 final XRegistryKey xRegistryRootKey = simpleReg.getRootKey(); 176 // read locale 177 final XRegistryKey locale = xRegistryRootKey.openKey(value); 178 if (locale != null) 179 { 180 final String newLocale = locale.getStringValue(); 181 if (newLocale != null) 182 { 183 currentLocale = newLocale.replace('-', '_'); 184 } 185 } 186 } 187 catch (InvalidValueException ex) 188 { 189 Logger.getLogger(SOReportJobFactory.class.getName()).log(Level.SEVERE, null, ex); 190 } 191 catch (InvalidRegistryException ex) 192 { 193 Logger.getLogger(SOReportJobFactory.class.getName()).log(Level.SEVERE, null, ex); 194 } 195 196 return currentLocale; 197 } 198 execute(final NamedValue[] namedValue)199 public Object execute(final NamedValue[] namedValue) 200 throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception 201 { 202 final ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader(); 203 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); 204 try 205 { 206 final XSimpleRegistry simpleReg = (XSimpleRegistry) UnoRuntime.queryInterface(XSimpleRegistry.class, 207 m_cmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.configuration.ConfigurationRegistry", m_cmpCtx)); 208 209 String currentLocale = getLocaleFromRegistry(simpleReg, "org.openoffice.Setup", "L10N/ooSetupSystemLocale"); 210 if (currentLocale == null || "".equals(currentLocale)) 211 { 212 currentLocale = getLocaleFromRegistry(simpleReg, "org.openoffice.Office.Linguistic", "General/DefaultLocale"); 213 } 214 if (currentLocale != null && !"".equals(currentLocale)) 215 { 216 System.setProperty("org.pentaho.reporting.libraries.formula.locale", currentLocale); 217 } 218 final ReportJob job = createReportJob(namedValue); 219 job.execute(); 220 221 } 222 catch (java.lang.Exception e) 223 { 224 LOGGER.error("ReportProcessing failed", e); 225 throw new com.sun.star.lang.WrappedTargetException(e.getMessage(), this, null); 226 } 227 catch (java.lang.IncompatibleClassChangeError e2) 228 { 229 LOGGER.error("Detected an IncompatibleClassChangeError"); 230 throw new com.sun.star.lang.WrappedTargetException("caught a " + e2.getClass().getName(), this, new com.sun.star.uno.Exception(e2.getLocalizedMessage())); 231 } 232 Thread.currentThread().setContextClassLoader(cl); 233 234 return null; 235 } 236 createReportJob(final NamedValue[] namedValue)237 public ReportJob createReportJob(final NamedValue[] namedValue) throws IllegalArgumentException, ReportExecutionException, Exception 238 { 239 XStorage input = null; 240 XStorage output = null; 241 XRowSet rowSet = null; 242 String mimetype = null; 243 String author = null; 244 String title = null; 245 Integer maxRows = null; 246 247 for (int i = 0; i < namedValue.length; ++i) 248 { 249 final NamedValue aProps = namedValue[i]; 250 if ("ActiveConnection".equalsIgnoreCase(aProps.Name)) 251 { 252 activeConnection = (XConnection) UnoRuntime.queryInterface(XConnection.class, aProps.Value); 253 } 254 else if ("ReportDefinition".equalsIgnoreCase(aProps.Name)) 255 { 256 report = (XReportDefinition) UnoRuntime.queryInterface(XReportDefinition.class, aProps.Value); 257 } 258 else if ("InputStorage".equalsIgnoreCase(aProps.Name)) 259 { 260 input = (XStorage) UnoRuntime.queryInterface(XStorage.class, aProps.Value); 261 } 262 else if ("OutputStorage".equalsIgnoreCase(aProps.Name)) 263 { 264 output = (XStorage) UnoRuntime.queryInterface(XStorage.class, aProps.Value); 265 } 266 else if ("RowSet".equalsIgnoreCase(aProps.Name)) 267 { 268 rowSet = (XRowSet) UnoRuntime.queryInterface(XRowSet.class, aProps.Value); 269 } 270 else if ("mimetype".equalsIgnoreCase(aProps.Name)) 271 { 272 mimetype = (String) aProps.Value; 273 } 274 else if ("MaxRows".equalsIgnoreCase(aProps.Name)) 275 { 276 maxRows = (Integer) aProps.Value; 277 } 278 else if (ReportEngineParameterNames.AUTHOR.equalsIgnoreCase(aProps.Name)) 279 { 280 author = (String) aProps.Value; 281 } 282 else if (ReportEngineParameterNames.TITLE.equalsIgnoreCase(aProps.Name)) 283 { 284 title = (String) aProps.Value; 285 } 286 } 287 288 if (input == null || output == null) 289 { 290 throw new com.sun.star.lang.IllegalArgumentException(); 291 } 292 293 if (rowSet == null) 294 { 295 if (report == null || activeConnection == null) 296 { 297 throw new com.sun.star.lang.IllegalArgumentException(); 298 } 299 mimetype = report.getMimeType(); 300 } 301 else 302 { 303 final XPropertySet set = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, rowSet); 304 if (set == null) 305 { 306 throw new com.sun.star.lang.IllegalArgumentException(); 307 } 308 activeConnection = (XConnection) UnoRuntime.queryInterface(XConnection.class, set.getPropertyValue("ActiveConnection")); 309 } 310 if (mimetype == null) 311 { 312 mimetype = PentahoReportEngineMetaData.OPENDOCUMENT_TEXT; 313 } 314 315 final XChild child = UnoRuntime.queryInterface(XChild.class, activeConnection); 316 final XDocumentDataSource docSource = UnoRuntime.queryInterface(XDocumentDataSource.class, child.getParent()); 317 final XModel model = UnoRuntime.queryInterface(XModel.class, docSource.getDatabaseDocument()); 318 final DataSourceFactory dataFactory = new SDBCReportDataFactory(m_cmpCtx, activeConnection); 319 final StorageRepository storageRepository = new StorageRepository(input, output, model.getURL()); 320 321 final String inputName = "content.xml"; 322 final String outputName = "content.xml"; 323 324 final PentahoReportEngine engine = new PentahoReportEngine(); 325 final ReportJobDefinition definition = engine.createJobDefinition(); 326 final JobProperties procParms = definition.getProcessingParameters(); 327 procParms.setProperty(ReportEngineParameterNames.INPUT_REPOSITORY, storageRepository); 328 procParms.setProperty(ReportEngineParameterNames.OUTPUT_REPOSITORY, storageRepository); 329 procParms.setProperty(ReportEngineParameterNames.INPUT_NAME, inputName); 330 procParms.setProperty(ReportEngineParameterNames.OUTPUT_NAME, outputName); 331 procParms.setProperty(ReportEngineParameterNames.CONTENT_TYPE, mimetype); 332 procParms.setProperty(ReportEngineParameterNames.INPUT_DATASOURCE_FACTORY, dataFactory); 333 procParms.setProperty(ReportEngineParameterNames.IMAGE_SERVICE, new SOImageService(m_cmpCtx)); 334 procParms.setProperty(ReportEngineParameterNames.INPUT_REPORTJOB_FACTORY, this); 335 procParms.setProperty(ReportEngineParameterNames.MAXROWS, maxRows); 336 if (author != null) 337 { 338 procParms.setProperty(ReportEngineParameterNames.AUTHOR, author); 339 } 340 if (title != null) 341 { 342 procParms.setProperty(ReportEngineParameterNames.TITLE, title); 343 } 344 345 return engine.createJob(definition); 346 } 347 348 // com.sun.star.beans.XPropertySet: getPropertySetInfo()349 public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() 350 { 351 return m_prophlp.getPropertySetInfo(); 352 } 353 setPropertyValue(final String aPropertyName, final Object aValue)354 public void setPropertyValue(final String aPropertyName, final Object aValue) 355 throws UnknownPropertyException, PropertyVetoException, com.sun.star.lang.IllegalArgumentException, 356 WrappedTargetException 357 { 358 m_prophlp.setPropertyValue(aPropertyName, aValue); 359 } 360 getPropertyValue(final String aPropertyName)361 public Object getPropertyValue(final String aPropertyName) 362 throws UnknownPropertyException, WrappedTargetException 363 { 364 return m_prophlp.getPropertyValue(aPropertyName); 365 } 366 addPropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener)367 public void addPropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener) 368 throws UnknownPropertyException, WrappedTargetException 369 { 370 m_prophlp.addPropertyChangeListener(aPropertyName, xListener); 371 } 372 removePropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener)373 public void removePropertyChangeListener(final String aPropertyName, final XPropertyChangeListener xListener) 374 throws UnknownPropertyException, WrappedTargetException 375 { 376 m_prophlp.removePropertyChangeListener(aPropertyName, xListener); 377 } 378 addVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener)379 public void addVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener) 380 throws UnknownPropertyException, WrappedTargetException 381 { 382 m_prophlp.addVetoableChangeListener(aPropertyName, xListener); 383 } 384 removeVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener)385 public void removeVetoableChangeListener(final String aPropertyName, final XVetoableChangeListener xListener) 386 throws UnknownPropertyException, WrappedTargetException 387 { 388 m_prophlp.removeVetoableChangeListener(aPropertyName, xListener); 389 } 390 } 391 392 /** 393 * Gives a factory for creating the service. This method is called by the <code>JavaLoader</code> 394 * <p/> 395 * 396 * @param sImplName the name of the implementation for which a service is desired 397 * @return returns a <code>XSingleComponentFactory</code> for creating the component 398 * @see com.sun.star.comp.loader.JavaLoader 399 */ __getComponentFactory(final String sImplName)400 public static XSingleComponentFactory __getComponentFactory(final String sImplName) 401 { 402 XSingleComponentFactory xFactory = null; 403 404 try 405 { 406 if (sImplName.equals(_SOReportJobFactory.class.getName())) 407 { 408 xFactory = Factory.createComponentFactory(_SOReportJobFactory.class, _SOReportJobFactory.getServiceNames()); 409 } 410 else if (sImplName.equals(SOFunctionManager.class.getName())) 411 { 412 xFactory = Factory.createComponentFactory(SOFunctionManager.class, SOFunctionManager.getServiceNames()); 413 } 414 else if (sImplName.equals(SOFormulaParser.class.getName())) 415 { 416 xFactory = Factory.createComponentFactory(SOFormulaParser.class, SOFormulaParser.getServiceNames()); 417 } 418 } 419 catch (java.lang.IncompatibleClassChangeError e2) 420 { 421 } 422 423 return xFactory; 424 } 425 426 /** 427 * Writes the service information into the given registry key. This method is called by the <code>JavaLoader</code> 428 * <p/> 429 * 430 * @param regKey the registryKey 431 * @return returns true if the operation succeeded 432 * @see com.sun.star.comp.loader.JavaLoader 433 */ __writeRegistryServiceInfo(final XRegistryKey regKey)434 public static boolean __writeRegistryServiceInfo(final XRegistryKey regKey) 435 { 436 return Factory.writeRegistryServiceInfo(SOFunctionManager.class.getName(), 437 SOFunctionManager.getServiceNames(), 438 regKey) && Factory.writeRegistryServiceInfo(_SOReportJobFactory.class.getName(), 439 _SOReportJobFactory.getServiceNames(), 440 regKey) && Factory.writeRegistryServiceInfo(SOFormulaParser.class.getName(), 441 SOFormulaParser.getServiceNames(), 442 regKey); 443 } 444 } 445