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