bump product version to 6.4.0.3
[LibreOffice.git] / jurt / com / sun / star / comp / loader / JavaLoader.java
blob8bc0ae22859319c7424d0ed90343dce5ed468cba
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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.loader;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.InvocationTargetException;
24 import java.net.URLDecoder;
26 import com.sun.star.loader.CannotActivateFactoryException;
27 import com.sun.star.loader.XImplementationLoader;
29 import com.sun.star.registry.CannotRegisterImplementationException;
30 import com.sun.star.registry.XRegistryKey;
32 import com.sun.star.lang.XSingleComponentFactory;
33 import com.sun.star.lang.XSingleServiceFactory;
34 import com.sun.star.lang.XMultiServiceFactory;
35 import com.sun.star.lang.XServiceInfo;
36 import com.sun.star.lang.XInitialization;
38 import com.sun.star.uno.XComponentContext;
39 import com.sun.star.beans.XPropertySet;
40 import com.sun.star.util.XMacroExpander;
42 import com.sun.star.uno.Type;
43 import com.sun.star.uno.UnoRuntime;
45 import com.sun.star.lib.util.StringHelper;
47 import com.sun.star.uno.AnyConverter;
50 /**
51 * The <code>JavaLoader</code> class provides the functionality of the
52 * <code>com.sun.star.loader.Java</code> service.
54 * <p>Therefore the <code>JavaLoader</code> activates external UNO components
55 * which are implemented in Java.</p>
57 * <p>The loader is used by the <code>ServiceManger</code>.</p>
59 * @see com.sun.star.loader.XImplementationLoader
60 * @see com.sun.star.loader.Java
61 * @see com.sun.star.comp.servicemanager.ServiceManager
62 * @since UDK1.0
64 public class JavaLoader implements XImplementationLoader,
65 XServiceInfo,
66 XInitialization
68 private static final boolean DEBUG = false;
70 private static final void DEBUG(String dbg) {
71 if (DEBUG) System.err.println( dbg );
74 private static String[] supportedServices = {
75 "com.sun.star.loader.Java"
78 protected XMultiServiceFactory multiServiceFactory = null;
80 private XMacroExpander m_xMacroExpander = null;
81 private static final String EXPAND_PROTOCOL_PREFIX = "vnd.sun.star.expand:";
83 /**
84 * Expands macrofied url using the macro expander singleton.
86 private String expand_url( String url ) throws RuntimeException
88 if (url == null || !url.startsWith( EXPAND_PROTOCOL_PREFIX )) {
89 return url;
91 try {
92 if (m_xMacroExpander == null) {
93 XPropertySet xProps =
94 UnoRuntime.queryInterface(
95 XPropertySet.class, multiServiceFactory );
96 if (xProps == null) {
97 throw new com.sun.star.uno.RuntimeException(
98 "service manager does not support XPropertySet!",
99 this );
101 XComponentContext xContext = (XComponentContext)
102 AnyConverter.toObject(
103 new Type( XComponentContext.class ),
104 xProps.getPropertyValue( "DefaultContext" ) );
105 m_xMacroExpander = (XMacroExpander)AnyConverter.toObject(
106 new Type( XMacroExpander.class ),
107 xContext.getValueByName(
108 "/singletons/com.sun.star.util.theMacroExpander" )
111 // decode uric class chars
112 String macro = URLDecoder.decode(
113 StringHelper.replace(
114 url.substring( EXPAND_PROTOCOL_PREFIX.length() ),
115 '+', "%2B" ), "UTF-8" );
116 // expand macro string
117 String ret = m_xMacroExpander.expandMacros( macro );
118 if (DEBUG) {
119 System.err.println(
120 "JavaLoader.expand_url(): " + url + " => " +
121 macro + " => " + ret );
123 return ret;
124 } catch (com.sun.star.uno.Exception exc) {
125 throw new com.sun.star.uno.RuntimeException(exc,
126 exc.getMessage(), this );
127 } catch (java.lang.Exception exc) {
128 throw new com.sun.star.uno.RuntimeException(exc,
129 exc.getMessage(), this );
134 * Default constructor.
136 * <p>Creates a new instance of the <code>JavaLoader</code> class.</p>
138 public JavaLoader() {}
141 * Creates a new <code>JavaLoader</code> object.
143 * <p>The specified <code>com.sun.star.lang.XMultiServiceFactory</code> is
144 * the <code>ServiceManager</code> service which can be delivered to all
145 * components the <code>JavaLoader</code> is loading.</p>
147 * <p>To set the <code>MultiServiceFactory</code> you can use the
148 * <code>com.sun.star.lang.XInitialization</code> interface, either.</p>
150 * @param factory the <code>ServiceManager</code>.
151 * @see com.sun.star.comp.servicemanager.ServiceManager
152 * @see com.sun.star.lang.XInitialization
154 public JavaLoader(XMultiServiceFactory factory) {
155 multiServiceFactory = factory;
159 * Unlike the original intention, the method could be called every time a
160 * new <code>com.sun.star.lang.XMultiServiceFactory</code> should be set at
161 * the loader.
163 * @param args - the first parameter (args[0]) specifies the <code>ServiceManager</code>.
164 * @see com.sun.star.lang.XInitialization
165 * @see com.sun.star.comp.servicemanager.ServiceManager
167 public void initialize( java.lang.Object[] args )
168 throws com.sun.star.uno.Exception,
169 com.sun.star.uno.RuntimeException
171 if (args.length == 0)
172 throw new com.sun.star.lang.IllegalArgumentException("No arguments specified");
174 try {
175 multiServiceFactory = (XMultiServiceFactory) AnyConverter.toObject(
176 new Type(XMultiServiceFactory.class), args[0]);
177 } catch (ClassCastException castEx) {
178 throw new com.sun.star.lang.IllegalArgumentException(castEx,
179 "The argument must be an instance of XMultiServiceFactory");
184 * Supplies the implementation name of the component.
186 * @return the implementation name - here the class name.
187 * @see com.sun.star.lang.XServiceInfo
189 public String getImplementationName()
190 throws com.sun.star.uno.RuntimeException
192 return getClass().getName();
196 * Verifies if a given service is supported by the component.
198 * @param serviceName the name of the service that should be checked.
199 * @return true,if service is supported - otherwise false.
201 * @see com.sun.star.lang.XServiceInfo
203 public boolean supportsService(String serviceName)
204 throws com.sun.star.uno.RuntimeException
206 for (String supportedService : supportedServices) {
207 if (supportedService.equals(serviceName)) {
208 return true;
211 return false;
215 * Supplies a list of all service names supported by the component.
217 * @return a String array with all supported services.
218 * @see com.sun.star.lang.XServiceInfo
220 public String[] getSupportedServiceNames()
221 throws com.sun.star.uno.RuntimeException
223 return supportedServices;
227 * Provides a components factory.
229 * <p>The <code>JavaLoader</code> tries to load the class first. If a
230 * location URL is given the RegistrationClassFinder is used to load the
231 * class. Otherwise the class is loaded through the Class.forName method.</p>
233 * <p>To get the factory the inspects the class for the optional static member
234 * functions __getServiceFactory resp. getServiceFactory (DEPRECATED).</p>
236 * @param implementationName the implementation (class) name of the component.
237 * @param implementationLoaderUrl the URL of the implementation loader. Not used.
238 * @param locationUrl points to an archive (JAR file) which contains a component.
239 * @param xKey registry key.
240 * @return the factory for the component (@see com.sun.star.lang.XSingleServiceFactory)
242 * @see com.sun.star.loader.XImplementationLoader
243 * @see com.sun.star.comp.loader.RegistrationClassFinder
245 public java.lang.Object activate( String implementationName,
246 String implementationLoaderUrl,
247 String locationUrl,
248 XRegistryKey xKey )
249 throws CannotActivateFactoryException,
250 com.sun.star.uno.RuntimeException
252 locationUrl = expand_url( locationUrl );
254 Object returnObject = null;
255 Class<?> clazz ;
257 DEBUG("try to get factory for " + implementationName);
259 // First we must get the class of the implementation
260 // 1. If a location URL is given it is assumed that this points to a JAR file.
261 // The components class name is stored in the manifest file.
262 // 2. If only the implementation name is given, the class is loaded with the
263 // Class.forName() method. This is a hack to load bootstrap components.
264 // Normally a string must no be null.
265 try {
266 if ( locationUrl != null ) {
267 clazz = RegistrationClassFinder.find( locationUrl );
268 if (clazz == null) {
269 throw new CannotActivateFactoryException(
270 "Cannot activate jar " + locationUrl);
272 } else {
273 clazz = Class.forName( implementationName );
274 if (clazz == null) {
275 throw new CannotActivateFactoryException(
276 "Cannot find class " + implementationName);
279 } catch (java.net.MalformedURLException e) {
280 throw new CannotActivateFactoryException(e, "Can not activate factory because " + e);
281 } catch (java.io.IOException e) {
282 throw new CannotActivateFactoryException(e, "Can not activate factory because " + e);
283 } catch (java.lang.ClassNotFoundException e) {
284 throw new CannotActivateFactoryException(e, "Can not activate factory because " + e);
287 Class<?>[] paramTypes = {String.class, XMultiServiceFactory.class, XRegistryKey.class};
288 Object[] params = { implementationName, multiServiceFactory, xKey };
290 // try to get factory from implementation class
291 // latest style: use the public static method __getComponentFactory
292 // - new style: use the public static method __getServiceFactory
293 // - old style: use the public static method getServiceFactory ( DEPRECATED )
295 Method compfac_method = null;
296 try {
297 compfac_method = clazz.getMethod(
298 "__getComponentFactory", new Class [] { String.class } );
299 } catch ( NoSuchMethodException noSuchMethodEx) {
300 } catch ( SecurityException secEx) {
303 Method method = null;
304 if (null == compfac_method) {
305 try {
306 method = clazz.getMethod("__getServiceFactory", paramTypes);
307 } catch ( NoSuchMethodException noSuchMethodEx) {
308 } catch ( SecurityException secEx) {
312 try {
313 if (null != compfac_method) {
314 Object ret = compfac_method.invoke( clazz, new Object [] { implementationName } );
315 if (!(ret instanceof XSingleComponentFactory))
316 throw new CannotActivateFactoryException(
317 "No factory object for " + implementationName );
319 return ret;
321 else {
322 if ( method == null )
323 method = clazz.getMethod("getServiceFactory", paramTypes);
325 Object oRet = method.invoke(clazz, params);
327 if ( (oRet != null) && (oRet instanceof XSingleServiceFactory) )
328 returnObject = oRet;
330 } catch ( NoSuchMethodException e) {
331 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
332 + implementationName);
333 } catch ( SecurityException e) {
334 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
335 + implementationName);
336 } catch ( IllegalAccessException e ) {
337 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
338 + implementationName);
340 catch ( IllegalArgumentException e ) {
341 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
342 + implementationName);
343 } catch ( InvocationTargetException e ) {
344 throw new CannotActivateFactoryException(e, "Can not activate the factory for "
345 + implementationName);
348 return returnObject;
352 * Registers the component in a registry under a given root key.
354 * <p>If the component supports the optional
355 * methods __writeRegistryServiceInfo, writeRegistryServiceInfo (DEPRECATED),
356 * the call is delegated to that method. Otherwise a default registration
357 * will be accomplished.</p>
359 * @param regKey the root key under that the component should be registered.
360 * @param implementationLoaderUrl specifies the loader, the component is loaded by.
361 * @param locationUrl points to an archive (JAR file) which contains a component.
362 * @return true if registration is successfully - otherwise false.
364 public boolean writeRegistryInfo( XRegistryKey regKey,
365 String implementationLoaderUrl,
366 String locationUrl )
367 throws CannotRegisterImplementationException,
368 com.sun.star.uno.RuntimeException
370 locationUrl = expand_url( locationUrl );
372 boolean success = false;
374 try {
376 Class<?> clazz = RegistrationClassFinder.find(locationUrl);
377 if (null == clazz)
378 throw new CannotRegisterImplementationException(
379 "Cannot determine registration class!" );
381 Class<?>[] paramTypes = { XRegistryKey.class };
382 Object[] params = { regKey };
384 Method method = clazz.getMethod("__writeRegistryServiceInfo", paramTypes);
385 Object oRet = method.invoke(clazz, params);
387 if ( (oRet != null) && (oRet instanceof Boolean) )
388 success = ((Boolean) oRet).booleanValue();
389 } catch (Exception e) {
390 throw new CannotRegisterImplementationException(e, e.toString());
393 return success;
397 * Supplies the factory for the <code>JavaLoader</code>.
399 * @param implName the name of the desired component.
400 * @param multiFactory the <code>ServiceManager</code> is delivered to the factory.
401 * @param regKey not used - can be null.
402 * @return the factory for the <code>JavaLoader</code>.
404 public static XSingleServiceFactory getServiceFactory( String implName,
405 XMultiServiceFactory multiFactory,
406 XRegistryKey regKey)
408 if ( implName.equals(JavaLoader.class.getName()) )
409 return new JavaLoaderFactory( multiFactory );
411 return null;
415 * Registers the <code>JavaLoader</code> at the registry.
417 * @param regKey root key under which the <code>JavaLoader</code> should be registered.
418 * @return true if registration succeeded - otherwise false.
420 public static boolean writeRegistryServiceInfo(XRegistryKey regKey) {
421 boolean result = false;
423 try {
424 XRegistryKey newKey = regKey.createKey("/" + JavaLoader.class.getName() + "/UNO/SERVICE");
426 for (String supportedService : supportedServices) {
427 newKey.createKey(supportedService);
430 result = true;
431 } catch (Exception ex) {
432 if (DEBUG) System.err.println(">>>JavaLoader.writeRegistryServiceInfo " + ex);
435 return result;
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */