bump product version to 5.0.4.1
[LibreOffice.git] / jurt / com / sun / star / comp / loader / JavaLoader.java
blobef07674dcf344ab3b7dac50fdf53159766461359
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package com.sun.star.comp.loader;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.InvocationTargetException;
23 import java.net.URLDecoder;
25 import com.sun.star.loader.CannotActivateFactoryException;
26 import com.sun.star.loader.XImplementationLoader;
28 import com.sun.star.registry.CannotRegisterImplementationException;
29 import com.sun.star.registry.XRegistryKey;
31 import com.sun.star.lang.XSingleComponentFactory;
32 import com.sun.star.lang.XSingleServiceFactory;
33 import com.sun.star.lang.XMultiServiceFactory;
34 import com.sun.star.lang.XServiceInfo;
35 import com.sun.star.lang.XInitialization;
37 import com.sun.star.uno.XComponentContext;
38 import com.sun.star.beans.XPropertySet;
39 import com.sun.star.util.XMacroExpander;
41 import com.sun.star.uno.Type;
42 import com.sun.star.uno.UnoRuntime;
44 import com.sun.star.lib.util.StringHelper;
46 import com.sun.star.uno.AnyConverter;
49 /**
50 * The <code>JavaLoader</code> class provides the functionality of the
51 * <code>com.sun.star.loader.Java</code> service.
53 * <p>Therefore the <code>JavaLoader</code> activates external UNO components
54 * which are implemented in Java.</p>
56 * <p>The loader is used by the <code>ServiceManger</code>.</p>
58 * @see com.sun.star.loader.XImplementationLoader
59 * @see com.sun.star.loader.Java
60 * @see com.sun.star.comp.servicemanager.ServiceManager
61 * @since UDK1.0
63 public class JavaLoader implements XImplementationLoader,
64 XServiceInfo,
65 XInitialization
67 private static final boolean DEBUG = false;
69 private static final void DEBUG(String dbg) {
70 if (DEBUG) System.err.println( dbg );
73 private static String[] supportedServices = {
74 "com.sun.star.loader.Java"
77 protected XMultiServiceFactory multiServiceFactory = null;
79 private XMacroExpander m_xMacroExpander = null;
80 private static final String EXPAND_PROTOCOL_PREFIX = "vnd.sun.star.expand:";
82 /**
83 * Expands macrofied url using the macro expander singleton.
85 private String expand_url( String url ) throws RuntimeException
87 if (url == null || !url.startsWith( EXPAND_PROTOCOL_PREFIX )) {
88 return url;
90 try {
91 if (m_xMacroExpander == null) {
92 XPropertySet xProps =
93 UnoRuntime.queryInterface(
94 XPropertySet.class, multiServiceFactory );
95 if (xProps == null) {
96 throw new com.sun.star.uno.RuntimeException(
97 "service manager does not support XPropertySet!",
98 this );
100 XComponentContext xContext = (XComponentContext)
101 AnyConverter.toObject(
102 new Type( XComponentContext.class ),
103 xProps.getPropertyValue( "DefaultContext" ) );
104 m_xMacroExpander = (XMacroExpander)AnyConverter.toObject(
105 new Type( XMacroExpander.class ),
106 xContext.getValueByName(
107 "/singletons/com.sun.star.util.theMacroExpander" )
110 // decode uric class chars
111 String macro = URLDecoder.decode(
112 StringHelper.replace(
113 url.substring( EXPAND_PROTOCOL_PREFIX.length() ),
114 '+', "%2B" ), "UTF-8" );
115 // expand macro string
116 String ret = m_xMacroExpander.expandMacros( macro );
117 if (DEBUG) {
118 System.err.println(
119 "JavaLoader.expand_url(): " + url + " => " +
120 macro + " => " + ret );
122 return ret;
123 } catch (com.sun.star.uno.Exception exc) {
124 throw new com.sun.star.uno.RuntimeException(exc,
125 exc.getMessage(), this );
126 } catch (java.lang.Exception exc) {
127 throw new com.sun.star.uno.RuntimeException(exc,
128 exc.getMessage(), this );
133 * Default constructor.
135 * <p>Creates a new instance of the <code>JavaLoader</code> class.</p>
137 public JavaLoader() {}
140 * Creates a new <code>JavaLoader</code> object.
142 * <p>The specified <code>com.sun.star.lang.XMultiServiceFactory</code> is
143 * the <code>ServiceManager</code> service which can be delivered to all
144 * components the <code>JavaLoader</code> is loading.</p>
146 * <p>To set the <code>MultiServiceFactory</code> you can use the
147 * <code>com.sun.star.lang.XInitialization</code> interface, either.</p>
149 * @param factory the <code>ServiceManager</code>.
150 * @see com.sun.star.comp.servicemanager.ServiceManager
151 * @see com.sun.star.lang.XInitialization
153 public JavaLoader(XMultiServiceFactory factory) {
154 multiServiceFactory = factory;
158 * Unlike the original intention, the method could be called every time a
159 * new <code>com.sun.star.lang.XMultiServiceFactory</code> should be set at
160 * the loader.
162 * @param args - the first parameter (args[0]) specifices the <code>ServiceManager</code>.
163 * @see com.sun.star.lang.XInitialization
164 * @see com.sun.star.comp.servicemanager.ServiceManager
166 public void initialize( java.lang.Object[] args )
167 throws com.sun.star.uno.Exception,
168 com.sun.star.uno.RuntimeException
170 if (args.length == 0)
171 throw new com.sun.star.lang.IllegalArgumentException("No arguments specified");
173 try {
174 multiServiceFactory = (XMultiServiceFactory) AnyConverter.toObject(
175 new Type(XMultiServiceFactory.class), args[0]);
176 } catch (ClassCastException castEx) {
177 throw new com.sun.star.lang.IllegalArgumentException(castEx,
178 "The argument must be an instance of XMultiServiceFactory");
183 * Supplies the implementation name of the component.
185 * @return the implementation name - here the class name.
186 * @see com.sun.star.lang.XServiceInfo
188 public String getImplementationName()
189 throws com.sun.star.uno.RuntimeException
191 return getClass().getName();
195 * Verifies if a given service is supported by the component.
197 * @param serviceName the name of the service that should be checked.
198 * @return true,if service is supported - otherwise false.
200 * @see com.sun.star.lang.XServiceInfo
202 public boolean supportsService(String serviceName)
203 throws com.sun.star.uno.RuntimeException
205 for (String supportedService : supportedServices) {
206 if (supportedService.equals(serviceName)) {
207 return true;
210 return false;
214 * Supplies a list of all service names supported by the component.
216 * @return a String array with all supported services.
217 * @see com.sun.star.lang.XServiceInfo
219 public String[] getSupportedServiceNames()
220 throws com.sun.star.uno.RuntimeException
222 return supportedServices;
226 * Provides a components factory.
228 * <p>The <code>JavaLoader</code> tries to load the class first. If a
229 * loacation URL is given the RegistrationClassFinder is used to load the
230 * class. Otherwise the class is loaded through the Class.forName method.</p>
232 * <p>To get the factory the inspects the class for the optional static member
233 * functions __getServiceFactory resp. getServiceFactory (DEPRECATED).</p>
235 * <p>If the function can not be found a default factory @see ComponentFactoryWrapper
236 * will be created.</p>
238 * @param implementationName the implementation (class) name of the component.
239 * @param implementationLoaderUrl the URL of the implementation loader. Not used.
240 * @param locationUrl points to an archive (JAR file) which contains a component.
241 * @param xKey registry key.
242 * @return the factory for the component (@see com.sun.star.lang.XSingleServiceFactory)
244 * @see com.sun.star.loader.XImplementationLoader
245 * @see com.sun.star.comp.loader.RegistrationClassFinder
247 public java.lang.Object activate( String implementationName,
248 String implementationLoaderUrl,
249 String locationUrl,
250 XRegistryKey xKey )
251 throws CannotActivateFactoryException,
252 com.sun.star.uno.RuntimeException
254 locationUrl = expand_url( locationUrl );
256 Object returnObject = null;
257 Class<?> clazz ;
259 DEBUG("try to get factory for " + implementationName);
261 // First we must get the class of the implementation
262 // 1. If a location URL is given it is assumed that this points to a JAR file.
263 // The components class name is stored in the manifest file.
264 // 2. If only the implementation name is given, the class is loaded with the
265 // Class.forName() method. This is a hack to load bootstrap components.
266 // Normally a string must no be null.
267 try {
268 if ( locationUrl != null ) {
269 clazz = RegistrationClassFinder.find( locationUrl );
270 if (clazz == null) {
271 throw new CannotActivateFactoryException(
272 "Cannot activate jar " + locationUrl);
274 } else {
275 clazz = Class.forName( implementationName );
276 if (clazz == null) {
277 throw new CannotActivateFactoryException(
278 "Cannot find class " + implementationName);
281 } catch (java.net.MalformedURLException e) {
282 throw new CannotActivateFactoryException(e, "Can not activate factory because " + e);
283 } catch (java.io.IOException e) {
284 throw new CannotActivateFactoryException(e, "Can not activate factory because " + e);
285 } catch (java.lang.ClassNotFoundException e) {
286 throw new CannotActivateFactoryException(e, "Can not activate factory because " + e);
289 Class<?>[] paramTypes = {String.class, XMultiServiceFactory.class, XRegistryKey.class};
290 Object[] params = { implementationName, multiServiceFactory, xKey };
292 // try to get factory from implementation class
293 // latest style: use the public static method __getComponentFactory
294 // - new style: use the public static method __getServiceFactory
295 // - old style: use the public static method getServiceFactory ( DEPRECATED )
297 Method compfac_method = null;
298 try {
299 compfac_method = clazz.getMethod(
300 "__getComponentFactory", new Class [] { String.class } );
301 } catch ( NoSuchMethodException noSuchMethodEx) {
302 } catch ( SecurityException secEx) {
305 Method method = null;
306 if (null == compfac_method) {
307 try {
308 method = clazz.getMethod("__getServiceFactory", paramTypes);
309 } catch ( NoSuchMethodException noSuchMethodEx) {
310 } catch ( SecurityException secEx) {
314 try {
315 if (null != compfac_method) {
316 Object ret = compfac_method.invoke( clazz, new Object [] { implementationName } );
317 if (!(ret instanceof XSingleComponentFactory))
318 throw new CannotActivateFactoryException(
319 "No factory object for " + implementationName );
321 return ret;
323 else {
324 if ( method == null )
325 method = clazz.getMethod("getServiceFactory", paramTypes);
327 Object oRet = method.invoke(clazz, params);
329 if ( (oRet != null) && (oRet instanceof XSingleServiceFactory) )
330 returnObject = oRet;
332 } catch ( NoSuchMethodException e) {
333 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
334 + implementationName);
335 } catch ( SecurityException e) {
336 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
337 + implementationName);
338 } catch ( IllegalAccessException e ) {
339 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
340 + implementationName);
342 catch ( IllegalArgumentException e ) {
343 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
344 + implementationName);
345 } catch ( InvocationTargetException e ) {
346 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
347 + implementationName);
350 return returnObject;
354 * Registers the component in a registry under a given root key.
356 * <p>If the component supports the optional
357 * methods __writeRegistryServiceInfo, writeRegistryServiceInfo (DEPRECATED),
358 * the call is delegated to that method. Otherwise a default registration
359 * will be accomplished.</p>
361 * @param regKey the root key under that the component should be registred.
362 * @param implementationLoaderUrl specifies the loader, the component is loaded by.
363 * @param locationUrl points to an archive (JAR file) which contains a component.
364 * @return true if registration is successfully - otherwise false.
366 * @see ComponentFactoryWrapper
368 public boolean writeRegistryInfo( XRegistryKey regKey,
369 String implementationLoaderUrl,
370 String locationUrl )
371 throws CannotRegisterImplementationException,
372 com.sun.star.uno.RuntimeException
374 locationUrl = expand_url( locationUrl );
376 boolean success = false;
378 try {
380 Class<?> clazz = RegistrationClassFinder.find(locationUrl);
381 if (null == clazz)
382 throw new CannotRegisterImplementationException(
383 "Cannot determine registration class!" );
385 Class<?>[] paramTypes = { XRegistryKey.class };
386 Object[] params = { regKey };
388 Method method = clazz.getMethod("__writeRegistryServiceInfo", paramTypes);
389 Object oRet = method.invoke(clazz, params);
391 if ( (oRet != null) && (oRet instanceof Boolean) )
392 success = ((Boolean) oRet).booleanValue();
393 } catch (Exception e) {
394 throw new CannotRegisterImplementationException(e, e.toString());
397 return success;
401 * Supplies the factory for the <code>JavaLoader</code>.
403 * @param implName the name of the desired component.
404 * @param multiFactory the <code>ServiceManager</code> is delivered to the factory.
405 * @param regKey not used - can be null.
406 * @return the factory for the <code>JavaLoader</code>.
408 public static XSingleServiceFactory getServiceFactory( String implName,
409 XMultiServiceFactory multiFactory,
410 XRegistryKey regKey)
412 if ( implName.equals(JavaLoader.class.getName()) )
413 return new JavaLoaderFactory( multiFactory );
415 return null;
419 * Registers the <code>JavaLoader</code> at the registry.
421 * @param regKey root key under which the <code>JavaLoader</code> should be regidstered.
422 * @return true if registration succseeded - otherwise false.
424 public static boolean writeRegistryServiceInfo(XRegistryKey regKey) {
425 boolean result = false;
427 try {
428 XRegistryKey newKey = regKey.createKey("/" + JavaLoader.class.getName() + "/UNO/SERVICE");
430 for (String supportedService : supportedServices) {
431 newKey.createKey(supportedService);
434 result = true;
435 } catch (Exception ex) {
436 if (DEBUG) System.err.println(">>>JavaLoader.writeRegistryServiceInfo " + ex);
439 return result;