/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
package com.sun.star.comp.loader;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.URLDecoder;
import com.sun.star.loader.CannotActivateFactoryException;
import com.sun.star.loader.XImplementationLoader;
import com.sun.star.registry.CannotRegisterImplementationException;
import com.sun.star.registry.XRegistryKey;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lang.XSingleServiceFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XInitialization;
import com.sun.star.uno.XComponentContext;
import com.sun.star.beans.XPropertySet;
import com.sun.star.util.XMacroExpander;
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.lib.util.StringHelper;
import com.sun.star.uno.AnyConverter;
/**
* The JavaLoader
class provides the functionality of the
* com.sun.star.loader.Java
service.
*
*
Therefore the JavaLoader
activates external UNO components
* which are implemented in Java.
The loader is used by the ServiceManger
.
Creates a new instance of the JavaLoader
class.
JavaLoader
object.
*
* The specified com.sun.star.lang.XMultiServiceFactory
is
* the ServiceManager
service which can be delivered to all
* components the JavaLoader
is loading.
To set the MultiServiceFactory
you can use the
* com.sun.star.lang.XInitialization
interface, either.
ServiceManager
.
* @see com.sun.star.comp.servicemanager.ServiceManager
* @see com.sun.star.lang.XInitialization
*/
public JavaLoader(XMultiServiceFactory factory) {
multiServiceFactory = factory;
}
/**
* Unlike the original intention, the method could be called every time a
* new com.sun.star.lang.XMultiServiceFactory
should be set at
* the loader.
*
* @param args - the first parameter (args[0]) specifies the ServiceManager
.
* @see com.sun.star.lang.XInitialization
* @see com.sun.star.comp.servicemanager.ServiceManager
*/
public void initialize( java.lang.Object[] args )
throws com.sun.star.uno.Exception,
com.sun.star.uno.RuntimeException
{
if (args.length == 0)
throw new com.sun.star.lang.IllegalArgumentException("No arguments specified");
try {
multiServiceFactory = (XMultiServiceFactory) AnyConverter.toObject(
new Type(XMultiServiceFactory.class), args[0]);
} catch (ClassCastException castEx) {
throw new com.sun.star.lang.IllegalArgumentException(castEx,
"The argument must be an instance of XMultiServiceFactory");
}
}
/**
* Supplies the implementation name of the component.
*
* @return the implementation name - here the class name.
* @see com.sun.star.lang.XServiceInfo
*/
public String getImplementationName()
throws com.sun.star.uno.RuntimeException
{
return getClass().getName();
}
/**
* Verifies if a given service is supported by the component.
*
* @param serviceName the name of the service that should be checked.
* @return true,if service is supported - otherwise false.
*
* @see com.sun.star.lang.XServiceInfo
*/
public boolean supportsService(String serviceName)
throws com.sun.star.uno.RuntimeException
{
for (String supportedService : supportedServices) {
if (supportedService.equals(serviceName)) {
return true;
}
}
return false;
}
/**
* Supplies a list of all service names supported by the component.
*
* @return a String array with all supported services.
* @see com.sun.star.lang.XServiceInfo
*/
public String[] getSupportedServiceNames()
throws com.sun.star.uno.RuntimeException
{
return supportedServices;
}
/**
* Provides a components factory.
*
* The JavaLoader
tries to load the class first. If a
* location URL is given the RegistrationClassFinder is used to load the
* class. Otherwise the class is loaded through the Class.forName method.
To get the factory the inspects the class for the optional static member * functions __getServiceFactory resp. getServiceFactory (DEPRECATED).
* * @param implementationName the implementation (class) name of the component. * @param implementationLoaderUrl the URL of the implementation loader. Not used. * @param locationUrl points to an archive (JAR file) which contains a component. * @param xKey registry key. * @return the factory for the component (@see com.sun.star.lang.XSingleServiceFactory) * * @see com.sun.star.loader.XImplementationLoader * @see com.sun.star.comp.loader.RegistrationClassFinder */ public java.lang.Object activate( String implementationName, String implementationLoaderUrl, String locationUrl, XRegistryKey xKey ) throws CannotActivateFactoryException, com.sun.star.uno.RuntimeException { locationUrl = expand_url( locationUrl ); Object returnObject = null; Class> clazz ; DEBUG("try to get factory for " + implementationName); // First we must get the class of the implementation // 1. If a location URL is given it is assumed that this points to a JAR file. // The components class name is stored in the manifest file. // 2. If only the implementation name is given, the class is loaded with the // Class.forName() method. This is a hack to load bootstrap components. // Normally a string must no be null. try { if ( locationUrl != null ) { clazz = RegistrationClassFinder.find( locationUrl ); if (clazz == null) { throw new CannotActivateFactoryException( "Cannot activate jar " + locationUrl); } } else { clazz = Class.forName( implementationName ); if (clazz == null) { throw new CannotActivateFactoryException( "Cannot find class " + implementationName); } } } catch (java.net.MalformedURLException e) { throw new CannotActivateFactoryException(e, "Can not activate factory because " + e); } catch (java.io.IOException e) { throw new CannotActivateFactoryException(e, "Can not activate factory because " + e); } catch (java.lang.ClassNotFoundException e) { throw new CannotActivateFactoryException(e, "Can not activate factory because " + e); } Class>[] paramTypes = {String.class, XMultiServiceFactory.class, XRegistryKey.class}; Object[] params = { implementationName, multiServiceFactory, xKey }; // try to get factory from implementation class // latest style: use the public static method __getComponentFactory // - new style: use the public static method __getServiceFactory // - old style: use the public static method getServiceFactory ( DEPRECATED ) Method compfac_method = null; try { compfac_method = clazz.getMethod( "__getComponentFactory", new Class [] { String.class } ); } catch ( NoSuchMethodException noSuchMethodEx) { } catch ( SecurityException secEx) { } Method method = null; if (null == compfac_method) { try { method = clazz.getMethod("__getServiceFactory", paramTypes); } catch ( NoSuchMethodException noSuchMethodEx) { } catch ( SecurityException secEx) { } } try { if (null != compfac_method) { Object ret = compfac_method.invoke( clazz, new Object [] { implementationName } ); if (!(ret instanceof XSingleComponentFactory)) throw new CannotActivateFactoryException( "No factory object for " + implementationName ); return ret; } else { if ( method == null ) method = clazz.getMethod("getServiceFactory", paramTypes); Object oRet = method.invoke(clazz, params); if ( (oRet != null) && (oRet instanceof XSingleServiceFactory) ) returnObject = oRet; } } catch ( NoSuchMethodException e) { throw new CannotActivateFactoryException(e, "Can not activate the factory for " + implementationName); } catch ( SecurityException e) { throw new CannotActivateFactoryException(e, "Can not activate the factory for " + implementationName); } catch ( IllegalAccessException e ) { throw new CannotActivateFactoryException(e, "Can not activate the factory for " + implementationName); } catch ( IllegalArgumentException e ) { throw new CannotActivateFactoryException(e, "Can not activate the factory for " + implementationName); } catch ( InvocationTargetException e ) { throw new CannotActivateFactoryException(e, "Can not activate the factory for " + implementationName); } return returnObject; } /** * Registers the component in a registry under a given root key. * *If the component supports the optional * methods __writeRegistryServiceInfo, writeRegistryServiceInfo (DEPRECATED), * the call is delegated to that method. Otherwise a default registration * will be accomplished.
* * @param regKey the root key under that the component should be registered. * @param implementationLoaderUrl specifies the loader, the component is loaded by. * @param locationUrl points to an archive (JAR file) which contains a component. * @return true if registration is successfully - otherwise false. */ public boolean writeRegistryInfo( XRegistryKey regKey, String implementationLoaderUrl, String locationUrl ) throws CannotRegisterImplementationException, com.sun.star.uno.RuntimeException { locationUrl = expand_url( locationUrl ); boolean success = false; try { Class> clazz = RegistrationClassFinder.find(locationUrl); if (null == clazz) throw new CannotRegisterImplementationException( "Cannot determine registration class!" ); Class>[] paramTypes = { XRegistryKey.class }; Object[] params = { regKey }; Method method = clazz.getMethod("__writeRegistryServiceInfo", paramTypes); Object oRet = method.invoke(clazz, params); if ( (oRet != null) && (oRet instanceof Boolean) ) success = ((Boolean) oRet).booleanValue(); } catch (Exception e) { throw new CannotRegisterImplementationException(e, e.toString()); } return success; } /** * Supplies the factory for theJavaLoader
.
*
* @param implName the name of the desired component.
* @param multiFactory the ServiceManager
is delivered to the factory.
* @param regKey not used - can be null.
* @return the factory for the JavaLoader
.
*/
public static XSingleServiceFactory getServiceFactory( String implName,
XMultiServiceFactory multiFactory,
XRegistryKey regKey)
{
if ( implName.equals(JavaLoader.class.getName()) )
return new JavaLoaderFactory( multiFactory );
return null;
}
/**
* Registers the JavaLoader
at the registry.
*
* @param regKey root key under which the JavaLoader
should be registered.
* @return true if registration succeeded - otherwise false.
*/
public static boolean writeRegistryServiceInfo(XRegistryKey regKey) {
boolean result = false;
try {
XRegistryKey newKey = regKey.createKey("/" + JavaLoader.class.getName() + "/UNO/SERVICE");
for (String supportedService : supportedServices) {
newKey.createKey(supportedService);
}
result = true;
} catch (Exception ex) {
if (DEBUG) System.err.println(">>>JavaLoader.writeRegistryServiceInfo " + ex);
}
return result;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */