xref: /AOO41X/main/jurt/com/sun/star/comp/loader/FactoryHelper.java (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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