1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package com.sun.star.comp.loader; 29 30 31 import java.lang.reflect.Constructor; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.InvocationTargetException; 34 35 import com.sun.star.uno.XComponentContext; 36 import com.sun.star.lang.XInitialization; 37 import com.sun.star.lang.XMultiServiceFactory; 38 import com.sun.star.lang.XServiceInfo; 39 import com.sun.star.lang.XSingleServiceFactory; 40 import com.sun.star.lang.XSingleComponentFactory; 41 import com.sun.star.lang.XTypeProvider; 42 43 import com.sun.star.registry.XRegistryKey; 44 45 import com.sun.star.uno.UnoRuntime; 46 import com.sun.star.uno.Type; 47 48 49 /** 50 * The purpose of this class to help component implementation. 51 * This class has default implementations for <code>getServiceFactory</code> 52 * and <code>writeRegistryServiceInfo</code>. 53 * <p> 54 * @version $Revision: 1.9 $ $ $Date: 2008-04-11 11:10:09 $ 55 * @author Kay Ramme 56 * @see com.sun.star.lang.XMultiServiceFactory 57 * @see com.sun.star.lang.XServiceInfo 58 * @see com.sun.star.lang.XSingleServiceFactory 59 * @see com.sun.star.registry.XRegistryKey 60 * @since UDK1.0 61 */ 62 public class FactoryHelper { 63 64 private static final boolean DEBUG = false; 65 // the factory 66 static protected class Factory 67 implements XSingleServiceFactory, XSingleComponentFactory, XServiceInfo, 68 XTypeProvider { 69 protected static Class __objectArray; 70 71 static { 72 try { 73 __objectArray = Class.forName("[Ljava.lang.Object;"); 74 } 75 catch(ClassNotFoundException classNotFoundException) { 76 System.err.println(FactoryHelper.class.getName() + " exception occurred - " + classNotFoundException); 77 } 78 } 79 80 // private static final boolean DEBUG = false; 81 82 protected XMultiServiceFactory _xMultiServiceFactory; 83 protected XRegistryKey _xRegistryKey; 84 protected int _nCode; 85 protected Constructor _constructor; 86 protected String _implName; 87 protected String _serviceName; 88 // keeps the Id for XTypeProvider 89 protected static Object _mutex= new Object(); 90 private static byte[] _implementationId; 91 92 protected Factory(Class implClass, 93 String serviceName, 94 XMultiServiceFactory xMultiServiceFactory, 95 XRegistryKey xRegistryKey) 96 { 97 _xMultiServiceFactory = xMultiServiceFactory; 98 _xRegistryKey = xRegistryKey; 99 _implName = implClass.getName(); 100 _serviceName = serviceName; 101 102 Constructor constructors[] = implClass.getConstructors(); 103 for(int i = 0; i < constructors.length && _constructor == null; ++i) { 104 Class parameters[] = constructors[i].getParameterTypes(); 105 106 if(parameters.length == 3 107 && parameters[0].equals(XComponentContext.class) 108 && parameters[1].equals(XRegistryKey.class) 109 && parameters[2].equals(__objectArray)) { 110 _nCode = 0; 111 _constructor = constructors[i]; 112 } 113 else if(parameters.length == 2 114 && parameters[0].equals(XComponentContext.class) 115 && parameters[1].equals(XRegistryKey.class)) { 116 _nCode = 1; 117 _constructor = constructors[i]; 118 } 119 else if(parameters.length == 2 120 && parameters[0].equals(XComponentContext.class) 121 && parameters[1].equals(__objectArray)) { 122 _nCode = 2; 123 _constructor = constructors[i]; 124 } 125 else if(parameters.length == 1 126 && parameters[0].equals(XComponentContext.class)) { 127 _nCode = 3; 128 _constructor = constructors[i]; 129 } 130 // depr 131 else if(parameters.length == 3 132 && parameters[0].equals(XMultiServiceFactory.class) 133 && parameters[1].equals(XRegistryKey.class) 134 && parameters[2].equals(__objectArray)) { 135 _nCode = 4; 136 _constructor = constructors[i]; 137 } 138 else if(parameters.length == 2 139 && parameters[0].equals(XMultiServiceFactory.class) 140 && parameters[1].equals(XRegistryKey.class)) { 141 _nCode = 5; 142 _constructor = constructors[i]; 143 } 144 else if(parameters.length == 2 145 && parameters[0].equals(XMultiServiceFactory.class) 146 && parameters[1].equals(__objectArray)) { 147 _nCode = 6; 148 _constructor = constructors[i]; 149 } 150 else if(parameters.length == 1 151 && parameters[0].equals(XMultiServiceFactory.class)) { 152 _nCode = 7; 153 _constructor = constructors[i]; 154 } 155 else if(parameters.length == 1 156 && parameters[0].equals(__objectArray)) { 157 _nCode = 8; 158 _constructor = constructors[i]; 159 } 160 else if(parameters.length == 0) { 161 _nCode = 9; 162 _constructor = constructors[i]; 163 } 164 } 165 166 if(_constructor == null) // have not found a useable constructor 167 throw new com.sun.star.uno.RuntimeException(getClass().getName() + " can not find a useable constructor"); 168 } 169 170 private final XMultiServiceFactory getSMgr( XComponentContext xContext ) 171 { 172 if (xContext != null) 173 { 174 return UnoRuntime.queryInterface( 175 XMultiServiceFactory.class, xContext.getServiceManager() ); 176 } 177 else 178 { 179 return _xMultiServiceFactory; 180 } 181 } 182 183 // XComponentContext impl 184 //______________________________________________________________________________________________ 185 public Object createInstanceWithContext( 186 XComponentContext xContext ) 187 throws com.sun.star.uno.Exception 188 { 189 Object args[]; 190 switch (_nCode) 191 { 192 case 0: 193 args = new Object [] { xContext, _xRegistryKey, new Object[ 0 ] }; 194 break; 195 case 1: 196 args = new Object [] { xContext, _xRegistryKey }; 197 break; 198 case 2: 199 args = new Object [] { xContext, new Object[ 0 ] }; 200 break; 201 case 3: 202 args = new Object [] { xContext }; 203 break; 204 case 4: 205 args = new Object [] { getSMgr( xContext ), _xRegistryKey, new Object[ 0 ] }; 206 break; 207 case 5: 208 args = new Object [] { getSMgr( xContext ), _xRegistryKey }; 209 break; 210 case 6: 211 args = new Object [] { getSMgr( xContext ), new Object[ 0 ] }; 212 break; 213 case 7: 214 args = new Object [] { getSMgr( xContext ) }; 215 break; 216 case 8: 217 args = new Object [] { new Object[ 0 ] }; 218 break; 219 default: 220 args = new Object [ 0 ]; 221 break; 222 } 223 224 try 225 { 226 return _constructor.newInstance( args ); 227 } 228 catch (InvocationTargetException invocationTargetException) 229 { 230 Throwable targetException = invocationTargetException.getTargetException(); 231 232 if (targetException instanceof java.lang.RuntimeException) 233 throw (java.lang.RuntimeException)targetException; 234 else if (targetException instanceof com.sun.star.uno.Exception) 235 throw (com.sun.star.uno.Exception)targetException; 236 else if (targetException instanceof com.sun.star.uno.RuntimeException) 237 throw (com.sun.star.uno.RuntimeException)targetException; 238 else 239 throw new com.sun.star.uno.Exception( targetException.toString() ); 240 } 241 catch (IllegalAccessException illegalAccessException) 242 { 243 throw new com.sun.star.uno.Exception( illegalAccessException.toString() ); 244 } 245 catch (InstantiationException instantiationException) 246 { 247 throw new com.sun.star.uno.Exception( instantiationException.toString() ); 248 } 249 } 250 //______________________________________________________________________________________________ 251 public Object createInstanceWithArgumentsAndContext( 252 Object rArguments[], XComponentContext xContext ) 253 throws com.sun.star.uno.Exception 254 { 255 Object args[]; 256 257 boolean bInitCall = true; 258 switch (_nCode) 259 { 260 case 0: 261 args = new Object [] { xContext, _xRegistryKey, rArguments }; 262 bInitCall = false; 263 break; 264 case 1: 265 args = new Object [] { xContext, _xRegistryKey }; 266 break; 267 case 2: 268 args = new Object [] { xContext, rArguments }; 269 bInitCall = false; 270 break; 271 case 3: 272 args = new Object [] { xContext }; 273 break; 274 case 4: 275 args = new Object [] { getSMgr( xContext ), _xRegistryKey, rArguments }; 276 bInitCall = false; 277 break; 278 case 5: 279 args = new Object [] { getSMgr( xContext ), _xRegistryKey }; 280 break; 281 case 6: 282 args = new Object [] { getSMgr( xContext ), rArguments }; 283 bInitCall = false; 284 break; 285 case 7: 286 args = new Object [] { getSMgr( xContext ) }; 287 break; 288 case 8: 289 args = new Object [] { rArguments }; 290 bInitCall = false; 291 break; 292 default: 293 args = new Object [ 0 ]; 294 break; 295 } 296 297 try 298 { 299 Object instance = _constructor.newInstance( args ); 300 if (bInitCall) 301 { 302 XInitialization xInitialization = UnoRuntime.queryInterface( 303 XInitialization.class, instance ); 304 if (xInitialization != null) 305 { 306 xInitialization.initialize( rArguments ); 307 } 308 } 309 return instance; 310 } 311 catch (InvocationTargetException invocationTargetException) 312 { 313 Throwable targetException = invocationTargetException.getTargetException(); 314 315 if (targetException instanceof java.lang.RuntimeException) 316 throw (java.lang.RuntimeException)targetException; 317 else if (targetException instanceof com.sun.star.uno.Exception) 318 throw (com.sun.star.uno.Exception)targetException; 319 else if (targetException instanceof com.sun.star.uno.RuntimeException) 320 throw (com.sun.star.uno.RuntimeException)targetException; 321 else 322 throw new com.sun.star.uno.Exception( targetException.toString() ); 323 } 324 catch (IllegalAccessException illegalAccessException) 325 { 326 throw new com.sun.star.uno.Exception( illegalAccessException.toString() ); 327 } 328 catch (InstantiationException instantiationException) 329 { 330 throw new com.sun.star.uno.Exception( instantiationException.toString() ); 331 } 332 } 333 334 /** 335 * Creates an instance of the desired service. 336 * <p> 337 * @return returns an instance of the desired service 338 * @see com.sun.star.lang.XSingleServiceFactory 339 */ 340 public Object createInstance() 341 throws com.sun.star.uno.Exception, 342 com.sun.star.uno.RuntimeException 343 { 344 return createInstanceWithContext( null ); 345 } 346 347 /** 348 * Creates an instance of the desired service. 349 * <p> 350 * @return returns an instance of the desired service 351 * @param args the args given to the constructor of the service 352 * @see com.sun.star.lang.XSingleServiceFactory 353 */ 354 public Object createInstanceWithArguments(Object[] args) 355 throws com.sun.star.uno.Exception, 356 com.sun.star.uno.RuntimeException 357 { 358 return createInstanceWithArgumentsAndContext( args, null ); 359 } 360 361 /** 362 * Gives the supported services 363 * <p> 364 * @return returns an array of supported services 365 * @see com.sun.star.lang.XServiceInfo 366 */ 367 public String[] getSupportedServiceNames() throws com.sun.star.uno.RuntimeException { 368 return new String[]{_serviceName}; 369 } 370 371 /** 372 * Gives the implementation name 373 * <p> 374 * @return returns the implementation name 375 * @see com.sun.star.lang.XServiceInfo 376 */ 377 public String getImplementationName() throws com.sun.star.uno.RuntimeException { 378 return _implName; 379 } 380 381 /** 382 * Indicates if the given service is supported. 383 * <p> 384 * @return returns true if the given service is supported 385 * @see com.sun.star.lang.XServiceInfo 386 */ 387 public boolean supportsService(String serviceName) throws com.sun.star.uno.RuntimeException { 388 String services[] = getSupportedServiceNames(); 389 390 boolean found = false; 391 392 for(int i = 0; i < services.length && !found; ++i) 393 found = services[i].equals(serviceName); 394 395 return found; 396 } 397 398 //XTypeProvider 399 public byte[] getImplementationId() 400 { 401 synchronized (_mutex) 402 { 403 if (_implementationId == null) 404 { 405 int hash = hashCode(); 406 String sName= getClass().getName(); 407 byte[] arName= sName.getBytes(); 408 int nNameLength= arName.length; 409 410 _implementationId= new byte[ 4 + nNameLength]; 411 _implementationId[0]= (byte)(hash & 0xff); 412 _implementationId[1]= (byte)((hash >>> 8) & 0xff); 413 _implementationId[2]= (byte)((hash >>> 16) & 0xff); 414 _implementationId[3]= (byte)((hash >>>24) & 0xff); 415 416 System.arraycopy(arName, 0, _implementationId, 4, nNameLength); 417 } 418 } 419 return _implementationId; 420 } 421 //XTypeProvider 422 public com.sun.star.uno.Type[] getTypes() 423 { 424 Type[] t = new Type[] { 425 new Type(XSingleServiceFactory.class), 426 new Type(XSingleComponentFactory.class), 427 new Type(XServiceInfo.class), 428 new Type(XTypeProvider.class) 429 }; 430 return t; 431 } 432 433 } 434 435 /** 436 * Creates a factory for the given class. 437 * <p> 438 * @deprecated as of UDK 1.0 439 * <p> 440 * @return returns a factory 441 * @param implClass the implementing class 442 * @param multiFactory the given multi service factory (service manager) 443 * @param regKey the given registry key 444 * @see com.sun.star.lang.XServiceInfo 445 */ 446 static public XSingleServiceFactory getServiceFactory(Class implClass, 447 XMultiServiceFactory multiFactory, 448 XRegistryKey regKey) 449 { 450 XSingleServiceFactory xSingleServiceFactory = null; 451 452 try { 453 Field serviceName ; 454 455 try { 456 serviceName = implClass.getField("__serviceName"); 457 } 458 catch(NoSuchFieldException noSuchFieldExceptio) { 459 serviceName = implClass.getField("serviceName"); // old style 460 } 461 462 xSingleServiceFactory = new Factory(implClass, (String)serviceName.get(null), multiFactory, regKey); 463 } 464 catch(NoSuchFieldException noSuchFieldException) { 465 System.err.println("##### FactoryHelper.getServiceFactory - exception:" + noSuchFieldException); 466 } 467 catch(IllegalAccessException illegalAccessException) { 468 System.err.println("##### FactoryHelper.getServiceFactory - exception:" + illegalAccessException); 469 } 470 471 return xSingleServiceFactory; 472 } 473 474 /** 475 * Creates a factory for the given class. 476 * <p> 477 * @return returns a factory 478 * @param implClass the implementing class 479 * @param serviceName the service name of the implementing class 480 * @param multiFactory the given multi service factory (service manager) 481 * @param regKey the given registry key 482 * @see com.sun.star.lang.XServiceInfo 483 */ 484 static public XSingleServiceFactory getServiceFactory(Class implClass, 485 String serviceName, 486 XMultiServiceFactory multiFactory, 487 XRegistryKey regKey) 488 { 489 return new Factory(implClass, serviceName, multiFactory, regKey); 490 } 491 492 /** Creates a factory for the given class. 493 494 @return returns a factory object 495 @param implClass the implementing class 496 */ 497 static public Object createComponentFactory( Class implClass, String serviceName ) 498 { 499 return new Factory( implClass, serviceName, null, null ); 500 } 501 502 /** 503 * Writes the registration data into the registry key 504 * <p> 505 * @return success 506 * @param implName the name of the implementing class 507 * @param serviceName the service name 508 * @param regKey the given registry key 509 * @see com.sun.star.lang.XServiceInfo 510 */ 511 static public boolean writeRegistryServiceInfo(String implName, String serviceName, XRegistryKey regKey) { 512 boolean result = false; 513 514 try { 515 XRegistryKey newKey = regKey.createKey("/" + implName + "/UNO/SERVICES"); 516 517 newKey.createKey(serviceName); 518 519 result = true; 520 } 521 catch (Exception ex) { 522 System.err.println(">>>Connection_Impl.writeRegistryServiceInfo " + ex); 523 } 524 525 return result; 526 } 527 528 /** Writes the registration data into the registry key. 529 * Several services are supported. 530 * 531 * @param impl_name name of implementation 532 * @param supported_services supported services of implementation 533 * @param xKey registry key to write to 534 * @return success 535 */ 536 public static boolean writeRegistryServiceInfo( 537 String impl_name, String supported_services [], XRegistryKey xKey ) 538 { 539 try 540 { 541 XRegistryKey xNewKey = xKey.createKey( "/" + impl_name + "/UNO/SERVICES" ); 542 for ( int nPos = 0; nPos < supported_services.length; ++nPos ) 543 { 544 xNewKey.createKey( supported_services[ nPos ] ); 545 } 546 return true; 547 } 548 catch (com.sun.star.registry.InvalidRegistryException exc) 549 { 550 if (DEBUG) 551 { 552 System.err.println( 553 "##### " + Factory.class.getName() + ".writeRegistryServiceInfo -- exc: " + 554 exc.toString() ); 555 } 556 } 557 return false; 558 } 559 560 } 561 562