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