1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 package com
.sun
.star
.comp
.servicemanager
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Collections
;
25 import com
.sun
.star
.container
.XContentEnumerationAccess
;
26 import com
.sun
.star
.container
.XEnumeration
;
27 import com
.sun
.star
.container
.XSet
;
28 import com
.sun
.star
.lang
.XComponent
;
29 import com
.sun
.star
.lang
.XEventListener
;
30 import com
.sun
.star
.lang
.XMultiComponentFactory
;
31 import com
.sun
.star
.lang
.XMultiServiceFactory
;
32 import com
.sun
.star
.lang
.XServiceInfo
;
33 import com
.sun
.star
.lang
.XSingleComponentFactory
;
34 import com
.sun
.star
.lang
.XSingleServiceFactory
;
35 import com
.sun
.star
.uno
.UnoRuntime
;
36 import com
.sun
.star
.uno
.XComponentContext
;
39 * The <code>ServiceManager</code> class is an implementation of the
40 * <code>ServiceManager</code>the central class needed for implementing or using
41 * UNO components in Java.
43 * <p>The Methods <code>queryInterface</code> and <code>isSame</code> delegate
44 * calls to the implementing objects and are used instead of casts and identity
47 * @see com.sun.star.lang.XMultiServiceFactory
48 * @see com.sun.star.container.XSet
49 * @see com.sun.star.container.XContentEnumerationAccess
50 * @see com.sun.star.lang.XComponent
51 * @see com.sun.star.lang.XServiceInfo
54 public class ServiceManager
implements XMultiServiceFactory
,
55 XMultiComponentFactory
,
57 XContentEnumerationAccess
,
61 private static final boolean DEBUG
= false;
63 private static final void DEBUG (String dbg
) {
64 if (DEBUG
) System
.err
.println( dbg
);
67 private static com
.sun
.star
.uno
.Type UNO_TYPE
= null;
69 static String
[] supportedServiceNames
= {
70 "com.sun.star.lang.MultiServiceFactory",
71 "com.sun.star.lang.ServiceManager"
74 ArrayList
<XEventListener
> eventListener
;
75 java
.util
.HashMap
<String
, Object
> factoriesByImplNames
;
76 java
.util
.HashMap
<String
, ArrayList
<Object
>> factoriesByServiceNames
; // keys:
78 private com
.sun
.star
.uno
.XComponentContext m_xDefaultContext
;
81 * Creates a new instance of the <code>ServiceManager</code>.
83 public ServiceManager() {
84 eventListener
= new ArrayList
<XEventListener
>();
85 factoriesByImplNames
= new java
.util
.HashMap
<String
, Object
>();
86 factoriesByServiceNames
= new java
.util
.HashMap
<String
, ArrayList
<Object
>>();
87 m_xDefaultContext
= null;
90 public void setDefaultContext(XComponentContext context
) {
91 m_xDefaultContext
= context
;
95 * Creates a new instance of a specified service.
97 * <p>Therefore the associated factory of the service is looked up and used
98 * to instantiate a new component. </p>
100 * @param serviceSpecifier indicates the service or component name.
101 * @return newly created component.
103 * @see com.sun.star.lang.XMultiServiceFactory
105 public java
.lang
.Object
createInstance( String serviceSpecifier
)
106 throws com
.sun
.star
.uno
.Exception
,
107 com
.sun
.star
.uno
.RuntimeException
109 return createInstanceWithContext( serviceSpecifier
, m_xDefaultContext
);
113 * Creates a new instance of a specified service with the given parameters.
115 * <p>Therefore the associated factory of the service is looked up and used
116 * to instantiate a new component.</p>
118 * @return newly created component.
119 * @param serviceSpecifier indicates the service or component name.
120 * @see com.sun.star.lang.XMultiServiceFactory
122 public java
.lang
.Object
createInstanceWithArguments(
123 String serviceSpecifier
, Object
[] args
)
124 throws com
.sun
.star
.uno
.Exception
, com
.sun
.star
.uno
.RuntimeException
127 System
.err
.println("createInstanceWithArguments:" );
129 for (Object arg
: args
) {
130 System
.err
.print(" " + arg
);
133 System
.err
.println();
136 return createInstanceWithArgumentsAndContext( serviceSpecifier
, args
, m_xDefaultContext
);
140 * Look up the factory for a given service or implementation name.
142 * <p>First the requested service name is search in the list of available
143 * services. If it can not be found the name is looked up in the implementation
146 * @param serviceName indicates the service or implementation name.
147 * @return the factory of the service / implementation.
149 * @see com.sun.star.lang.XMultiServiceFactory
151 private Object
queryServiceFactory(String serviceName
)
152 throws com
.sun
.star
.uno
.Exception
,
153 com
.sun
.star
.uno
.RuntimeException
155 DEBUG("queryServiceFactory for name " + serviceName
);
156 Object factory
= null;
158 if ( factoriesByServiceNames
.containsKey( serviceName
) ) {
159 ArrayList
<Object
> availableFact
= factoriesByServiceNames
.get( serviceName
);
162 DEBUG("available factories for " + serviceName
+" "+ availableFact
);
165 if ( !availableFact
.isEmpty() )
166 factory
= availableFact
.get(availableFact
.size()-1);
168 } else // not found in list of services - now try the implementations
169 factory
= factoriesByImplNames
.get( serviceName
); // return null if none is available
172 if (factory
== null) System
.err
.println("service not registered");
174 System
.err
.println("service found:" + factory
+ " " + UnoRuntime
.queryInterface(XSingleServiceFactory
.class, factory
));
178 throw new com
.sun
.star
.uno
.Exception("Query for service factory for " + serviceName
+ " failed.");
184 * Supplies a list of all available services names.
186 * @return list of Strings of all service names.
187 * @see com.sun.star.container.XContentEnumerationAccess
189 public String
[] getAvailableServiceNames()
190 throws com
.sun
.star
.uno
.RuntimeException
193 return factoriesByServiceNames
.keySet().toArray(
194 new String
[ factoriesByServiceNames
.size() ] );
195 } catch(Exception ex
) {
196 throw new com
.sun
.star
.uno
.RuntimeException(ex
);
200 // XMultiComponentFactory implementation
202 /** Create a service instance with given context.
204 * @param rServiceSpecifier service name.
205 * @param xContext context.
206 * @return service instance.
208 public java
.lang
.Object
createInstanceWithContext(
209 String rServiceSpecifier
,
210 com
.sun
.star
.uno
.XComponentContext xContext
)
211 throws com
.sun
.star
.uno
.Exception
213 Object fac
= queryServiceFactory( rServiceSpecifier
);
216 XSingleComponentFactory xCompFac
= UnoRuntime
.queryInterface(
217 XSingleComponentFactory
.class, fac
);
218 if (xCompFac
!= null)
220 return xCompFac
.createInstanceWithContext( xContext
);
224 XSingleServiceFactory xServiceFac
= UnoRuntime
.queryInterface(
225 XSingleServiceFactory
.class, fac
);
226 if (xServiceFac
!= null)
229 System
.err
.println( "### ignoring context raising service \"" + rServiceSpecifier
+ "\"!" );
230 return xServiceFac
.createInstance();
234 throw new com
.sun
.star
.uno
.Exception(
235 "retrieved service factory object for \"" + rServiceSpecifier
+
236 "\" does not export XSingleComponentFactory nor XSingleServiceFactory!" );
243 * Create a service instance with given context and arguments.
245 * @param rServiceSpecifier service name.
246 * @param rArguments arguments.
247 * @param xContext context.
248 * @return service instance.
250 public java
.lang
.Object
createInstanceWithArgumentsAndContext(
251 String rServiceSpecifier
,
252 java
.lang
.Object
[] rArguments
,
253 com
.sun
.star
.uno
.XComponentContext xContext
)
254 throws com
.sun
.star
.uno
.Exception
256 Object fac
= queryServiceFactory( rServiceSpecifier
);
259 XSingleComponentFactory xCompFac
= UnoRuntime
.queryInterface(
260 XSingleComponentFactory
.class, fac
);
261 if (xCompFac
!= null)
263 return xCompFac
.createInstanceWithArgumentsAndContext( rArguments
, xContext
);
267 XSingleServiceFactory xServiceFac
= UnoRuntime
.queryInterface(
268 XSingleServiceFactory
.class, fac
);
269 if (xServiceFac
!= null)
272 System
.err
.println( "### ignoring context raising service \"" + rServiceSpecifier
+ "\"!" );
273 return xServiceFac
.createInstanceWithArguments( rArguments
);
277 throw new com
.sun
.star
.uno
.Exception(
278 "retrieved service factory object for \"" + rServiceSpecifier
+
279 "\" does not export XSingleComponentFactory nor XSingleServiceFactory!" );
287 * Removes all listeners from the <code>ServiceManager</code> and clears the
288 * list of the services.
290 * @see com.sun.star.lang.XComponent
292 public void dispose()
293 throws com
.sun
.star
.uno
.RuntimeException
295 if (eventListener
!= null) {
296 for (XEventListener listener
: eventListener
) {
297 listener
.disposing(new com
.sun
.star
.lang
.EventObject(this));
299 eventListener
.clear();
302 factoriesByServiceNames
.clear();
303 factoriesByImplNames
.clear();
307 * Adds a new <code>EventListener</code>.
309 * <p>The listener is notified when a service is added (removed) to (from)
310 * the <code>ServiceManager</code>.</p>
312 * <p>If the listener is already registered a
313 * <code>com.sun.star.uno.RuntimeException</code> will be thrown.</p>
315 * @param xListener the new listener which should been added.
316 * @see com.sun.star.lang.XComponent
318 public void addEventListener( XEventListener xListener
)
319 throws com
.sun
.star
.uno
.RuntimeException
321 if (xListener
== null)
322 throw new com
.sun
.star
.uno
.RuntimeException("Listener must not be null");
324 if ( eventListener
.contains(xListener
) )
325 throw new com
.sun
.star
.uno
.RuntimeException("Listener already registered.");
327 eventListener
.add(xListener
);
331 * Removes a <code>EventListener</code> from the <code>ServiceManager</code>.
333 * <p>If the listener is not registered a <code>com.sun.star.uno.RuntimeException</code>
334 * will be thrown.</p>
336 * @param xListener the new listener which should been removed.
337 * @see com.sun.star.lang.XComponent
339 public void removeEventListener( XEventListener xListener
)
340 throws com
.sun
.star
.uno
.RuntimeException
342 if (xListener
== null)
343 throw new com
.sun
.star
.uno
.RuntimeException("Listener must not be null");
345 if ( !eventListener
.contains(xListener
) )
346 throw new com
.sun
.star
.uno
.RuntimeException("Listener is not registered.");
348 eventListener
.remove(xListener
);
352 * Checks if a component is registered at the <code>ServiceManager</code>.
354 * <p>The given object argument must provide a <code>XServiceInfo</code>
357 * @param object object which provides a <code>XServiceInfo</code> interface.
358 * @return true if the component is registered otherwise false.
360 * @see com.sun.star.container.XSet
361 * @see com.sun.star.lang.XServiceInfo
363 public boolean has( Object object
)
364 throws com
.sun
.star
.uno
.RuntimeException
367 throw new com
.sun
.star
.uno
.RuntimeException("The parameter must not been null");
369 XServiceInfo xServiceInfo
= UnoRuntime
.queryInterface(XServiceInfo
.class, object
);
371 return xServiceInfo
!= null && UnoRuntime
.areSame(factoriesByImplNames
.get(xServiceInfo
.getImplementationName()), object
);
375 * Adds a <code>SingleServiceFactory</code> to the <code>ServiceManager</code>.
377 * @param object factory which should be added.
378 * @see com.sun.star.container.XSet
379 * @see com.sun.star.lang.XSingleServiceFactory
381 public void insert( Object object
)
382 throws com
.sun
.star
.lang
.IllegalArgumentException
,
383 com
.sun
.star
.container
.ElementExistException
,
384 com
.sun
.star
.uno
.RuntimeException
386 if (object
== null) throw new com
.sun
.star
.lang
.IllegalArgumentException();
388 XServiceInfo xServiceInfo
=
389 UnoRuntime
.queryInterface(XServiceInfo
.class, object
);
391 if (xServiceInfo
== null)
392 throw new com
.sun
.star
.lang
.IllegalArgumentException(
393 "The given object does not implement the XServiceInfo interface."
396 if ( factoriesByImplNames
.containsKey( xServiceInfo
.getImplementationName() ) ) {
397 throw new com
.sun
.star
.container
.ElementExistException(
398 xServiceInfo
.getImplementationName() + " already registered"
402 DEBUG("add factory " + object
.toString() + " for " + xServiceInfo
.getImplementationName());
403 factoriesByImplNames
.put( xServiceInfo
.getImplementationName(), object
);
406 String
[] serviceNames
= xServiceInfo
.getSupportedServiceNames();
407 ArrayList
<Object
> vec
;
409 for (String serviceName
: serviceNames
) {
410 if (!factoriesByServiceNames
.containsKey(serviceName
)) {
411 DEBUG("> no registered services found under " + serviceName
+ ": adding...");
412 factoriesByServiceNames
.put(serviceName
, new ArrayList
<Object
>());
414 vec
= factoriesByServiceNames
.get(serviceName
);
415 if (vec
.contains( object
)) {
416 System
.err
.println("The implementation " + xServiceInfo
.getImplementationName() +
417 " already registered for the service " + serviceName
+ " - ignoring!");
425 * Removes a <code>SingleServiceFactory</code> from the <code>ServiceManager</code>.
427 * @param object factory which should be removed.
428 * @see com.sun.star.container.XSet
429 * @see com.sun.star.lang.XSingleServiceFactory
431 public void remove( Object object
)
432 throws com
.sun
.star
.lang
.IllegalArgumentException
,
433 com
.sun
.star
.container
.NoSuchElementException
,
434 com
.sun
.star
.uno
.RuntimeException
437 throw new com
.sun
.star
.lang
.IllegalArgumentException(
438 "The given object must not be null."
441 XServiceInfo xServiceInfo
=
442 UnoRuntime
.queryInterface(XServiceInfo
.class, object
);
444 if (xServiceInfo
== null)
445 throw new com
.sun
.star
.lang
.IllegalArgumentException(
446 "The given object does not implement the XServiceInfo interface."
449 XSingleServiceFactory xSingleServiceFactory
=
450 UnoRuntime
.queryInterface(XSingleServiceFactory
.class, object
);
452 if (xSingleServiceFactory
== null)
453 throw new com
.sun
.star
.lang
.IllegalArgumentException(
454 "The given object does not implement the XSingleServiceFactory interface."
457 if ( factoriesByImplNames
.remove( xServiceInfo
.getImplementationName() ) == null )
458 throw new com
.sun
.star
.container
.NoSuchElementException(
459 xServiceInfo
.getImplementationName() +
460 " is not registered as an implementation."
463 String
[] serviceNames
= xServiceInfo
.getSupportedServiceNames();
465 for (String serviceName
: serviceNames
) {
466 if (factoriesByServiceNames
.containsKey(serviceName
)) {
467 ArrayList
<Object
> vec
= factoriesByServiceNames
.get(serviceName
);
468 if (!vec
.remove(object
)) {
469 System
.err
.println("The implementation " + xServiceInfo
.getImplementationName() +
470 " is not registered for the service " + serviceName
+ " - ignoring!");
472 // remove the vector if no implementations available for the service
474 factoriesByServiceNames
.remove(serviceName
);
481 * Provides an enumeration of all registered services.
483 * @return an enumeration of all available services.
484 * @see com.sun.star.container.XEnumerationAccess
486 public XEnumeration
createEnumeration()
487 throws com
.sun
.star
.uno
.RuntimeException
489 return new ServiceEnumerationImpl( factoriesByImplNames
.values().iterator() );
493 * Provides the UNO type of the <code>ServiceManager</code>
495 * @return the UNO type of the <code>ServiceManager</code>.
496 * @see com.sun.star.container.XElementAccess
497 * @see com.sun.star.uno.TypeClass
499 public com
.sun
.star
.uno
.Type
getElementType()
500 throws com
.sun
.star
.uno
.RuntimeException
502 if ( UNO_TYPE
== null )
503 UNO_TYPE
= new com
.sun
.star
.uno
.Type(ServiceManager
.class);
509 * Checks if the any components are registered.
511 * @return true - if the list of the registered components is not empty - otherwise false.
512 * @see com.sun.star.container.XElementAccess
514 public boolean hasElements() {
515 return ! factoriesByImplNames
.isEmpty();
519 * Provides an enumeration of all factories for a specified service.
521 * @param serviceName name of the requested service.
522 * @return an enumeration for service name.
523 * @see com.sun.star.container.XContentEnumerationAccess
525 public XEnumeration
createContentEnumeration( String serviceName
)
526 throws com
.sun
.star
.uno
.RuntimeException
528 XEnumeration enumer
;
530 ArrayList
<Object
> serviceList
= factoriesByServiceNames
.get(serviceName
);
532 if (serviceList
!= null)
533 enumer
= new ServiceEnumerationImpl( serviceList
.iterator() );
535 enumer
= new ServiceEnumerationImpl();
541 * Returns the implementation name of the <code>ServiceManager</code> component.
543 * @return the class name of the <code>ServiceManager</code>.
544 * @see com.sun.star.lang.XServiceInfo
546 public String
getImplementationName()
547 throws com
.sun
.star
.uno
.RuntimeException
549 return getClass().getName();
553 * Checks if the <code>ServiceManager</code> supports a service.
555 * @param serviceName service name which should be checked.
556 * @return true if the service is supported - otherwise false.
558 * @see com.sun.star.lang.XServiceInfo
560 public boolean supportsService( String serviceName
)
561 throws com
.sun
.star
.uno
.RuntimeException
563 for (String supportedServiceName
: supportedServiceNames
) {
564 if (supportedServiceName
.equals(serviceName
)) {
569 return getImplementationName().equals(serviceName
);
573 * Supplies list of all supported services.
575 * @return a list of all supported service names.
576 * @see com.sun.star.lang.XServiceInfo
578 public String
[] getSupportedServiceNames()
579 throws com
.sun
.star
.uno
.RuntimeException
581 return supportedServiceNames
;
585 * The <code>ServiceEnumerationImpl</code> class provides an
586 * implementation of the @see com.sun.star.container.XEnumeration interface.
588 * <p>It is an inner wrapper for a java.util.Enumeration object.</p>
590 * @see com.sun.star.lang.XSingleServiceFactory
591 * @see com.sun.star.lang.XServiceInfo
594 static class ServiceEnumerationImpl
implements XEnumeration
{
595 java
.util
.Iterator
<Object
> enumeration
= null;
598 * Constructs a new empty instance.
600 public ServiceEnumerationImpl() {
604 * Constructs a new instance with a given enumeration.
606 * @param enumer is the enumeration which should been wrapped.
607 * @see com.sun.star.container.XEnumeration
609 public ServiceEnumerationImpl(java
.util
.Enumeration
<Object
> enumer
) {
610 enumeration
= Collections
.list(enumer
).iterator();
614 * Constructs a new instance with a given enumeration.
616 * @param enumer is the enumeration which should been wrapped.
617 * @see com.sun.star.container.XEnumeration
619 public ServiceEnumerationImpl(java
.util
.Iterator
<Object
> enumer
) {
620 enumeration
= enumer
;
624 * Checks if the enumeration contains more elements.
626 * @return true if more elements are available - otherwise false.
627 * @see com.sun.star.container.XEnumeration
629 public boolean hasMoreElements()
630 throws com
.sun
.star
.uno
.RuntimeException
632 return enumeration
!= null && enumeration
.hasNext();
637 * Returns the next element of the enumeration.
639 * <p>If no further elements available a com.sun.star.container.NoSuchElementException
640 * exception will be thrown.</p>
642 * @return the next element.
643 * @see com.sun.star.container.XEnumeration
645 public Object
nextElement()
646 throws com
.sun
.star
.container
.NoSuchElementException
,
647 com
.sun
.star
.lang
.WrappedTargetException
,
648 com
.sun
.star
.uno
.RuntimeException
650 if (enumeration
== null)
651 throw new com
.sun
.star
.container
.NoSuchElementException();
654 return enumeration
.next();
655 } catch (java
.util
.NoSuchElementException e
) {
656 throw new com
.sun
.star
.container
.NoSuchElementException(e
, e
.toString());
662 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */