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