Cleanup: Move files to ridljar
These files are now part of ridl.jar instead of jurt.jar,
so move them accordingly.
Follow-up cleanup for ae855bf481
Change-Id: I01df60d99f5296b6252b260f52160c3e62f4b8dc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88007
Tested-by: Jenkins
Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt@cib.de>
This commit is contained in:
+54
-54
@@ -33,6 +33,51 @@ $(eval $(call gb_Jar_add_packagedirs,ridl,\
|
||||
))
|
||||
|
||||
$(eval $(call gb_Jar_add_sourcefiles,ridl,\
|
||||
ridljar/com/sun/star/comp/bridgefactory/BridgeFactory \
|
||||
ridljar/com/sun/star/comp/connections/Acceptor \
|
||||
ridljar/com/sun/star/comp/connections/Connector \
|
||||
ridljar/com/sun/star/comp/connections/ConstantInstanceProvider \
|
||||
ridljar/com/sun/star/comp/connections/Implementation \
|
||||
ridljar/com/sun/star/comp/connections/PipedConnection \
|
||||
ridljar/com/sun/star/comp/loader/FactoryHelper \
|
||||
ridljar/com/sun/star/comp/loader/JavaLoader \
|
||||
ridljar/com/sun/star/comp/loader/JavaLoaderFactory \
|
||||
ridljar/com/sun/star/comp/loader/RegistrationClassFinder \
|
||||
ridljar/com/sun/star/comp/servicemanager/ServiceManager \
|
||||
ridljar/com/sun/star/comp/urlresolver/UrlResolver \
|
||||
ridljar/com/sun/star/lib/connections/pipe/PipeConnection \
|
||||
ridljar/com/sun/star/lib/connections/pipe/pipeAcceptor \
|
||||
ridljar/com/sun/star/lib/connections/pipe/pipeConnector \
|
||||
ridljar/com/sun/star/lib/connections/socket/ConnectionDescriptor \
|
||||
ridljar/com/sun/star/lib/connections/socket/SocketConnection \
|
||||
ridljar/com/sun/star/lib/connections/socket/socketAcceptor \
|
||||
ridljar/com/sun/star/lib/connections/socket/socketConnector \
|
||||
ridljar/com/sun/star/lib/uno/Proxy \
|
||||
ridljar/com/sun/star/lib/uno/bridges/java_remote/BridgedObject \
|
||||
ridljar/com/sun/star/lib/uno/bridges/java_remote/ProxyFactory \
|
||||
ridljar/com/sun/star/lib/uno/bridges/java_remote/RequestHandler \
|
||||
ridljar/com/sun/star/lib/uno/bridges/java_remote/XConnectionInputStream_Adapter \
|
||||
ridljar/com/sun/star/lib/uno/bridges/java_remote/XConnectionOutputStream_Adapter \
|
||||
ridljar/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge \
|
||||
ridljar/com/sun/star/lib/uno/environments/java/java_environment \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/IProtocol \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/IReceiver \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/IThreadPool \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/JavaThreadPool \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/JavaThreadPoolFactory \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/Job \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/JobQueue \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/Message \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/NativeThreadPool \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/ThreadId \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/ThreadPoolManager \
|
||||
ridljar/com/sun/star/lib/uno/environments/remote/remote_environment \
|
||||
ridljar/com/sun/star/lib/uno/protocols/urp/Cache \
|
||||
ridljar/com/sun/star/lib/uno/protocols/urp/Marshal \
|
||||
ridljar/com/sun/star/lib/uno/protocols/urp/PendingRequests \
|
||||
ridljar/com/sun/star/lib/uno/protocols/urp/Unmarshal \
|
||||
ridljar/com/sun/star/lib/uno/protocols/urp/UrpMessage \
|
||||
ridljar/com/sun/star/lib/uno/protocols/urp/urp \
|
||||
ridljar/com/sun/star/lib/uno/typedesc/FieldDescription \
|
||||
ridljar/com/sun/star/lib/uno/typedesc/MemberDescriptionHelper \
|
||||
ridljar/com/sun/star/lib/uno/typedesc/MethodDescription \
|
||||
@@ -43,71 +88,26 @@ $(eval $(call gb_Jar_add_sourcefiles,ridl,\
|
||||
ridljar/com/sun/star/lib/uno/typeinfo/MethodTypeInfo \
|
||||
ridljar/com/sun/star/lib/uno/typeinfo/ParameterTypeInfo \
|
||||
ridljar/com/sun/star/lib/uno/typeinfo/TypeInfo \
|
||||
ridljar/com/sun/star/lib/util/AsynchronousFinalizer \
|
||||
ridljar/com/sun/star/lib/util/DisposeListener \
|
||||
ridljar/com/sun/star/lib/util/DisposeNotifier \
|
||||
ridljar/com/sun/star/lib/util/NativeLibraryLoader \
|
||||
ridljar/com/sun/star/lib/util/StringHelper \
|
||||
ridljar/com/sun/star/lib/util/UrlToFileMapper \
|
||||
ridljar/com/sun/star/lib/util/WeakMap \
|
||||
ridljar/com/sun/star/uno/Any \
|
||||
ridljar/com/sun/star/uno/AnyConverter \
|
||||
ridljar/com/sun/star/uno/Ascii \
|
||||
ridljar/com/sun/star/uno/AsciiString \
|
||||
ridljar/com/sun/star/uno/Enum \
|
||||
ridljar/com/sun/star/uno/IBridge \
|
||||
ridljar/com/sun/star/uno/IEnvironment \
|
||||
ridljar/com/sun/star/uno/IMapping \
|
||||
ridljar/com/sun/star/uno/IQueryInterface \
|
||||
ridljar/com/sun/star/uno/MappingException \
|
||||
ridljar/com/sun/star/uno/Type \
|
||||
ridljar/com/sun/star/uno/UnoRuntime \
|
||||
jurt/com/sun/star/comp/bridgefactory/BridgeFactory \
|
||||
jurt/com/sun/star/comp/connections/Acceptor \
|
||||
jurt/com/sun/star/comp/connections/Connector \
|
||||
jurt/com/sun/star/comp/connections/ConstantInstanceProvider \
|
||||
jurt/com/sun/star/comp/connections/Implementation \
|
||||
jurt/com/sun/star/comp/connections/PipedConnection \
|
||||
jurt/com/sun/star/comp/loader/FactoryHelper \
|
||||
jurt/com/sun/star/comp/loader/JavaLoader \
|
||||
jurt/com/sun/star/comp/loader/JavaLoaderFactory \
|
||||
jurt/com/sun/star/comp/loader/RegistrationClassFinder \
|
||||
jurt/com/sun/star/comp/servicemanager/ServiceManager \
|
||||
jurt/com/sun/star/comp/urlresolver/UrlResolver \
|
||||
jurt/com/sun/star/lib/connections/pipe/PipeConnection \
|
||||
jurt/com/sun/star/lib/connections/pipe/pipeAcceptor \
|
||||
jurt/com/sun/star/lib/connections/pipe/pipeConnector \
|
||||
jurt/com/sun/star/lib/connections/socket/ConnectionDescriptor \
|
||||
jurt/com/sun/star/lib/connections/socket/SocketConnection \
|
||||
jurt/com/sun/star/lib/connections/socket/socketAcceptor \
|
||||
jurt/com/sun/star/lib/connections/socket/socketConnector \
|
||||
jurt/com/sun/star/lib/uno/Proxy \
|
||||
jurt/com/sun/star/lib/uno/bridges/java_remote/BridgedObject \
|
||||
jurt/com/sun/star/lib/uno/bridges/java_remote/ProxyFactory \
|
||||
jurt/com/sun/star/lib/uno/bridges/java_remote/RequestHandler \
|
||||
jurt/com/sun/star/lib/uno/bridges/java_remote/XConnectionInputStream_Adapter \
|
||||
jurt/com/sun/star/lib/uno/bridges/java_remote/XConnectionOutputStream_Adapter \
|
||||
jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge \
|
||||
jurt/com/sun/star/lib/uno/environments/java/java_environment \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/IProtocol \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/IReceiver \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/IThreadPool \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/JavaThreadPool \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/JavaThreadPoolFactory \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/Job \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/JobQueue \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/Message \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/NativeThreadPool \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/ThreadId \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/ThreadPoolManager \
|
||||
jurt/com/sun/star/lib/uno/environments/remote/remote_environment \
|
||||
jurt/com/sun/star/lib/uno/protocols/urp/Cache \
|
||||
jurt/com/sun/star/lib/uno/protocols/urp/Marshal \
|
||||
jurt/com/sun/star/lib/uno/protocols/urp/PendingRequests \
|
||||
jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal \
|
||||
jurt/com/sun/star/lib/uno/protocols/urp/UrpMessage \
|
||||
jurt/com/sun/star/lib/uno/protocols/urp/urp \
|
||||
jurt/com/sun/star/lib/util/AsynchronousFinalizer \
|
||||
jurt/com/sun/star/lib/util/NativeLibraryLoader \
|
||||
jurt/com/sun/star/lib/util/StringHelper \
|
||||
jurt/com/sun/star/lib/util/UrlToFileMapper \
|
||||
jurt/com/sun/star/uno/AnyConverter \
|
||||
jurt/com/sun/star/uno/Ascii \
|
||||
jurt/com/sun/star/uno/AsciiString \
|
||||
jurt/com/sun/star/uno/MappingException \
|
||||
jurt/com/sun/star/uno/WeakReference \
|
||||
ridljar/com/sun/star/uno/WeakReference \
|
||||
))
|
||||
|
||||
# vim:set noet sw=4 ts=4:
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/* -*- 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.bridgefactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.star.bridge.BridgeExistsException;
|
||||
import com.sun.star.bridge.XBridge;
|
||||
import com.sun.star.bridge.XBridgeFactory;
|
||||
import com.sun.star.bridge.XInstanceProvider;
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
import com.sun.star.uno.IBridge;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
|
||||
/**
|
||||
* The BridgeFactory class implements the <code>XBridgeFactory</code> Interface.
|
||||
*
|
||||
* <p>It wraps the <code>UnoRuntime#getBridgeByName</code>method and delivers a
|
||||
* XBridge component.</p>
|
||||
*
|
||||
* <p>This component is only usable for remote bridges.</p>
|
||||
*
|
||||
* @see com.sun.star.uno.UnoRuntime
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class BridgeFactory implements XBridgeFactory/*, XEventListener*/ {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* The name of the service, the <code>JavaLoader</code> accesses this through
|
||||
* reflection.
|
||||
*/
|
||||
public static final String __serviceName = "com.sun.star.bridge.BridgeFactory";
|
||||
|
||||
/**
|
||||
* Gives a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is desired.
|
||||
* @param multiFactory the service manager to be uses if needed.
|
||||
* @param regKey the registryKey.
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
|
||||
if (implName.equals(BridgeFactory.class.getName()) )
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(BridgeFactory.class,
|
||||
multiFactory,
|
||||
regKey);
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a remote bridge and memorizes it under <code>sName</code>.
|
||||
*
|
||||
* @param sName the name to memorize the bridge.
|
||||
* @param sProtocol the protocol the bridge should use.
|
||||
* @param anInstanceProvider the instance provider.
|
||||
* @return the bridge.
|
||||
*
|
||||
* @see com.sun.star.bridge.XBridgeFactory
|
||||
*/
|
||||
public XBridge createBridge(String sName, String sProtocol, XConnection aConnection, XInstanceProvider anInstanceProvider) throws
|
||||
BridgeExistsException,
|
||||
com.sun.star.lang.IllegalArgumentException,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
boolean hasName = sName.length() != 0;
|
||||
Object context = hasName ? sName : new UniqueToken();
|
||||
// UnoRuntime.getBridgeByName internally uses context.toString() to
|
||||
// distinguish bridges, so the result of
|
||||
// new UniqueToken().toString() might clash with an explicit
|
||||
// sName.toString(), but the UnoRuntime bridge management is
|
||||
// obsolete anyway and should be removed
|
||||
|
||||
// do not create a new bridge, if one already exists
|
||||
if (hasName) {
|
||||
IBridge iBridges[] = UnoRuntime.getBridges();
|
||||
for(int i = 0; i < iBridges.length; ++ i) {
|
||||
XBridge xBridge = UnoRuntime.queryInterface(XBridge.class, iBridges[i]);
|
||||
|
||||
if(xBridge != null && xBridge.getName().equals(sName)) {
|
||||
throw new BridgeExistsException(sName + " already exists");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XBridge xBridge;
|
||||
|
||||
try {
|
||||
IBridge iBridge = UnoRuntime.getBridgeByName("java", context, "remote", context, hasName ? new Object[]{sProtocol, aConnection, anInstanceProvider, sName} : new Object[]{sProtocol, aConnection, anInstanceProvider});
|
||||
|
||||
xBridge = UnoRuntime.queryInterface(XBridge.class, iBridge);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new com.sun.star.lang.IllegalArgumentException(e, e.getMessage());
|
||||
}
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".createBridge:" + sName + " " + sProtocol + " " + aConnection + " " + anInstanceProvider + " " + xBridge);
|
||||
|
||||
return xBridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a remote bridge which must already exist.
|
||||
*
|
||||
* @param sName the name of the bridge.
|
||||
* @return the bridge.
|
||||
* @see com.sun.star.bridge.XBridgeFactory
|
||||
*/
|
||||
public XBridge getBridge(String sName) throws com.sun.star.uno.RuntimeException {
|
||||
XBridge xBridge = null;
|
||||
|
||||
IBridge iBridges[] = UnoRuntime.getBridges();
|
||||
for(int i = 0; i < iBridges.length; ++ i) {
|
||||
xBridge = UnoRuntime.queryInterface(XBridge.class, iBridges[i]);
|
||||
|
||||
if(xBridge != null) {
|
||||
if(xBridge.getName().equals(sName))
|
||||
break;
|
||||
|
||||
else
|
||||
xBridge = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".getBridge:" + sName + " " + xBridge);
|
||||
|
||||
return xBridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives all created bridges.
|
||||
*
|
||||
* @return the bridges.
|
||||
* @see com.sun.star.bridge.XBridgeFactory
|
||||
*/
|
||||
public synchronized XBridge[] getExistingBridges() throws com.sun.star.uno.RuntimeException {
|
||||
ArrayList<XBridge> vector = new ArrayList<XBridge>();
|
||||
|
||||
IBridge iBridges[] = UnoRuntime.getBridges();
|
||||
for(int i = 0; i < iBridges.length; ++ i) {
|
||||
XBridge xBridge = UnoRuntime.queryInterface(XBridge.class, iBridges[i]);
|
||||
|
||||
if(xBridge != null)
|
||||
vector.add(xBridge);
|
||||
}
|
||||
|
||||
XBridge xBridges[]= new XBridge[vector.size()];
|
||||
for(int i = 0; i < vector.size(); ++ i)
|
||||
xBridges[i] = vector.get(i);
|
||||
|
||||
return xBridges;
|
||||
}
|
||||
|
||||
private static final class UniqueToken {
|
||||
public UniqueToken() {
|
||||
synchronized (UniqueToken.class) {
|
||||
token = counter.toString();
|
||||
counter = counter.add(BigInteger.ONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object.
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
* @see java.lang.Object#toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return token;
|
||||
}
|
||||
|
||||
private final String token;
|
||||
private static BigInteger counter = BigInteger.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,153 @@
|
||||
/* -*- 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.connections;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.AlreadyAcceptingException;
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.XAcceptor;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XAcceptor</code> interface.
|
||||
*
|
||||
* <p>The <code>Acceptor</code> is a general component, that uses less general
|
||||
* components (like <code>com.sun.star.connection.socketAcceptor</code>) to
|
||||
* implement its functionality.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*
|
||||
* @since UDK 1.0
|
||||
*/
|
||||
public final class Acceptor implements XAcceptor {
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> accesses this through reflection.</p>
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static final String __serviceName
|
||||
= "com.sun.star.connection.Acceptor";
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is
|
||||
* requested.
|
||||
* @param multiFactory the service manager to be used (if needed).
|
||||
* @param regKey the registry key.
|
||||
* @return an <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(
|
||||
String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
|
||||
{
|
||||
return implName.equals(Acceptor.class.getName())
|
||||
? FactoryHelper.getServiceFactory(Acceptor.class, __serviceName,
|
||||
multiFactory, regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Acceptor</code> that uses the given service
|
||||
* factory to create a specific <code>XAcceptor</code>.
|
||||
*
|
||||
* @param serviceFactory the service factory to use.
|
||||
*/
|
||||
public Acceptor(XMultiServiceFactory serviceFactory) {
|
||||
this.serviceFactory = serviceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a connection request via the given connection type.
|
||||
*
|
||||
* <p>This call blocks until a connection has been established.</p>
|
||||
*
|
||||
* <p>The connection description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>).
|
||||
* The specific <code>XAcceptor</code> implementation is instantiated
|
||||
* through the service factory as
|
||||
* <code>com.sun.star.connection.<var>type</var>Acceptor</code> (with
|
||||
* <code><var>type</var></code> in lower case).</p>
|
||||
*
|
||||
* @param connectionDescription the description of the connection.
|
||||
* @return an <code>XConnection</code> to the client.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
*/
|
||||
public XConnection accept(String connectionDescription) throws
|
||||
AlreadyAcceptingException, ConnectionSetupException,
|
||||
com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
if (DEBUG) {
|
||||
System.err.println("##### " + getClass().getName() + ".accept("
|
||||
+ connectionDescription + ")");
|
||||
}
|
||||
XAcceptor acc;
|
||||
synchronized (this) {
|
||||
if (acceptor == null) {
|
||||
acceptor = (XAcceptor) Implementation.getConnectionService(
|
||||
serviceFactory, connectionDescription, XAcceptor.class,
|
||||
"Acceptor");
|
||||
acceptingDescription = connectionDescription;
|
||||
} else if (!connectionDescription.equals(acceptingDescription)) {
|
||||
throw new AlreadyAcceptingException(acceptingDescription
|
||||
+ " vs. "
|
||||
+ connectionDescription);
|
||||
}
|
||||
acc = acceptor;
|
||||
}
|
||||
return acc.accept(connectionDescription);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor#stopAccepting
|
||||
*/
|
||||
public void stopAccepting() {
|
||||
XAcceptor acc;
|
||||
synchronized (this) {
|
||||
acc = acceptor;
|
||||
}
|
||||
acc.stopAccepting();
|
||||
}
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final XMultiServiceFactory serviceFactory;
|
||||
|
||||
private XAcceptor acceptor = null;
|
||||
private String acceptingDescription;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/* -*- 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.connections;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.NoConnectException;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnector;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XConnector</code> interface.
|
||||
*
|
||||
* <p>The <code>Connector</code> is a general component, that uses less general
|
||||
* components (like <code>com.sun.star.connection.socketConnector</code>) to
|
||||
* implement its functionality.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*
|
||||
* @since UDK 1.0
|
||||
*/
|
||||
public class Connector implements XConnector {
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> accesses this through reflection.</p>
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static final String __serviceName
|
||||
= "com.sun.star.connection.Connector";
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is
|
||||
* requested.
|
||||
* @param multiFactory the service manager to be used (if needed).
|
||||
* @param regKey the registry key.
|
||||
* @return an <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(
|
||||
String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
|
||||
{
|
||||
return implName.equals(Connector.class.getName())
|
||||
? FactoryHelper.getServiceFactory(Connector.class, __serviceName,
|
||||
multiFactory, regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Connector</code> that uses the given service
|
||||
* factory to create a specific <code>XConnector</code>.
|
||||
*
|
||||
* @param serviceFactory the service factory to use.
|
||||
*/
|
||||
public Connector(XMultiServiceFactory serviceFactory) {
|
||||
this.serviceFactory = serviceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects via the given connection type to a waiting server.
|
||||
*
|
||||
* <p>The connection description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>).
|
||||
* The specific <code>XConnector</code> implementation is instantiated
|
||||
* through the service factory as
|
||||
* <code>com.sun.star.connection.<var>type</var>Connector</code> (with
|
||||
* <code><var>type</var></code> in lower case).</p>
|
||||
*
|
||||
* @param connectionDescription the description of the connection.
|
||||
* @return an <code>XConnection</code> to the server.
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
*/
|
||||
public synchronized XConnection connect(String connectionDescription)
|
||||
throws NoConnectException, ConnectionSetupException
|
||||
{
|
||||
if (DEBUG) {
|
||||
System.err.println("##### " + getClass().getName() + ".connect("
|
||||
+ connectionDescription + ")");
|
||||
}
|
||||
if (connected) {
|
||||
throw new ConnectionSetupException("already connected");
|
||||
}
|
||||
XConnection con
|
||||
= ((XConnector) Implementation.getConnectionService(
|
||||
serviceFactory, connectionDescription, XConnector.class,
|
||||
"Connector")).connect(connectionDescription);
|
||||
connected = true;
|
||||
return con;
|
||||
}
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final XMultiServiceFactory serviceFactory;
|
||||
|
||||
private boolean connected = false;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,118 @@
|
||||
/* -*- 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.connections;
|
||||
|
||||
import com.sun.star.bridge.XInstanceProvider;
|
||||
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>ConstantInstanceProvider</code> is a component
|
||||
* that implements the <code>XInstanceProvider</code> Interface.
|
||||
*
|
||||
* @see com.sun.star.bridge.XBridge
|
||||
* @see com.sun.star.bridge.XBridgeFactory
|
||||
* @see com.sun.star.bridge.XInstanceProvider
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class ConstantInstanceProvider implements XInstanceProvider {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* The name of the service, the <code>JavaLoader</code> accesses this through
|
||||
* reflection.
|
||||
*/
|
||||
private static final String __serviceName = "com.sun.star.comp.connection.InstanceProvider";
|
||||
|
||||
/**
|
||||
* Gives a factory for creating the service.
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is desired.
|
||||
* @param multiFactory the service manager to be uses if needed.
|
||||
* @param regKey the registryKey.
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
|
||||
if (implName.equals(ConstantInstanceProvider.class.getName()) )
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(ConstantInstanceProvider.class,
|
||||
__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
protected XMultiServiceFactory _serviceManager;
|
||||
protected String _serviceName;
|
||||
protected Object _instance;
|
||||
|
||||
|
||||
public void setInstance(String serviceName) throws com.sun.star.uno.Exception {
|
||||
_instance = _serviceManager.createInstance(serviceName);
|
||||
_serviceName = serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ConstantInstanceProvider</code>.
|
||||
* <p>Uses the provided ServiceManager as the provided instance.</p>
|
||||
*
|
||||
* @param serviceManager the provided service manager
|
||||
*/
|
||||
public ConstantInstanceProvider(XMultiServiceFactory serviceManager) {
|
||||
_serviceManager = serviceManager;
|
||||
|
||||
_serviceName = "SERVICEMANAGER";
|
||||
_instance = serviceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives an object for the passed instance name.
|
||||
*
|
||||
* @return the desired instance
|
||||
* @param sInstanceName the name of the desired instance
|
||||
*/
|
||||
public Object getInstance(String sInstanceName) throws com.sun.star.container.NoSuchElementException, com.sun.star.uno.RuntimeException {
|
||||
Object result = sInstanceName.equals(_serviceName) ? _instance : null;
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".getInstance(" + sInstanceName + "):" + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,95 @@
|
||||
/* -*- 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.connections;
|
||||
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
/**
|
||||
* Helper class for <code>Acceptor</code> and <code>Connector</code>.
|
||||
*/
|
||||
final class Implementation {
|
||||
/**
|
||||
* Instantiate a service for a given connection type.
|
||||
*
|
||||
* @param factory the service factory used to instantiate the requested
|
||||
* service.
|
||||
* @param description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>).
|
||||
* The specific service implementation is instantiated through the
|
||||
* service factory as
|
||||
* <code>com.sun.star.connection.<var>type</var>service<var></var><!--
|
||||
* --></code>
|
||||
* (with <code><var>type</var></code> in lower case, and
|
||||
* <code><var>service</var></code> either <code>Acceptor</code> or
|
||||
* <code>Connector</code>).
|
||||
* @param serviceClass the IDL interface type for which to query the
|
||||
* requested service.
|
||||
* @param serviceType must be either <code>Acceptor</code> or
|
||||
* <code>Connector</code>.
|
||||
* @return an instance of the requested service. Never returns
|
||||
* <code>null</code>.
|
||||
* @throws ConnectionSetupException if the requested service can not be
|
||||
* found, or cannot be instantiated.
|
||||
*/
|
||||
public static Object getConnectionService(XMultiServiceFactory factory,
|
||||
String description,
|
||||
Class<?> serviceClass,
|
||||
String serviceType)
|
||||
throws ConnectionSetupException
|
||||
{
|
||||
int i = description.indexOf(',');
|
||||
String type
|
||||
= (i < 0 ? description : description.substring(0, i)).toLowerCase();
|
||||
Object service = null;
|
||||
try {
|
||||
service = UnoRuntime.queryInterface(
|
||||
serviceClass,
|
||||
factory.createInstance("com.sun.star.connection." + type
|
||||
+ serviceType));
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (com.sun.star.uno.Exception e) {
|
||||
}
|
||||
if (service == null) {
|
||||
// As a fallback, also try to instantiate the service from the
|
||||
// com.sun.star.lib.connections package structure:
|
||||
try {
|
||||
service
|
||||
= Class.forName("com.sun.star.lib.connections." + type
|
||||
+ "." + type + serviceType).newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (InstantiationException e) {
|
||||
}
|
||||
}
|
||||
if (service == null) {
|
||||
throw new ConnectionSetupException("no " + serviceType + " for "
|
||||
+ type);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
private Implementation() {} // do not instantiate
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,259 @@
|
||||
/* -*- 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.connections;
|
||||
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
/**
|
||||
* The <code>PipedConnection</code> is a component that implements the
|
||||
* <code>XConnection</code> Interface.
|
||||
* <p>It is useful for <code>Thread</code> communication in one Process.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class PipedConnection implements XConnection {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* The name of the service, the <code>JavaLoader</code> accesses this through
|
||||
* reflection.
|
||||
*/
|
||||
private static final String __serviceName = "com.sun.star.connection.PipedConnection";
|
||||
|
||||
/**
|
||||
* Gives a factory for creating the service.
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is desired.
|
||||
* @param multiFactory the service manager to be uses if needed.
|
||||
* @param regKey the registryKey.
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
|
||||
if (implName.equals(PipedConnection.class.getName()) )
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(PipedConnection.class,
|
||||
__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of time in milliseconds, to wait to see check the buffers.
|
||||
*/
|
||||
protected static final int __waitTime = 10000;
|
||||
|
||||
protected byte _buffer[] = new byte[4096];
|
||||
protected int _in,
|
||||
_out;
|
||||
protected boolean _closed;
|
||||
protected PipedConnection _otherSide;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>PipedConnection</code>, sees if there is another
|
||||
* side, which it should be connected to.
|
||||
*
|
||||
* @param args Another side could be in index 0.
|
||||
*/
|
||||
public PipedConnection(Object args[]) throws com.sun.star.uno.RuntimeException {
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated");
|
||||
|
||||
_otherSide = (args.length == 1) ? (PipedConnection)args[0] : null;
|
||||
if(_otherSide != null) {
|
||||
if(_otherSide == this)
|
||||
throw new RuntimeException("can not connect to myself");
|
||||
|
||||
_otherSide._otherSide = this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a private method, used to communicate internal in the pipe.
|
||||
*/
|
||||
private synchronized void receive(byte aData[]) throws com.sun.star.io.IOException {
|
||||
int bytesWritten = 0;
|
||||
|
||||
if(DEBUG) System.err.println("##### PipedConnection.receive - bytes:" + aData.length + " at:" + _out);
|
||||
|
||||
while(bytesWritten < aData.length) {
|
||||
// wait until it is not full anymore
|
||||
while(_out == (_in - 1) || (_in == 0 && _out == _buffer.length - 1)) {
|
||||
try {
|
||||
notify(); // the buffer is full, signal it
|
||||
|
||||
wait(__waitTime);
|
||||
}
|
||||
catch(InterruptedException interruptedException) {
|
||||
throw new com.sun.star.io.IOException(interruptedException);
|
||||
}
|
||||
}
|
||||
|
||||
if(_closed) throw new com.sun.star.io.IOException("connection has been closed");
|
||||
|
||||
int bytes ;
|
||||
|
||||
if(_out < _in) {
|
||||
bytes = Math.min(aData.length - bytesWritten, _in - _out - 1);
|
||||
|
||||
System.arraycopy(aData, bytesWritten, _buffer, _out, bytes);
|
||||
}
|
||||
else {
|
||||
if(_in > 0){
|
||||
bytes = Math.min(aData.length - bytesWritten, _buffer.length - _out);
|
||||
}
|
||||
else {
|
||||
bytes = Math.min(aData.length - bytesWritten, _buffer.length - _out - 1);
|
||||
}
|
||||
|
||||
System.arraycopy(aData, bytesWritten, _buffer, _out, bytes);
|
||||
}
|
||||
|
||||
bytesWritten += bytes;
|
||||
_out += bytes;
|
||||
if(_out >= _buffer.length)
|
||||
_out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the required number of bytes.
|
||||
*
|
||||
* @param aReadBytes the out parameter, where the bytes have to be placed.
|
||||
* @param nBytesToRead the number of bytes to read.
|
||||
* @return the number of bytes read.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#read
|
||||
*/
|
||||
public synchronized int read(/*OUT*/byte[][] aReadBytes, int nBytesToRead) throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
|
||||
aReadBytes[0] = new byte[nBytesToRead];
|
||||
|
||||
if(DEBUG) System.err.println("##### PipedConnection.read - bytes:" + nBytesToRead + " at:" + _in);
|
||||
|
||||
// loop while not all bytes read or when closed but there is still data
|
||||
while(nBytesToRead > 0 && (_in != _out || !_closed)) {
|
||||
while(_in == _out && !_closed) {
|
||||
try {
|
||||
notify(); // the buffer is empty, signal it
|
||||
|
||||
wait(__waitTime); // we wait for data or for the pipe to be closed
|
||||
}
|
||||
catch(InterruptedException interruptedException) {
|
||||
throw new com.sun.star.io.IOException(interruptedException);
|
||||
}
|
||||
}
|
||||
|
||||
if(_in < _out) {
|
||||
int bytes = Math.min(nBytesToRead, _out - _in);
|
||||
|
||||
System.arraycopy(_buffer, _in, aReadBytes[0], aReadBytes[0].length - nBytesToRead, bytes);
|
||||
|
||||
nBytesToRead -= bytes;
|
||||
_in += bytes;
|
||||
}
|
||||
else if(_in > _out) {
|
||||
int bytes = Math.min(nBytesToRead, _buffer.length - _in);
|
||||
|
||||
System.arraycopy(_buffer, _in, aReadBytes[0], aReadBytes[0].length - nBytesToRead, bytes);
|
||||
|
||||
nBytesToRead -= bytes;
|
||||
_in += bytes;
|
||||
if(_in >= _buffer.length)
|
||||
_in = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(nBytesToRead > 0) { // not all bytes read
|
||||
byte tmp[] = new byte[aReadBytes[0].length - nBytesToRead];
|
||||
System.arraycopy(aReadBytes[0], 0, tmp, 0, tmp.length);
|
||||
|
||||
aReadBytes[0] = tmp;
|
||||
}
|
||||
|
||||
return aReadBytes[0].length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write bytes.
|
||||
*
|
||||
* @param aData the bytes to write.
|
||||
* @see com.sun.star.connection.XConnection#write
|
||||
*/
|
||||
public void write(byte aData[]) throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
|
||||
_otherSide.receive(aData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the buffer, notifies if necessary the other side that new data has
|
||||
* arrived.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#flush
|
||||
*/
|
||||
public void flush() throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
|
||||
synchronized(_otherSide) {
|
||||
_otherSide.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the pipe.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#close()
|
||||
*/
|
||||
public synchronized void close() throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
|
||||
if(!_closed) {
|
||||
_closed = true;
|
||||
|
||||
_otherSide.close();
|
||||
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a description of this pipe.
|
||||
*
|
||||
* @return the description.
|
||||
* @see com.sun.star.connection.XConnection#getDescription
|
||||
*/
|
||||
public String getDescription() throws com.sun.star.uno.RuntimeException {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,502 @@
|
||||
/* -*- 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.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.lang.XInitialization;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.lang.XSingleComponentFactory;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.Type;
|
||||
|
||||
|
||||
/**
|
||||
* The purpose of this class to help component implementation.
|
||||
*
|
||||
* <p>This class has default implementations for <code>getServiceFactory</code>
|
||||
* and <code>writeRegistryServiceInfo</code>.</p>
|
||||
*
|
||||
* @see com.sun.star.lang.XMultiServiceFactory
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
* @see com.sun.star.lang.XSingleServiceFactory
|
||||
* @see com.sun.star.registry.XRegistryKey
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class FactoryHelper {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
// the factory
|
||||
protected static class Factory
|
||||
implements XSingleServiceFactory, XSingleComponentFactory, XServiceInfo,
|
||||
XTypeProvider {
|
||||
|
||||
protected XMultiServiceFactory _xMultiServiceFactory;
|
||||
protected XRegistryKey _xRegistryKey;
|
||||
protected int _nCode;
|
||||
protected Constructor<?> _constructor;
|
||||
protected String _implName;
|
||||
protected String _serviceName;
|
||||
|
||||
protected Factory(Class<?> implClass,
|
||||
String serviceName,
|
||||
XMultiServiceFactory xMultiServiceFactory,
|
||||
XRegistryKey xRegistryKey)
|
||||
{
|
||||
_xMultiServiceFactory = xMultiServiceFactory;
|
||||
_xRegistryKey = xRegistryKey;
|
||||
_implName = implClass.getName();
|
||||
_serviceName = serviceName;
|
||||
|
||||
Constructor<?> constructors[] = implClass.getConstructors();
|
||||
for(int i = 0; i < constructors.length && _constructor == null; ++i) {
|
||||
Class<?> parameters[] = constructors[i].getParameterTypes();
|
||||
|
||||
if(parameters.length == 3
|
||||
&& parameters[0].equals(XComponentContext.class)
|
||||
&& parameters[1].equals(XRegistryKey.class)
|
||||
&& parameters[2].equals(Object[].class)) {
|
||||
_nCode = 0;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 2
|
||||
&& parameters[0].equals(XComponentContext.class)
|
||||
&& parameters[1].equals(XRegistryKey.class)) {
|
||||
_nCode = 1;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 2
|
||||
&& parameters[0].equals(XComponentContext.class)
|
||||
&& parameters[1].equals(Object[].class)) {
|
||||
_nCode = 2;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 1
|
||||
&& parameters[0].equals(XComponentContext.class)) {
|
||||
_nCode = 3;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
// depr
|
||||
else if(parameters.length == 3
|
||||
&& parameters[0].equals(XMultiServiceFactory.class)
|
||||
&& parameters[1].equals(XRegistryKey.class)
|
||||
&& parameters[2].equals(Object[].class)) {
|
||||
_nCode = 4;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 2
|
||||
&& parameters[0].equals(XMultiServiceFactory.class)
|
||||
&& parameters[1].equals(XRegistryKey.class)) {
|
||||
_nCode = 5;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 2
|
||||
&& parameters[0].equals(XMultiServiceFactory.class)
|
||||
&& parameters[1].equals(Object[].class)) {
|
||||
_nCode = 6;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 1
|
||||
&& parameters[0].equals(XMultiServiceFactory.class)) {
|
||||
_nCode = 7;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 1
|
||||
&& parameters[0].equals(Object[].class)) {
|
||||
_nCode = 8;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
else if(parameters.length == 0) {
|
||||
_nCode = 9;
|
||||
_constructor = constructors[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(_constructor == null) // have not found a usable constructor
|
||||
throw new com.sun.star.uno.RuntimeException(getClass().getName() + " can not find a usable constructor");
|
||||
}
|
||||
|
||||
private final XMultiServiceFactory getSMgr( XComponentContext xContext )
|
||||
{
|
||||
if (xContext != null)
|
||||
{
|
||||
return UnoRuntime.queryInterface(
|
||||
XMultiServiceFactory.class, xContext.getServiceManager() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return _xMultiServiceFactory;
|
||||
}
|
||||
}
|
||||
|
||||
// XComponentContext impl
|
||||
|
||||
public Object createInstanceWithContext(
|
||||
XComponentContext xContext )
|
||||
throws com.sun.star.uno.Exception
|
||||
{
|
||||
Object args[];
|
||||
switch (_nCode)
|
||||
{
|
||||
case 0:
|
||||
args = new Object [] { xContext, _xRegistryKey, new Object[ 0 ] };
|
||||
break;
|
||||
case 1:
|
||||
args = new Object [] { xContext, _xRegistryKey };
|
||||
break;
|
||||
case 2:
|
||||
args = new Object [] { xContext, new Object[ 0 ] };
|
||||
break;
|
||||
case 3:
|
||||
args = new Object [] { xContext };
|
||||
break;
|
||||
case 4:
|
||||
args = new Object [] { getSMgr( xContext ), _xRegistryKey, new Object[ 0 ] };
|
||||
break;
|
||||
case 5:
|
||||
args = new Object [] { getSMgr( xContext ), _xRegistryKey };
|
||||
break;
|
||||
case 6:
|
||||
args = new Object [] { getSMgr( xContext ), new Object[ 0 ] };
|
||||
break;
|
||||
case 7:
|
||||
args = new Object [] { getSMgr( xContext ) };
|
||||
break;
|
||||
case 8:
|
||||
args = new Object [] { new Object[ 0 ] };
|
||||
break;
|
||||
default:
|
||||
args = new Object [ 0 ];
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
return _constructor.newInstance( args );
|
||||
} catch (InvocationTargetException invocationTargetException) {
|
||||
Throwable targetException = invocationTargetException.getCause();
|
||||
|
||||
if (targetException instanceof java.lang.RuntimeException)
|
||||
throw (java.lang.RuntimeException)targetException;
|
||||
else if (targetException instanceof com.sun.star.uno.Exception)
|
||||
throw (com.sun.star.uno.Exception)targetException;
|
||||
else if (targetException instanceof com.sun.star.uno.RuntimeException)
|
||||
throw (com.sun.star.uno.RuntimeException)targetException;
|
||||
else
|
||||
throw new com.sun.star.uno.Exception( targetException );
|
||||
} catch (IllegalAccessException illegalAccessException) {
|
||||
throw new com.sun.star.uno.Exception( illegalAccessException );
|
||||
} catch (InstantiationException instantiationException) {
|
||||
throw new com.sun.star.uno.Exception( instantiationException );
|
||||
}
|
||||
}
|
||||
|
||||
public Object createInstanceWithArgumentsAndContext(
|
||||
Object rArguments[], XComponentContext xContext )
|
||||
throws com.sun.star.uno.Exception
|
||||
{
|
||||
Object args[];
|
||||
|
||||
boolean bInitCall = true;
|
||||
switch (_nCode)
|
||||
{
|
||||
case 0:
|
||||
args = new Object [] { xContext, _xRegistryKey, rArguments };
|
||||
bInitCall = false;
|
||||
break;
|
||||
case 1:
|
||||
args = new Object [] { xContext, _xRegistryKey };
|
||||
break;
|
||||
case 2:
|
||||
args = new Object [] { xContext, rArguments };
|
||||
bInitCall = false;
|
||||
break;
|
||||
case 3:
|
||||
args = new Object [] { xContext };
|
||||
break;
|
||||
case 4:
|
||||
args = new Object [] { getSMgr( xContext ), _xRegistryKey, rArguments };
|
||||
bInitCall = false;
|
||||
break;
|
||||
case 5:
|
||||
args = new Object [] { getSMgr( xContext ), _xRegistryKey };
|
||||
break;
|
||||
case 6:
|
||||
args = new Object [] { getSMgr( xContext ), rArguments };
|
||||
bInitCall = false;
|
||||
break;
|
||||
case 7:
|
||||
args = new Object [] { getSMgr( xContext ) };
|
||||
break;
|
||||
case 8:
|
||||
args = new Object [] { rArguments };
|
||||
bInitCall = false;
|
||||
break;
|
||||
default:
|
||||
args = new Object [ 0 ];
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
Object instance = _constructor.newInstance( args );
|
||||
if (bInitCall)
|
||||
{
|
||||
XInitialization xInitialization = UnoRuntime.queryInterface(
|
||||
XInitialization.class, instance );
|
||||
if (xInitialization != null)
|
||||
{
|
||||
xInitialization.initialize( rArguments );
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
} catch (InvocationTargetException invocationTargetException) {
|
||||
Throwable targetException = invocationTargetException.getCause();
|
||||
|
||||
if (targetException instanceof java.lang.RuntimeException)
|
||||
throw (java.lang.RuntimeException)targetException;
|
||||
else if (targetException instanceof com.sun.star.uno.Exception)
|
||||
throw (com.sun.star.uno.Exception)targetException;
|
||||
else if (targetException instanceof com.sun.star.uno.RuntimeException)
|
||||
throw (com.sun.star.uno.RuntimeException)targetException;
|
||||
else
|
||||
throw new com.sun.star.uno.Exception( targetException );
|
||||
} catch (IllegalAccessException illegalAccessException) {
|
||||
throw new com.sun.star.uno.Exception( illegalAccessException );
|
||||
} catch (InstantiationException instantiationException) {
|
||||
throw new com.sun.star.uno.Exception( instantiationException );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the desired service.
|
||||
*
|
||||
* @return returns an instance of the desired service.
|
||||
* @see com.sun.star.lang.XSingleServiceFactory
|
||||
*/
|
||||
public Object createInstance()
|
||||
throws com.sun.star.uno.Exception,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return createInstanceWithContext( null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the desired service.
|
||||
*
|
||||
* @param args the args given to the constructor of the service.
|
||||
* @return returns an instance of the desired service.
|
||||
*
|
||||
* @see com.sun.star.lang.XSingleServiceFactory
|
||||
*/
|
||||
public Object createInstanceWithArguments(Object[] args)
|
||||
throws com.sun.star.uno.Exception,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return createInstanceWithArgumentsAndContext( args, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the supported services.
|
||||
*
|
||||
* @return returns an array of supported services.
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public String[] getSupportedServiceNames() throws com.sun.star.uno.RuntimeException {
|
||||
return new String[]{_serviceName};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the implementation name.
|
||||
*
|
||||
* @return returns the implementation name.
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public String getImplementationName() throws com.sun.star.uno.RuntimeException {
|
||||
return _implName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the given service is supported.
|
||||
*
|
||||
* @return returns true if the given service is supported.
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public boolean supportsService(String serviceName) throws com.sun.star.uno.RuntimeException {
|
||||
String services[] = getSupportedServiceNames();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for(int i = 0; i < services.length && !found; ++i)
|
||||
found = services[i].equals(serviceName);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
//XTypeProvider
|
||||
public byte[] getImplementationId()
|
||||
{
|
||||
return new byte[0];
|
||||
}
|
||||
//XTypeProvider
|
||||
public com.sun.star.uno.Type[] getTypes()
|
||||
{
|
||||
Type[] t = new Type[] {
|
||||
new Type(XSingleServiceFactory.class),
|
||||
new Type(XSingleComponentFactory.class),
|
||||
new Type(XServiceInfo.class),
|
||||
new Type(XTypeProvider.class)
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a factory for the given class.
|
||||
*
|
||||
* @param implClass the implementing class.
|
||||
* @param multiFactory the given multi service factory (service manager).
|
||||
* @param regKey the given registry key.
|
||||
* @return returns a factory.
|
||||
*
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
* @deprecated as of UDK 1.0
|
||||
*/
|
||||
@Deprecated
|
||||
public static XSingleServiceFactory getServiceFactory(Class<?> implClass,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
|
||||
try {
|
||||
Field serviceName ;
|
||||
|
||||
try {
|
||||
serviceName = implClass.getField("__serviceName");
|
||||
} catch(NoSuchFieldException noSuchFieldExceptio) {
|
||||
serviceName = implClass.getField("serviceName"); // old style
|
||||
}
|
||||
|
||||
xSingleServiceFactory = new Factory(implClass, (String)serviceName.get(null), multiFactory, regKey);
|
||||
} catch(NoSuchFieldException noSuchFieldException) {
|
||||
System.err.println("##### FactoryHelper.getServiceFactory - exception:" + noSuchFieldException);
|
||||
} catch(IllegalAccessException illegalAccessException) {
|
||||
System.err.println("##### FactoryHelper.getServiceFactory - exception:" + illegalAccessException);
|
||||
}
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a factory for the given class.
|
||||
*
|
||||
* @param implClass the implementing class.
|
||||
* @param serviceName the service name of the implementing class.
|
||||
* @param multiFactory the given multi service factory (service manager).
|
||||
* @param regKey the given registry key.
|
||||
*
|
||||
* @return returns a factory.
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public static XSingleServiceFactory getServiceFactory(Class<?> implClass,
|
||||
String serviceName,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
return new Factory(implClass, serviceName, multiFactory, regKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a factory for the given class.
|
||||
*
|
||||
* @param implClass the implementing class.
|
||||
* @return returns a factory object.
|
||||
*/
|
||||
public static Object createComponentFactory( Class<?> implClass, String serviceName )
|
||||
{
|
||||
return new Factory( implClass, serviceName, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the registration data into the registry key.
|
||||
*
|
||||
* @param implName the name of the implementing class.
|
||||
* @param serviceName the service name.
|
||||
* @param regKey the given registry key.
|
||||
* @return success.
|
||||
*
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public static boolean writeRegistryServiceInfo(String implName, String serviceName, XRegistryKey regKey) {
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
XRegistryKey newKey = regKey.createKey("/" + implName + "/UNO/SERVICES");
|
||||
|
||||
newKey.createKey(serviceName);
|
||||
|
||||
result = true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
System.err.println(">>>Connection_Impl.writeRegistryServiceInfo " + ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the registration data into the registry key.
|
||||
*
|
||||
* <p>Several services are supported.</p>
|
||||
*
|
||||
* @param impl_name name of implementation.
|
||||
* @param supported_services supported services of implementation.
|
||||
* @param xKey registry key to write to.
|
||||
* @return success.
|
||||
*/
|
||||
public static boolean writeRegistryServiceInfo(
|
||||
String impl_name, String supported_services [], XRegistryKey xKey )
|
||||
{
|
||||
try {
|
||||
XRegistryKey xNewKey = xKey.createKey( "/" + impl_name + "/UNO/SERVICES" );
|
||||
for ( int nPos = 0; nPos < supported_services.length; ++nPos ) {
|
||||
xNewKey.createKey( supported_services[ nPos ] );
|
||||
}
|
||||
return true;
|
||||
} catch (com.sun.star.registry.InvalidRegistryException exc) {
|
||||
if (DEBUG) {
|
||||
System.err.println(
|
||||
"##### " + Factory.class.getName() + ".writeRegistryServiceInfo -- exc: " +
|
||||
exc.toString() );
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,439 @@
|
||||
/* -*- 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 <code>JavaLoader</code> class provides the functionality of the
|
||||
* <code>com.sun.star.loader.Java</code> service.
|
||||
*
|
||||
* <p>Therefore the <code>JavaLoader</code> activates external UNO components
|
||||
* which are implemented in Java.</p>
|
||||
*
|
||||
* <p>The loader is used by the <code>ServiceManger</code>.</p>
|
||||
*
|
||||
* @see com.sun.star.loader.XImplementationLoader
|
||||
* @see com.sun.star.loader.Java
|
||||
* @see com.sun.star.comp.servicemanager.ServiceManager
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class JavaLoader implements XImplementationLoader,
|
||||
XServiceInfo,
|
||||
XInitialization
|
||||
{
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final void DEBUG(String dbg) {
|
||||
if (DEBUG) System.err.println( dbg );
|
||||
}
|
||||
|
||||
private static String[] supportedServices = {
|
||||
"com.sun.star.loader.Java"
|
||||
};
|
||||
|
||||
protected XMultiServiceFactory multiServiceFactory = null;
|
||||
|
||||
private XMacroExpander m_xMacroExpander = null;
|
||||
private static final String EXPAND_PROTOCOL_PREFIX = "vnd.sun.star.expand:";
|
||||
|
||||
/**
|
||||
* Expands macrofied url using the macro expander singleton.
|
||||
*/
|
||||
private String expand_url( String url ) throws RuntimeException
|
||||
{
|
||||
if (url == null || !url.startsWith( EXPAND_PROTOCOL_PREFIX )) {
|
||||
return url;
|
||||
}
|
||||
try {
|
||||
if (m_xMacroExpander == null) {
|
||||
XPropertySet xProps =
|
||||
UnoRuntime.queryInterface(
|
||||
XPropertySet.class, multiServiceFactory );
|
||||
if (xProps == null) {
|
||||
throw new com.sun.star.uno.RuntimeException(
|
||||
"service manager does not support XPropertySet!",
|
||||
this );
|
||||
}
|
||||
XComponentContext xContext = (XComponentContext)
|
||||
AnyConverter.toObject(
|
||||
new Type( XComponentContext.class ),
|
||||
xProps.getPropertyValue( "DefaultContext" ) );
|
||||
m_xMacroExpander = (XMacroExpander)AnyConverter.toObject(
|
||||
new Type( XMacroExpander.class ),
|
||||
xContext.getValueByName(
|
||||
"/singletons/com.sun.star.util.theMacroExpander" )
|
||||
);
|
||||
}
|
||||
// decode uric class chars
|
||||
String macro = URLDecoder.decode(
|
||||
StringHelper.replace(
|
||||
url.substring( EXPAND_PROTOCOL_PREFIX.length() ),
|
||||
'+', "%2B" ), "UTF-8" );
|
||||
// expand macro string
|
||||
String ret = m_xMacroExpander.expandMacros( macro );
|
||||
if (DEBUG) {
|
||||
System.err.println(
|
||||
"JavaLoader.expand_url(): " + url + " => " +
|
||||
macro + " => " + ret );
|
||||
}
|
||||
return ret;
|
||||
} catch (com.sun.star.uno.Exception exc) {
|
||||
throw new com.sun.star.uno.RuntimeException(exc,
|
||||
exc.getMessage(), this );
|
||||
} catch (java.lang.Exception exc) {
|
||||
throw new com.sun.star.uno.RuntimeException(exc,
|
||||
exc.getMessage(), this );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* <p>Creates a new instance of the <code>JavaLoader</code> class.</p>
|
||||
*/
|
||||
public JavaLoader() {}
|
||||
|
||||
/**
|
||||
* Creates a new <code>JavaLoader</code> object.
|
||||
*
|
||||
* <p>The specified <code>com.sun.star.lang.XMultiServiceFactory</code> is
|
||||
* the <code>ServiceManager</code> service which can be delivered to all
|
||||
* components the <code>JavaLoader</code> is loading.</p>
|
||||
*
|
||||
* <p>To set the <code>MultiServiceFactory</code> you can use the
|
||||
* <code>com.sun.star.lang.XInitialization</code> interface, either.</p>
|
||||
*
|
||||
* @param factory the <code>ServiceManager</code>.
|
||||
* @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 <code>com.sun.star.lang.XMultiServiceFactory</code> should be set at
|
||||
* the loader.
|
||||
*
|
||||
* @param args - the first parameter (args[0]) specifies the <code>ServiceManager</code>.
|
||||
* @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.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> 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.</p>
|
||||
*
|
||||
* <p>To get the factory the inspects the class for the optional static member
|
||||
* functions __getServiceFactory resp. getServiceFactory (DEPRECATED).</p>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* <p>If the component supports the optional
|
||||
* methods __writeRegistryServiceInfo, writeRegistryServiceInfo (DEPRECATED),
|
||||
* the call is delegated to that method. Otherwise a default registration
|
||||
* will be accomplished.</p>
|
||||
*
|
||||
* @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 the <code>JavaLoader</code>.
|
||||
*
|
||||
* @param implName the name of the desired component.
|
||||
* @param multiFactory the <code>ServiceManager</code> is delivered to the factory.
|
||||
* @param regKey not used - can be null.
|
||||
* @return the factory for the <code>JavaLoader</code>.
|
||||
*/
|
||||
public static XSingleServiceFactory getServiceFactory( String implName,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
if ( implName.equals(JavaLoader.class.getName()) )
|
||||
return new JavaLoaderFactory( multiFactory );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the <code>JavaLoader</code> at the registry.
|
||||
*
|
||||
* @param regKey root key under which the <code>JavaLoader</code> 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: */
|
||||
@@ -0,0 +1,90 @@
|
||||
/* -*- 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 com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
|
||||
|
||||
public class JavaLoaderFactory implements XSingleServiceFactory, XServiceInfo {
|
||||
|
||||
private static String[] supportedServices = {
|
||||
"com.sun.star.loader.Java",
|
||||
"com.sun.star.loader.Java2"
|
||||
};
|
||||
|
||||
protected XMultiServiceFactory multiServiceFactory = null;
|
||||
|
||||
public JavaLoaderFactory(XMultiServiceFactory factory) {
|
||||
multiServiceFactory = factory;
|
||||
}
|
||||
|
||||
public java.lang.Object createInstance()
|
||||
throws com.sun.star.uno.Exception,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return new JavaLoader(multiServiceFactory);
|
||||
}
|
||||
|
||||
public java.lang.Object createInstanceWithArguments( java.lang.Object[] args )
|
||||
throws com.sun.star.uno.Exception,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
JavaLoader loader = new JavaLoader();
|
||||
loader.initialize(args);
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the XServiceInfo interface.
|
||||
*/
|
||||
public String getImplementationName()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return JavaLoader.class.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the XServiceInfo interface.
|
||||
*/
|
||||
public boolean supportsService(String serviceName)
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
for (String supportedService : supportedServices) {
|
||||
if (supportedService.equals(serviceName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the XServiceInfo interface.
|
||||
*/
|
||||
public String[] getSupportedServiceNames()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return supportedServices;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,69 @@
|
||||
/* -*- 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 com.sun.star.lib.unoloader.UnoClassLoader;
|
||||
import com.sun.star.lib.util.WeakMap;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.jar.Attributes;
|
||||
|
||||
final class RegistrationClassFinder {
|
||||
public static Class<?> find(String locationUrl)
|
||||
throws ClassNotFoundException, IOException
|
||||
{
|
||||
synchronized (map) {
|
||||
Class<?> c = (Class<?>) WeakMap.getValue(map.get(locationUrl));
|
||||
if (c != null) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
URL url = new URL(locationUrl);
|
||||
Attributes attr = UnoClassLoader.getJarMainAttributes(url);
|
||||
String name = attr == null
|
||||
? null : attr.getValue("RegistrationClassName");
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
ClassLoader cl1 = RegistrationClassFinder.class.getClassLoader();
|
||||
ClassLoader cl2;
|
||||
if (cl1 instanceof UnoClassLoader) {
|
||||
cl2 = ((UnoClassLoader) cl1).getClassLoader(url, attr);
|
||||
} else {
|
||||
cl2 = URLClassLoader.newInstance(new URL[] { url }, cl1);
|
||||
}
|
||||
Class<?> c = cl2.loadClass(name);
|
||||
synchronized (map) {
|
||||
Class<?> c2 = (Class<?>) WeakMap.getValue(map.get(locationUrl));
|
||||
if (c2 != null) {
|
||||
return c2;
|
||||
}
|
||||
map.put(locationUrl, c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private RegistrationClassFinder() {} // do not instantiate
|
||||
|
||||
private static final WeakMap map = new WeakMap();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,662 @@
|
||||
/* -*- 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.servicemanager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sun.star.container.XContentEnumerationAccess;
|
||||
import com.sun.star.container.XEnumeration;
|
||||
import com.sun.star.container.XSet;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XEventListener;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XSingleComponentFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
/**
|
||||
* The <code>ServiceManager</code> class is an implementation of the
|
||||
* <code>ServiceManager</code>the central class needed for implementing or using
|
||||
* UNO components in Java.
|
||||
*
|
||||
* <p>The Methods <code>queryInterface</code> and <code>isSame</code> delegate
|
||||
* calls to the implementing objects and are used instead of casts and identity
|
||||
* comparisons.</p>
|
||||
*
|
||||
* @see com.sun.star.lang.XMultiServiceFactory
|
||||
* @see com.sun.star.container.XSet
|
||||
* @see com.sun.star.container.XContentEnumerationAccess
|
||||
* @see com.sun.star.lang.XComponent
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class ServiceManager implements XMultiServiceFactory,
|
||||
XMultiComponentFactory,
|
||||
XSet,
|
||||
XContentEnumerationAccess,
|
||||
XComponent,
|
||||
XServiceInfo
|
||||
{
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final void DEBUG (String dbg) {
|
||||
if (DEBUG) System.err.println( dbg );
|
||||
}
|
||||
|
||||
private static com.sun.star.uno.Type UNO_TYPE = null;
|
||||
|
||||
static String[] supportedServiceNames = {
|
||||
"com.sun.star.lang.MultiServiceFactory",
|
||||
"com.sun.star.lang.ServiceManager"
|
||||
};
|
||||
|
||||
ArrayList<XEventListener> eventListener;
|
||||
java.util.HashMap<String, Object> factoriesByImplNames;
|
||||
java.util.HashMap<String, ArrayList<Object>> factoriesByServiceNames; // keys:
|
||||
|
||||
private com.sun.star.uno.XComponentContext m_xDefaultContext;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the <code>ServiceManager</code>.
|
||||
*/
|
||||
public ServiceManager() {
|
||||
eventListener = new ArrayList<XEventListener>();
|
||||
factoriesByImplNames = new java.util.HashMap<String, Object>();
|
||||
factoriesByServiceNames = new java.util.HashMap<String, ArrayList<Object>>();
|
||||
m_xDefaultContext = null;
|
||||
}
|
||||
|
||||
public void setDefaultContext(XComponentContext context) {
|
||||
m_xDefaultContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a specified service.
|
||||
*
|
||||
* <p>Therefore the associated factory of the service is looked up and used
|
||||
* to instantiate a new component. </p>
|
||||
*
|
||||
* @param serviceSpecifier indicates the service or component name.
|
||||
* @return newly created component.
|
||||
*
|
||||
* @see com.sun.star.lang.XMultiServiceFactory
|
||||
*/
|
||||
public java.lang.Object createInstance( String serviceSpecifier )
|
||||
throws com.sun.star.uno.Exception,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return createInstanceWithContext( serviceSpecifier, m_xDefaultContext );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a specified service with the given parameters.
|
||||
*
|
||||
* <p>Therefore the associated factory of the service is looked up and used
|
||||
* to instantiate a new component.</p>
|
||||
*
|
||||
* @return newly created component.
|
||||
* @param serviceSpecifier indicates the service or component name.
|
||||
* @see com.sun.star.lang.XMultiServiceFactory
|
||||
*/
|
||||
public java.lang.Object createInstanceWithArguments(
|
||||
String serviceSpecifier, Object[] args )
|
||||
throws com.sun.star.uno.Exception, com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (DEBUG) {
|
||||
System.err.println("createInstanceWithArguments:" );
|
||||
|
||||
for (Object arg : args) {
|
||||
System.err.print(" " + arg);
|
||||
}
|
||||
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
return createInstanceWithArgumentsAndContext( serviceSpecifier, args, m_xDefaultContext );
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the factory for a given service or implementation name.
|
||||
*
|
||||
* <p>First the requested service name is search in the list of available
|
||||
* services. If it can not be found the name is looked up in the implementation
|
||||
* list.</p>
|
||||
*
|
||||
* @param serviceName indicates the service or implementation name.
|
||||
* @return the factory of the service / implementation.
|
||||
*
|
||||
* @see com.sun.star.lang.XMultiServiceFactory
|
||||
*/
|
||||
private Object queryServiceFactory(String serviceName)
|
||||
throws com.sun.star.uno.Exception,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
DEBUG("queryServiceFactory for name " + serviceName );
|
||||
Object factory = null;
|
||||
|
||||
if ( factoriesByServiceNames.containsKey( serviceName ) ) {
|
||||
ArrayList<Object> availableFact = factoriesByServiceNames.get( serviceName );
|
||||
|
||||
DEBUG("");
|
||||
DEBUG("available factories for " + serviceName +" "+ availableFact);
|
||||
DEBUG("");
|
||||
|
||||
if ( !availableFact.isEmpty() )
|
||||
factory = availableFact.get(availableFact.size()-1);
|
||||
|
||||
} else // not found in list of services - now try the implementations
|
||||
factory = factoriesByImplNames.get( serviceName ); // return null if none is available
|
||||
|
||||
if (DEBUG) {
|
||||
if (factory == null) System.err.println("service not registered");
|
||||
else
|
||||
System.err.println("service found:" + factory + " " + UnoRuntime.queryInterface(XSingleServiceFactory.class, factory));
|
||||
}
|
||||
|
||||
if (factory == null)
|
||||
throw new com.sun.star.uno.Exception("Query for service factory for " + serviceName + " failed.");
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies a list of all available services names.
|
||||
*
|
||||
* @return list of Strings of all service names.
|
||||
* @see com.sun.star.container.XContentEnumerationAccess
|
||||
*/
|
||||
public String[] getAvailableServiceNames()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
try{
|
||||
return factoriesByServiceNames.keySet().toArray(
|
||||
new String[ factoriesByServiceNames.size() ] );
|
||||
} catch(Exception ex) {
|
||||
throw new com.sun.star.uno.RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// XMultiComponentFactory implementation
|
||||
|
||||
/** Create a service instance with given context.
|
||||
*
|
||||
* @param rServiceSpecifier service name.
|
||||
* @param xContext context.
|
||||
* @return service instance.
|
||||
*/
|
||||
public java.lang.Object createInstanceWithContext(
|
||||
String rServiceSpecifier,
|
||||
com.sun.star.uno.XComponentContext xContext )
|
||||
throws com.sun.star.uno.Exception
|
||||
{
|
||||
Object fac = queryServiceFactory( rServiceSpecifier );
|
||||
if (fac != null)
|
||||
{
|
||||
XSingleComponentFactory xCompFac = UnoRuntime.queryInterface(
|
||||
XSingleComponentFactory.class, fac );
|
||||
if (xCompFac != null)
|
||||
{
|
||||
return xCompFac.createInstanceWithContext( xContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
XSingleServiceFactory xServiceFac = UnoRuntime.queryInterface(
|
||||
XSingleServiceFactory.class, fac );
|
||||
if (xServiceFac != null)
|
||||
{
|
||||
if (DEBUG)
|
||||
System.err.println( "### ignoring context raising service \"" + rServiceSpecifier + "\"!" );
|
||||
return xServiceFac.createInstance();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new com.sun.star.uno.Exception(
|
||||
"retrieved service factory object for \"" + rServiceSpecifier +
|
||||
"\" does not export XSingleComponentFactory nor XSingleServiceFactory!" );
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Create a service instance with given context and arguments.
|
||||
*
|
||||
* @param rServiceSpecifier service name.
|
||||
* @param rArguments arguments.
|
||||
* @param xContext context.
|
||||
* @return service instance.
|
||||
*/
|
||||
public java.lang.Object createInstanceWithArgumentsAndContext(
|
||||
String rServiceSpecifier,
|
||||
java.lang.Object[] rArguments,
|
||||
com.sun.star.uno.XComponentContext xContext )
|
||||
throws com.sun.star.uno.Exception
|
||||
{
|
||||
Object fac = queryServiceFactory( rServiceSpecifier );
|
||||
if (fac != null)
|
||||
{
|
||||
XSingleComponentFactory xCompFac = UnoRuntime.queryInterface(
|
||||
XSingleComponentFactory.class, fac );
|
||||
if (xCompFac != null)
|
||||
{
|
||||
return xCompFac.createInstanceWithArgumentsAndContext( rArguments, xContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
XSingleServiceFactory xServiceFac = UnoRuntime.queryInterface(
|
||||
XSingleServiceFactory.class, fac );
|
||||
if (xServiceFac != null)
|
||||
{
|
||||
if (DEBUG)
|
||||
System.err.println( "### ignoring context raising service \"" + rServiceSpecifier + "\"!" );
|
||||
return xServiceFac.createInstanceWithArguments( rArguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new com.sun.star.uno.Exception(
|
||||
"retrieved service factory object for \"" + rServiceSpecifier +
|
||||
"\" does not export XSingleComponentFactory nor XSingleServiceFactory!" );
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all listeners from the <code>ServiceManager</code> and clears the
|
||||
* list of the services.
|
||||
*
|
||||
* @see com.sun.star.lang.XComponent
|
||||
*/
|
||||
public void dispose()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (eventListener != null) {
|
||||
for (XEventListener listener : eventListener) {
|
||||
listener.disposing(new com.sun.star.lang.EventObject(this));
|
||||
}
|
||||
eventListener.clear();
|
||||
}
|
||||
|
||||
factoriesByServiceNames.clear();
|
||||
factoriesByImplNames.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new <code>EventListener</code>.
|
||||
*
|
||||
* <p>The listener is notified when a service is added (removed) to (from)
|
||||
* the <code>ServiceManager</code>.</p>
|
||||
*
|
||||
* <p>If the listener is already registered a
|
||||
* <code>com.sun.star.uno.RuntimeException</code> will be thrown.</p>
|
||||
*
|
||||
* @param xListener the new listener which should been added.
|
||||
* @see com.sun.star.lang.XComponent
|
||||
*/
|
||||
public void addEventListener( XEventListener xListener )
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (xListener == null)
|
||||
throw new com.sun.star.uno.RuntimeException("Listener must not be null");
|
||||
|
||||
if ( eventListener.contains(xListener) )
|
||||
throw new com.sun.star.uno.RuntimeException("Listener already registered.");
|
||||
|
||||
eventListener.add(xListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a <code>EventListener</code> from the <code>ServiceManager</code>.
|
||||
*
|
||||
* <p>If the listener is not registered a <code>com.sun.star.uno.RuntimeException</code>
|
||||
* will be thrown.</p>
|
||||
*
|
||||
* @param xListener the new listener which should been removed.
|
||||
* @see com.sun.star.lang.XComponent
|
||||
*/
|
||||
public void removeEventListener( XEventListener xListener )
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (xListener == null)
|
||||
throw new com.sun.star.uno.RuntimeException("Listener must not be null");
|
||||
|
||||
if ( !eventListener.contains(xListener) )
|
||||
throw new com.sun.star.uno.RuntimeException("Listener is not registered.");
|
||||
|
||||
eventListener.remove(xListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a component is registered at the <code>ServiceManager</code>.
|
||||
*
|
||||
* <p>The given object argument must provide a <code>XServiceInfo</code>
|
||||
* interface.</p>
|
||||
*
|
||||
* @param object object which provides a <code>XServiceInfo</code> interface.
|
||||
* @return true if the component is registered otherwise false.
|
||||
*
|
||||
* @see com.sun.star.container.XSet
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public boolean has( Object object )
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (object == null)
|
||||
throw new com.sun.star.uno.RuntimeException("The parameter must not been null");
|
||||
|
||||
XServiceInfo xServiceInfo = UnoRuntime.queryInterface(XServiceInfo.class, object);
|
||||
|
||||
return xServiceInfo != null && UnoRuntime.areSame(factoriesByImplNames.get(xServiceInfo.getImplementationName()), object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a <code>SingleServiceFactory</code> to the <code>ServiceManager</code>.
|
||||
*
|
||||
* @param object factory which should be added.
|
||||
* @see com.sun.star.container.XSet
|
||||
* @see com.sun.star.lang.XSingleServiceFactory
|
||||
*/
|
||||
public void insert( Object object )
|
||||
throws com.sun.star.lang.IllegalArgumentException,
|
||||
com.sun.star.container.ElementExistException,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (object == null) throw new com.sun.star.lang.IllegalArgumentException();
|
||||
|
||||
XServiceInfo xServiceInfo =
|
||||
UnoRuntime.queryInterface(XServiceInfo.class, object);
|
||||
|
||||
if (xServiceInfo == null)
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"The given object does not implement the XServiceInfo interface."
|
||||
);
|
||||
|
||||
if ( factoriesByImplNames.containsKey( xServiceInfo.getImplementationName() ) ) {
|
||||
throw new com.sun.star.container.ElementExistException(
|
||||
xServiceInfo.getImplementationName() + " already registered"
|
||||
);
|
||||
}
|
||||
|
||||
DEBUG("add factory " + object.toString() + " for " + xServiceInfo.getImplementationName());
|
||||
factoriesByImplNames.put( xServiceInfo.getImplementationName(), object );
|
||||
|
||||
|
||||
String[] serviceNames = xServiceInfo.getSupportedServiceNames();
|
||||
ArrayList<Object> vec ;
|
||||
|
||||
for (String serviceName : serviceNames) {
|
||||
if (!factoriesByServiceNames.containsKey(serviceName)) {
|
||||
DEBUG("> no registered services found under " + serviceName + ": adding...");
|
||||
factoriesByServiceNames.put(serviceName, new ArrayList<Object>());
|
||||
}
|
||||
vec = factoriesByServiceNames.get(serviceName);
|
||||
if (vec.contains( object )) {
|
||||
System.err.println("The implementation " + xServiceInfo.getImplementationName() +
|
||||
" already registered for the service " + serviceName + " - ignoring!");
|
||||
} else {
|
||||
vec.add(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a <code>SingleServiceFactory</code> from the <code>ServiceManager</code>.
|
||||
*
|
||||
* @param object factory which should be removed.
|
||||
* @see com.sun.star.container.XSet
|
||||
* @see com.sun.star.lang.XSingleServiceFactory
|
||||
*/
|
||||
public void remove( Object object )
|
||||
throws com.sun.star.lang.IllegalArgumentException,
|
||||
com.sun.star.container.NoSuchElementException,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (object == null)
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"The given object must not be null."
|
||||
);
|
||||
|
||||
XServiceInfo xServiceInfo =
|
||||
UnoRuntime.queryInterface(XServiceInfo.class, object);
|
||||
|
||||
if (xServiceInfo == null)
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"The given object does not implement the XServiceInfo interface."
|
||||
);
|
||||
|
||||
XSingleServiceFactory xSingleServiceFactory =
|
||||
UnoRuntime.queryInterface(XSingleServiceFactory.class, object);
|
||||
|
||||
if (xSingleServiceFactory == null)
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"The given object does not implement the XSingleServiceFactory interface."
|
||||
);
|
||||
|
||||
if ( factoriesByImplNames.remove( xServiceInfo.getImplementationName() ) == null )
|
||||
throw new com.sun.star.container.NoSuchElementException(
|
||||
xServiceInfo.getImplementationName() +
|
||||
" is not registered as an implementation."
|
||||
);
|
||||
|
||||
String[] serviceNames = xServiceInfo.getSupportedServiceNames();
|
||||
|
||||
for (String serviceName : serviceNames) {
|
||||
if (factoriesByServiceNames.containsKey(serviceName)) {
|
||||
ArrayList<Object> vec = factoriesByServiceNames.get(serviceName);
|
||||
if (!vec.remove(object)) {
|
||||
System.err.println("The implementation " + xServiceInfo.getImplementationName() +
|
||||
" is not registered for the service " + serviceName + " - ignoring!");
|
||||
}
|
||||
// remove the vector if no implementations available for the service
|
||||
if (vec.isEmpty()) {
|
||||
factoriesByServiceNames.remove(serviceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an enumeration of all registered services.
|
||||
*
|
||||
* @return an enumeration of all available services.
|
||||
* @see com.sun.star.container.XEnumerationAccess
|
||||
*/
|
||||
public XEnumeration createEnumeration()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return new ServiceEnumerationImpl( factoriesByImplNames.values().iterator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the UNO type of the <code>ServiceManager</code>
|
||||
*
|
||||
* @return the UNO type of the <code>ServiceManager</code>.
|
||||
* @see com.sun.star.container.XElementAccess
|
||||
* @see com.sun.star.uno.TypeClass
|
||||
*/
|
||||
public com.sun.star.uno.Type getElementType()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if ( UNO_TYPE == null )
|
||||
UNO_TYPE = new com.sun.star.uno.Type(ServiceManager.class);
|
||||
|
||||
return UNO_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any components are registered.
|
||||
*
|
||||
* @return true - if the list of the registered components is not empty - otherwise false.
|
||||
* @see com.sun.star.container.XElementAccess
|
||||
*/
|
||||
public boolean hasElements() {
|
||||
return ! factoriesByImplNames.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an enumeration of all factories for a specified service.
|
||||
*
|
||||
* @param serviceName name of the requested service.
|
||||
* @return an enumeration for service name.
|
||||
* @see com.sun.star.container.XContentEnumerationAccess
|
||||
*/
|
||||
public XEnumeration createContentEnumeration( String serviceName )
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
XEnumeration enumer ;
|
||||
|
||||
ArrayList<Object> serviceList = factoriesByServiceNames.get(serviceName);
|
||||
|
||||
if (serviceList != null)
|
||||
enumer = new ServiceEnumerationImpl( serviceList.iterator() );
|
||||
else
|
||||
enumer = new ServiceEnumerationImpl();
|
||||
|
||||
return enumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the implementation name of the <code>ServiceManager</code> component.
|
||||
*
|
||||
* @return the class name of the <code>ServiceManager</code>.
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public String getImplementationName()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the <code>ServiceManager</code> supports a service.
|
||||
*
|
||||
* @param serviceName service name which should be checked.
|
||||
* @return true if the service is supported - otherwise false.
|
||||
*
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public boolean supportsService( String serviceName )
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
for (String supportedServiceName : supportedServiceNames) {
|
||||
if (supportedServiceName.equals(serviceName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return getImplementationName().equals(serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies list of all supported services.
|
||||
*
|
||||
* @return a list of all supported service names.
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
*/
|
||||
public String[] getSupportedServiceNames()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return supportedServiceNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>ServiceEnumerationImpl</code> class provides an
|
||||
* implementation of the @see com.sun.star.container.XEnumeration interface.
|
||||
*
|
||||
* <p>It is an inner wrapper for a java.util.Enumeration object.</p>
|
||||
*
|
||||
* @see com.sun.star.lang.XSingleServiceFactory
|
||||
* @see com.sun.star.lang.XServiceInfo
|
||||
* @since UDK1.0
|
||||
*/
|
||||
static class ServiceEnumerationImpl implements XEnumeration {
|
||||
java.util.Iterator<Object> enumeration = null;
|
||||
|
||||
/**
|
||||
* Constructs a new empty instance.
|
||||
*/
|
||||
public ServiceEnumerationImpl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance with a given enumeration.
|
||||
*
|
||||
* @param enumer is the enumeration which should been wrapped.
|
||||
* @see com.sun.star.container.XEnumeration
|
||||
*/
|
||||
public ServiceEnumerationImpl(java.util.Enumeration<Object> enumer) {
|
||||
enumeration = Collections.list(enumer).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance with a given enumeration.
|
||||
*
|
||||
* @param enumer is the enumeration which should been wrapped.
|
||||
* @see com.sun.star.container.XEnumeration
|
||||
*/
|
||||
public ServiceEnumerationImpl(java.util.Iterator<Object> enumer) {
|
||||
enumeration = enumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the enumeration contains more elements.
|
||||
*
|
||||
* @return true if more elements are available - otherwise false.
|
||||
* @see com.sun.star.container.XEnumeration
|
||||
*/
|
||||
public boolean hasMoreElements()
|
||||
throws com.sun.star.uno.RuntimeException
|
||||
{
|
||||
return enumeration != null && enumeration.hasNext();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next element of the enumeration.
|
||||
*
|
||||
* <p>If no further elements available a com.sun.star.container.NoSuchElementException
|
||||
* exception will be thrown.</p>
|
||||
*
|
||||
* @return the next element.
|
||||
* @see com.sun.star.container.XEnumeration
|
||||
*/
|
||||
public Object nextElement()
|
||||
throws com.sun.star.container.NoSuchElementException,
|
||||
com.sun.star.lang.WrappedTargetException,
|
||||
com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (enumeration == null)
|
||||
throw new com.sun.star.container.NoSuchElementException();
|
||||
|
||||
try {
|
||||
return enumeration.next();
|
||||
} catch (java.util.NoSuchElementException e) {
|
||||
throw new com.sun.star.container.NoSuchElementException(e, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,147 @@
|
||||
/* -*- 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.urlresolver;
|
||||
|
||||
|
||||
import com.sun.star.bridge.XBridge;
|
||||
import com.sun.star.bridge.XBridgeFactory;
|
||||
import com.sun.star.bridge.XUnoUrlResolver;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.NoConnectException;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnector;
|
||||
|
||||
import com.sun.star.lang.IllegalArgumentException;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
|
||||
/**
|
||||
* This component gives a factory for an <code>UnoUrlResolver</code> service.
|
||||
*
|
||||
* @see com.sun.star.bridge.XBridgeFactory
|
||||
* @see com.sun.star.connection.Connector
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class UrlResolver {
|
||||
public static class _UrlResolver implements XUnoUrlResolver {
|
||||
private static final String __serviceName = "com.sun.star.bridge.UnoUrlResolver";
|
||||
|
||||
private final XMultiServiceFactory _xMultiServiceFactory;
|
||||
|
||||
public _UrlResolver(XMultiServiceFactory xMultiServiceFactory) {
|
||||
_xMultiServiceFactory = xMultiServiceFactory;
|
||||
}
|
||||
|
||||
public Object resolve(/*IN*/String dcp) throws NoConnectException, ConnectionSetupException, IllegalArgumentException, com.sun.star.uno.RuntimeException {
|
||||
String conDcp ;
|
||||
String protDcp ;
|
||||
String rootOid ;
|
||||
|
||||
if(dcp.indexOf(';') == -1) {// use old style
|
||||
conDcp = dcp;
|
||||
protDcp = "iiop";
|
||||
rootOid = "classic_uno";
|
||||
}
|
||||
else { // new style
|
||||
int index = dcp.indexOf(':');
|
||||
dcp = dcp.substring(index + 1).trim();
|
||||
|
||||
index = dcp.indexOf(';');
|
||||
conDcp = dcp.substring(0, index).trim();
|
||||
dcp = dcp.substring(index + 1).trim();
|
||||
|
||||
index = dcp.indexOf(';');
|
||||
protDcp = dcp.substring(0, index).trim();
|
||||
dcp = dcp.substring(index + 1).trim();
|
||||
|
||||
rootOid = dcp.trim().trim();
|
||||
}
|
||||
|
||||
Object rootObject ;
|
||||
XBridgeFactory xBridgeFactory ;
|
||||
try {
|
||||
xBridgeFactory = UnoRuntime.queryInterface(XBridgeFactory.class,
|
||||
_xMultiServiceFactory.createInstance("com.sun.star.bridge.BridgeFactory"));
|
||||
} catch (com.sun.star.uno.Exception e) {
|
||||
throw new com.sun.star.uno.RuntimeException(e);
|
||||
}
|
||||
XBridge xBridge = xBridgeFactory.getBridge(conDcp + ";" + protDcp);
|
||||
|
||||
if(xBridge == null) {
|
||||
Object connector ;
|
||||
try {
|
||||
connector = _xMultiServiceFactory.createInstance("com.sun.star.connection.Connector");
|
||||
} catch (com.sun.star.uno.Exception e) {
|
||||
throw new com.sun.star.uno.RuntimeException(e);
|
||||
}
|
||||
|
||||
XConnector connector_xConnector = UnoRuntime.queryInterface(XConnector.class, connector);
|
||||
|
||||
// connect to the server
|
||||
XConnection xConnection = connector_xConnector.connect(conDcp);
|
||||
try {
|
||||
xBridge = xBridgeFactory.createBridge(conDcp + ";" + protDcp, protDcp, xConnection, null);
|
||||
} catch (com.sun.star.bridge.BridgeExistsException e) {
|
||||
throw new com.sun.star.uno.RuntimeException(e);
|
||||
}
|
||||
}
|
||||
rootObject = xBridge.getInstance(rootOid);
|
||||
return rootObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is desired.
|
||||
* @param multiFactory the service manager to be uses if needed.
|
||||
* @param regKey the registryKey.
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory,
|
||||
XRegistryKey regKey)
|
||||
{
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
|
||||
if (implName.equals(UrlResolver.class.getName()) )
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(_UrlResolver.class,
|
||||
_UrlResolver.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,213 @@
|
||||
/* -*- 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.lib.connections.pipe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnectionBroadcaster;
|
||||
import com.sun.star.io.XStreamListener;
|
||||
import com.sun.star.lib.util.NativeLibraryLoader;
|
||||
|
||||
/**
|
||||
* The PipeConnection implements the <code>XConnection</code> interface
|
||||
* and is uses by the <code>PipeConnector</code> and the <code>PipeAcceptor</code>.
|
||||
* This class is not part of the provided <code>api</code>.
|
||||
*
|
||||
* The native implementation is in jurt/source/pipe/com_sun_star_lib_connections_pipe_PipeConnection.c
|
||||
*
|
||||
* @see com.sun.star.lib.connections.pipe.pipeAcceptor
|
||||
* @see com.sun.star.lib.connections.pipe.pipeConnector
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class PipeConnection implements XConnection, XConnectionBroadcaster {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
static {
|
||||
// load shared library for JNI code
|
||||
NativeLibraryLoader.loadLibrary(PipeConnection.class.getClassLoader(), "jpipe");
|
||||
}
|
||||
|
||||
protected String _aDescription;
|
||||
protected long _nPipeHandle;
|
||||
protected ArrayList<XStreamListener> _aListeners;
|
||||
protected boolean _bFirstRead;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>PipeConnection</code>.
|
||||
*
|
||||
* @param description the description of the connection.
|
||||
*/
|
||||
public PipeConnection(String description)
|
||||
throws IOException
|
||||
{
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated " + description );
|
||||
|
||||
_aListeners = new ArrayList<XStreamListener>();
|
||||
_bFirstRead = true;
|
||||
|
||||
// get pipe name from pipe descriptor
|
||||
String aPipeName ;
|
||||
StringTokenizer aTokenizer = new StringTokenizer( description, "," );
|
||||
if ( aTokenizer.hasMoreTokens() ) {
|
||||
String aConnType = aTokenizer.nextToken();
|
||||
if ( !aConnType.equals( "pipe" ) )
|
||||
throw new RuntimeException( "invalid pipe descriptor: does not start with 'pipe,'" );
|
||||
|
||||
String aPipeNameParam = aTokenizer.nextToken();
|
||||
if ( !aPipeNameParam.substring( 0, 5 ).equals( "name=" ) )
|
||||
throw new RuntimeException( "invalid pipe descriptor: no 'name=' parameter found" );
|
||||
aPipeName = aPipeNameParam.substring( 5 );
|
||||
}
|
||||
else
|
||||
throw new RuntimeException( "invalid or empty pipe descriptor" );
|
||||
|
||||
// create the pipe
|
||||
try {
|
||||
createJNI( aPipeName );
|
||||
} catch ( java.lang.Exception ex1 ) {
|
||||
IOException ex2 = new IOException();
|
||||
ex2.initCause(ex1);
|
||||
throw ex2;
|
||||
}
|
||||
}
|
||||
|
||||
public void addStreamListener(XStreamListener aListener ) throws com.sun.star.uno.RuntimeException {
|
||||
_aListeners.add(aListener);
|
||||
}
|
||||
|
||||
public void removeStreamListener(XStreamListener aListener ) throws com.sun.star.uno.RuntimeException {
|
||||
_aListeners.remove(aListener);
|
||||
}
|
||||
|
||||
private void notifyListeners_open() {
|
||||
for (XStreamListener xStreamListener : _aListeners) {
|
||||
xStreamListener.started();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners_close() {
|
||||
for (XStreamListener xStreamListener : _aListeners) {
|
||||
xStreamListener.closed();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners_error(com.sun.star.uno.Exception exception) {
|
||||
for (XStreamListener xStreamListener : _aListeners) {
|
||||
xStreamListener.error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
// JNI implementation to create the pipe
|
||||
private native int createJNI( String name )
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException;
|
||||
|
||||
// JNI implementation to read from the pipe
|
||||
private native int readJNI(/*OUT*/byte[][] bytes, int nBytesToRead)
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException;
|
||||
|
||||
// JNI implementation to write to the pipe
|
||||
private native void writeJNI(byte aData[])
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException;
|
||||
|
||||
// JNI implementation to flush the pipe
|
||||
private native void flushJNI()
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException;
|
||||
|
||||
// JNI implementation to close the pipe
|
||||
private native void closeJNI()
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException;
|
||||
|
||||
/**
|
||||
* Read the required number of bytes.
|
||||
*
|
||||
* @param bytes the outparameter, where the bytes have to be placed.
|
||||
* @param nBytesToRead the number of bytes to read.
|
||||
* @return the number of bytes read.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#read
|
||||
*/
|
||||
public int read(/*OUT*/byte[][] bytes, int nBytesToRead)
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if(_bFirstRead) {
|
||||
_bFirstRead = false;
|
||||
|
||||
notifyListeners_open();
|
||||
}
|
||||
|
||||
return readJNI( bytes, nBytesToRead );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write bytes.
|
||||
*
|
||||
* @param aData the bytes to write.
|
||||
* @see com.sun.star.connection.XConnection#write
|
||||
*/
|
||||
public void write(byte aData[])
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException
|
||||
{
|
||||
writeJNI( aData );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the buffer.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#flush
|
||||
*/
|
||||
public void flush()
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException
|
||||
{
|
||||
flushJNI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#close
|
||||
*/
|
||||
public void close()
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException
|
||||
{
|
||||
if (DEBUG) System.out.print( "PipeConnection::close() " );
|
||||
closeJNI();
|
||||
notifyListeners_close();
|
||||
if (DEBUG) System.out.println( "done" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a description of the connection.
|
||||
*
|
||||
* @return the description.
|
||||
* @see com.sun.star.connection.XConnection#getDescription
|
||||
*/
|
||||
public String getDescription() throws com.sun.star.uno.RuntimeException {
|
||||
return _aDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,123 @@
|
||||
/* -*- 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.lib.connections.pipe;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.AlreadyAcceptingException;
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.XAcceptor;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XAcceptor</code> interface.
|
||||
*
|
||||
* <p>The <code>pipeAcceptor</code> is a specialized component that uses TCP
|
||||
* pipes for communication. The <code>pipeAcceptor</code> is generally used
|
||||
* by the <code>com.sun.star.connection.Acceptor</code> service.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*
|
||||
* @since UDK 1.0
|
||||
*/
|
||||
public final class pipeAcceptor implements XAcceptor {
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> accesses this through reflection.</p>
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static final String __serviceName
|
||||
= "com.sun.star.connection.pipeAcceptor";
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is
|
||||
* requested.
|
||||
* @param multiFactory the service manager to be used (if needed).
|
||||
* @param regKey the registry key.
|
||||
* @return an <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(
|
||||
String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
|
||||
{
|
||||
return implName.equals(pipeAcceptor.class.getName())
|
||||
? FactoryHelper.getServiceFactory(
|
||||
pipeAcceptor.class, __serviceName, multiFactory, regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a connection request via the described pipe.
|
||||
*
|
||||
* <p>This call blocks until a connection has been established.</p>
|
||||
*
|
||||
* <p>The connection description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>),
|
||||
* where <code><var>type</var></code> should be <code>pipe</code>
|
||||
* (ignoring case). Supported keys (ignoring case) currently are</p>
|
||||
* <dl>
|
||||
* <dt><code>host</code>
|
||||
* <dd>The name or address of the accepting interface (defaults to
|
||||
* <code>0</code>, meaning any interface).
|
||||
* <dt><code>port</code>
|
||||
* <dd>The TCP port number to accept on (defaults to <code>6001</code>).
|
||||
* <dt><code>backlog</code>
|
||||
* <dd>The maximum length of the acceptor's queue (defaults to
|
||||
* <code>50</code>).
|
||||
* <dt><code>tcpnodelay</code>
|
||||
* <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's
|
||||
* algorithm on the resulting connection.
|
||||
* </dl>
|
||||
*
|
||||
* @param connectionDescription the description of the connection.
|
||||
* @return an <code>XConnection</code> to the client.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
*/
|
||||
public XConnection accept(String connectionDescription) throws
|
||||
AlreadyAcceptingException, ConnectionSetupException,
|
||||
com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
throw new java.lang.NoSuchMethodError( "pipeAcceptor not fully implemented yet" );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor#stopAccepting
|
||||
*/
|
||||
public void stopAccepting() {
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,120 @@
|
||||
/* -*- 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.lib.connections.pipe;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.NoConnectException;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnector;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XConnector</code> interface.
|
||||
*
|
||||
* <p>The <code>pipeConnector</code> is a specialized component that uses TCP
|
||||
* pipes for communication. The <code>pipeConnector</code> is generally
|
||||
* used by the <code>com.sun.star.connection.Connector</code> service.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*
|
||||
* @since UDK 1.0
|
||||
*/
|
||||
public final class pipeConnector implements XConnector {
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> accesses this through reflection.</p>
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static final String __serviceName = "com.sun.star.connection.pipeConnector";
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is
|
||||
* requested.
|
||||
* @param multiFactory the service manager to be used (if needed).
|
||||
* @param regKey the registry key.
|
||||
* @return an <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(
|
||||
String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
|
||||
{
|
||||
return implName.equals(pipeConnector.class.getName())
|
||||
? FactoryHelper.getServiceFactory(pipeConnector.class,
|
||||
__serviceName, multiFactory,
|
||||
regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects via the described pipe to a waiting server.
|
||||
*
|
||||
* <p>The connection description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>),
|
||||
* where <code><var>type</var></code> should be <code>pipe</code>
|
||||
* (ignoring case). Supported keys (ignoring case) currently are</p>
|
||||
* <dl>
|
||||
* <dt><code>host</code>
|
||||
* <dd>The name or address of the server. Must be present.
|
||||
* <dt><code>port</code>
|
||||
* <dd>The TCP port number of the server (defaults to <code>6001</code>).
|
||||
* <dt><code>tcpnodelay</code>
|
||||
* <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's
|
||||
* algorithm on the resulting connection.
|
||||
* </dl>
|
||||
*
|
||||
* @param connectionDescription the description of the connection.
|
||||
* @return an <code>XConnection</code> to the server.
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
*/
|
||||
public synchronized XConnection connect(String connectionDescription)
|
||||
throws NoConnectException, ConnectionSetupException
|
||||
{
|
||||
if (bConnected)
|
||||
throw new ConnectionSetupException("already connected");
|
||||
|
||||
try {
|
||||
XConnection xConn = new PipeConnection( connectionDescription );
|
||||
bConnected = true;
|
||||
return xConn;
|
||||
} catch ( java.io.IOException e ) {
|
||||
throw new NoConnectException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean bConnected = false;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,98 @@
|
||||
/* -*- 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.lib.connections.socket;
|
||||
|
||||
/**
|
||||
* Helper class for <code>socketAcceptor</code> and <code>socketConnector</code>.
|
||||
*
|
||||
* <p>FIXME: Once those classes have been moved from <code>jurt</code> to
|
||||
* <code>javaunohelper</code>, they should use
|
||||
* <code>com.sun.star.lib.uno.helper.UnoUrl</code> either instead of this class
|
||||
* or underneath this class.</p>
|
||||
*/
|
||||
final class ConnectionDescriptor {
|
||||
public ConnectionDescriptor(String description)
|
||||
throws com.sun.star.lang.IllegalArgumentException {
|
||||
for (int i = description.indexOf(','); i >= 0;) {
|
||||
int j = description.indexOf(',', i + 1);
|
||||
int k = j < 0 ? description.length() : j;
|
||||
int l = description.indexOf('=', i + 1);
|
||||
if (l < 0 || l >= k) {
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"parameter lacks '='");
|
||||
}
|
||||
String key = description.substring(i + 1, l);
|
||||
String value = description.substring(l + 1, k);
|
||||
if (key.equalsIgnoreCase("host")) {
|
||||
host = value;
|
||||
} else if (key.equalsIgnoreCase("port")) {
|
||||
try {
|
||||
port = Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new com.sun.star.lang.IllegalArgumentException(e);
|
||||
}
|
||||
if (port < 0 || port > 65535) {
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"port parameter must have value between 0 and 65535,"
|
||||
+ " inclusive");
|
||||
}
|
||||
} else if (key.equalsIgnoreCase("backlog")) {
|
||||
try {
|
||||
backlog = Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new com.sun.star.lang.IllegalArgumentException(e);
|
||||
}
|
||||
} else if (key.equalsIgnoreCase("tcpnodelay")) {
|
||||
if (value.equals("0")) {
|
||||
tcpNoDelay = Boolean.FALSE;
|
||||
} else if (value.equals("1")) {
|
||||
tcpNoDelay = Boolean.TRUE;
|
||||
} else {
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"tcpnodelay parameter must have 0/1 value");
|
||||
}
|
||||
}
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public int getBacklog() {
|
||||
return backlog;
|
||||
}
|
||||
|
||||
public Boolean getTcpNoDelay() {
|
||||
return tcpNoDelay;
|
||||
}
|
||||
|
||||
private String host = null;
|
||||
private int port = 6001;
|
||||
private int backlog = 50;
|
||||
private Boolean tcpNoDelay = null;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,235 @@
|
||||
/* -*- 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.lib.connections.socket;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnectionBroadcaster;
|
||||
import com.sun.star.io.XStreamListener;
|
||||
|
||||
/**
|
||||
* The SocketConnection implements the <code>XConnection</code> interface
|
||||
* and is uses by the <code>SocketConnector</code> and the <code>SocketAcceptor</code>.
|
||||
*
|
||||
* <p>This class is not part of the provided <code>api</code>.</p>
|
||||
*
|
||||
* @see com.sun.star.lib.connections.socket.socketAcceptor
|
||||
* @see com.sun.star.lib.connections.socket.socketConnector
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class SocketConnection implements XConnection, XConnectionBroadcaster {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
protected String _description;
|
||||
protected Socket _socket;
|
||||
protected InputStream _inputStream;
|
||||
protected OutputStream _outputStream;
|
||||
protected ArrayList<XStreamListener> _listeners;
|
||||
protected boolean _firstRead;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>SocketConnection</code>.
|
||||
*
|
||||
* @param description the description of the connection.
|
||||
* @param socket the socket of the connection.
|
||||
*/
|
||||
public SocketConnection(String description, Socket socket) throws IOException {
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated " + description + " " + socket);
|
||||
|
||||
_description = description
|
||||
+ ",localHost=" + socket.getLocalAddress().getHostName()
|
||||
+ ",localPort=" + socket.getLocalPort()
|
||||
+ ",peerHost=" + socket.getInetAddress().getHostName()
|
||||
+ ",peerPort=" + socket.getPort();
|
||||
|
||||
_socket = socket;
|
||||
_inputStream = new BufferedInputStream(socket.getInputStream());
|
||||
_outputStream = new BufferedOutputStream(socket.getOutputStream());
|
||||
|
||||
_listeners = new ArrayList<XStreamListener>();
|
||||
_firstRead = true;
|
||||
}
|
||||
|
||||
public void addStreamListener(XStreamListener aListener )
|
||||
throws com.sun.star.uno.RuntimeException {
|
||||
_listeners.add(aListener);
|
||||
}
|
||||
|
||||
public void removeStreamListener(XStreamListener aListener )
|
||||
throws com.sun.star.uno.RuntimeException {
|
||||
_listeners.remove(aListener);
|
||||
}
|
||||
|
||||
private void notifyListeners_open() {
|
||||
for (XStreamListener xStreamListener : _listeners) {
|
||||
xStreamListener.started();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners_close() {
|
||||
for (XStreamListener xStreamListener : _listeners) {
|
||||
xStreamListener.closed();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners_error(com.sun.star.uno.Exception exception) {
|
||||
for (XStreamListener xStreamListener : _listeners) {
|
||||
xStreamListener.error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the required number of bytes.
|
||||
*
|
||||
* @param bytes the outparameter, where the bytes have to be placed.
|
||||
* @param nBytesToRead the number of bytes to read.
|
||||
* @return the number of bytes read.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#read
|
||||
*/
|
||||
public int read(/*OUT*/byte[][] bytes, int nBytesToRead)
|
||||
throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
|
||||
if(_firstRead) {
|
||||
_firstRead = false;
|
||||
|
||||
notifyListeners_open();
|
||||
}
|
||||
|
||||
String errMessage = null;
|
||||
|
||||
int read_bytes = 0;
|
||||
bytes[0] = new byte[nBytesToRead];
|
||||
|
||||
try {
|
||||
int count ;
|
||||
|
||||
do {
|
||||
count = _inputStream.read(bytes[0], read_bytes, nBytesToRead - read_bytes);
|
||||
if(count == -1)
|
||||
errMessage = "EOF reached - " + getDescription();
|
||||
|
||||
read_bytes += count;
|
||||
}
|
||||
while(read_bytes >= 0 && read_bytes < nBytesToRead && count >= 0);
|
||||
} catch(IOException ioException) {
|
||||
if(DEBUG) {
|
||||
System.err.println("##### " + getClass().getName() + ".read - exception occurred:" + ioException);
|
||||
ioException.printStackTrace();
|
||||
}
|
||||
|
||||
errMessage = ioException.toString();
|
||||
}
|
||||
|
||||
if(errMessage != null) {
|
||||
com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(errMessage);
|
||||
notifyListeners_error(unoIOException);
|
||||
|
||||
throw unoIOException;
|
||||
}
|
||||
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - read byte:" + read_bytes + " " + Arrays.toString(bytes[0]));
|
||||
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write bytes.
|
||||
*
|
||||
* @param aData the bytes to write.
|
||||
* @see com.sun.star.connection.XConnection#write
|
||||
*/
|
||||
public void write(byte aData[]) throws com.sun.star.io.IOException,
|
||||
com.sun.star.uno.RuntimeException {
|
||||
try {
|
||||
_outputStream.write(aData);
|
||||
} catch(IOException ioException) {
|
||||
com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException);
|
||||
notifyListeners_error(unoIOException);
|
||||
|
||||
throw unoIOException;
|
||||
}
|
||||
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - written bytes:" + Arrays.toString(aData) + " " + aData.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the buffer.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#flush
|
||||
*/
|
||||
public void flush() throws com.sun.star.io.IOException,
|
||||
com.sun.star.uno.RuntimeException {
|
||||
try {
|
||||
_outputStream.flush();
|
||||
} catch(IOException ioException) {
|
||||
com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException);
|
||||
notifyListeners_error(unoIOException);
|
||||
|
||||
throw unoIOException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#close
|
||||
*/
|
||||
public void close() throws com.sun.star.io.IOException,
|
||||
com.sun.star.uno.RuntimeException {
|
||||
try {
|
||||
_socket.close();
|
||||
} catch(IOException ioException) {
|
||||
com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException);
|
||||
notifyListeners_error(unoIOException);
|
||||
|
||||
throw unoIOException;
|
||||
}
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - socket closed");
|
||||
|
||||
notifyListeners_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a description of the connection.
|
||||
*
|
||||
* @return the description.
|
||||
* @see com.sun.star.connection.XConnection#getDescription
|
||||
*/
|
||||
public String getDescription() throws com.sun.star.uno.RuntimeException {
|
||||
return _description;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,202 @@
|
||||
/* -*- 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.lib.connections.socket;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.AlreadyAcceptingException;
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.XAcceptor;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XAcceptor</code> interface.
|
||||
*
|
||||
* <p>The <code>socketAcceptor</code> is a specialized component that uses TCP
|
||||
* sockets for communication. The <code>socketAcceptor</code> is generally used
|
||||
* by the <code>com.sun.star.connection.Acceptor</code> service.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection2
|
||||
* @see com.sun.star.connection.XConnector
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*
|
||||
* @since UDK 1.0
|
||||
*/
|
||||
public final class socketAcceptor implements XAcceptor {
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> accesses this through reflection.</p>
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static final String __serviceName
|
||||
= "com.sun.star.connection.socketAcceptor";
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is
|
||||
* requested.
|
||||
* @param multiFactory the service manager to be used (if needed).
|
||||
* @param regKey the registry key.
|
||||
* @return an <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(
|
||||
String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
|
||||
{
|
||||
return implName.equals(socketAcceptor.class.getName())
|
||||
? FactoryHelper.getServiceFactory(socketAcceptor.class,
|
||||
__serviceName, multiFactory,
|
||||
regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a connection request via the described socket.
|
||||
*
|
||||
* <p>This call blocks until a connection has been established.</p>
|
||||
*
|
||||
* <p>The connection description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>),
|
||||
* where <code><var>type</var></code> should be <code>socket</code>
|
||||
* (ignoring case). Supported keys (ignoring case) currently are</p>
|
||||
* <dl>
|
||||
* <dt><code>host</code>
|
||||
* <dd>The name or address of the accepting interface (defaults to
|
||||
* <code>0</code>, meaning any interface).
|
||||
* <dt><code>port</code>
|
||||
* <dd>The TCP port number to accept on (defaults to <code>6001</code>).
|
||||
* <dt><code>backlog</code>
|
||||
* <dd>The maximum length of the acceptor's queue (defaults to
|
||||
* <code>50</code>).
|
||||
* <dt><code>tcpnodelay</code>
|
||||
* <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's
|
||||
* algorithm on the resulting connection.
|
||||
* </dl>
|
||||
*
|
||||
* @param connectionDescription the description of the connection.
|
||||
* @return an <code>XConnection</code> to the client.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
*/
|
||||
public XConnection accept(String connectionDescription) throws
|
||||
AlreadyAcceptingException, ConnectionSetupException,
|
||||
com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
ServerSocket serv;
|
||||
synchronized (this) {
|
||||
if (server == null) {
|
||||
ConnectionDescriptor desc
|
||||
= new ConnectionDescriptor(connectionDescription);
|
||||
String host = desc.getHost();
|
||||
if (host.equals("0")) {
|
||||
host = null;
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.err.println("##### " + getClass().getName()
|
||||
+ ".accept: creating ServerSocket "
|
||||
+ desc.getPort() + ", "
|
||||
+ desc.getBacklog() + ", " + host);
|
||||
}
|
||||
try {
|
||||
server = new ServerSocket(desc.getPort(), desc.getBacklog(),
|
||||
host == null ? null
|
||||
: InetAddress.getByName(host));
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
}
|
||||
acceptingDescription = connectionDescription;
|
||||
tcpNoDelay = desc.getTcpNoDelay();
|
||||
} else if (!connectionDescription.equals(acceptingDescription)) {
|
||||
throw new AlreadyAcceptingException(acceptingDescription
|
||||
+ " vs. "
|
||||
+ connectionDescription);
|
||||
}
|
||||
serv = server;
|
||||
}
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = serv.accept();
|
||||
if (DEBUG) {
|
||||
System.err.println("##### " + getClass().getName()
|
||||
+ ".accept: accepted " + socket);
|
||||
}
|
||||
// we enable tcpNoDelay for loopback connections because
|
||||
// it can make a significant speed difference on linux boxes.
|
||||
if (tcpNoDelay != null) {
|
||||
socket.setTcpNoDelay(tcpNoDelay.booleanValue());
|
||||
}
|
||||
else {
|
||||
InetSocketAddress address = (InetSocketAddress)socket.getRemoteSocketAddress();
|
||||
if (address != null && address.getAddress().isLoopbackAddress()) {
|
||||
socket.setTcpNoDelay(true);
|
||||
}
|
||||
}
|
||||
return new SocketConnection(acceptingDescription, socket);
|
||||
}
|
||||
catch(IOException e) {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch(IOException ioException) {
|
||||
}
|
||||
}
|
||||
throw new ConnectionSetupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor#stopAccepting
|
||||
*/
|
||||
public void stopAccepting() {
|
||||
ServerSocket serv;
|
||||
synchronized (this) {
|
||||
serv = server;
|
||||
}
|
||||
try {
|
||||
serv.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new com.sun.star.uno.RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private ServerSocket server = null;
|
||||
private String acceptingDescription;
|
||||
private Boolean tcpNoDelay;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,176 @@
|
||||
/* -*- 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.lib.connections.socket;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
import com.sun.star.connection.ConnectionSetupException;
|
||||
import com.sun.star.connection.NoConnectException;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnector;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XConnector</code> interface.
|
||||
*
|
||||
* <p>The <code>socketConnector</code> is a specialized component that uses TCP
|
||||
* sockets for communication. The <code>socketConnector</code> is generally
|
||||
* used by the <code>com.sun.star.connection.Connector</code> service.</p>
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
* @see com.sun.star.connection.XConnector
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*
|
||||
* @since UDK 1.0
|
||||
*/
|
||||
public final class socketConnector implements XConnector {
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* <p>The <code>JavaLoader</code> accesses this through reflection.</p>
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static final String __serviceName
|
||||
= "com.sun.star.connection.socketConnector";
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
*
|
||||
* <p>This method is called by the <code>JavaLoader</code>.</p>
|
||||
*
|
||||
* @param implName the name of the implementation for which a service is
|
||||
* requested.
|
||||
* @param multiFactory the service manager to be used (if needed).
|
||||
* @param regKey the registry key.
|
||||
* @return an <code>XSingleServiceFactory</code> for creating the component.
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(
|
||||
String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
|
||||
{
|
||||
return implName.equals(socketConnector.class.getName())
|
||||
? FactoryHelper.getServiceFactory(socketConnector.class,
|
||||
__serviceName, multiFactory,
|
||||
regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects via the described socket to a waiting server.
|
||||
*
|
||||
* <p>The connection description has the following format:
|
||||
* <code><var>type</var></code><!--
|
||||
* -->*(<code><var>key</var>=<var>value</var></code>),
|
||||
* where <code><var>type</var></code> should be <code>socket</code>
|
||||
* (ignoring case). Supported keys (ignoring case) currently are</p>
|
||||
* <dl>
|
||||
* <dt><code>host</code>
|
||||
* <dd>The name or address of the server. Must be present.
|
||||
* <dt><code>port</code>
|
||||
* <dd>The TCP port number of the server (defaults to <code>6001</code>).
|
||||
* <dt><code>tcpnodelay</code>
|
||||
* <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's
|
||||
* algorithm on the resulting connection.
|
||||
* </dl>
|
||||
*
|
||||
* @param connectionDescription the description of the connection.
|
||||
* @return an <code>XConnection</code> to the server.
|
||||
*
|
||||
* @see com.sun.star.connection.XAcceptor
|
||||
* @see com.sun.star.connection.XConnection
|
||||
*/
|
||||
public synchronized XConnection connect(String connectionDescription)
|
||||
throws NoConnectException, ConnectionSetupException
|
||||
{
|
||||
if (connected)
|
||||
throw new ConnectionSetupException("already connected");
|
||||
|
||||
ConnectionDescriptor desc;
|
||||
try {
|
||||
desc = new ConnectionDescriptor(connectionDescription);
|
||||
} catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
}
|
||||
|
||||
if (desc.getHost() == null)
|
||||
throw new ConnectionSetupException("host parameter missing");
|
||||
// Try all (IPv4 and IPv6) addresses, in case this client is on a
|
||||
// dual-stack host and the server process is an IPv4-only process, also
|
||||
// on a dual-stack host (see Stevens, Fenner, Rudoff: "Unix Network
|
||||
// Programming, Volume 1: The Sockets Networking API, 3rd Edition",
|
||||
// p. 359):
|
||||
InetAddress[] adr;
|
||||
try {
|
||||
adr = InetAddress.getAllByName(desc.getHost());
|
||||
} catch (UnknownHostException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
}
|
||||
Socket socket = null;
|
||||
boolean isLoopbackAddress = false;
|
||||
for (int i = 0; i < adr.length; ++i) {
|
||||
try {
|
||||
isLoopbackAddress = adr[i].isLoopbackAddress();
|
||||
socket = new Socket(adr[i], desc.getPort());
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
if (i == adr.length - 1)
|
||||
throw new NoConnectException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (socket == null)
|
||||
throw new ConnectionSetupException("no socket");
|
||||
|
||||
XConnection con;
|
||||
try {
|
||||
// we enable tcpNoDelay for loopback connections because
|
||||
// it can make a significant speed difference on linux boxes.
|
||||
if (desc.getTcpNoDelay() != null)
|
||||
socket.setTcpNoDelay(desc.getTcpNoDelay().booleanValue());
|
||||
else if (isLoopbackAddress)
|
||||
socket.setTcpNoDelay(true);
|
||||
|
||||
con = new SocketConnection(connectionDescription, socket);
|
||||
} catch (IOException e) {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch(IOException ioException) {
|
||||
}
|
||||
}
|
||||
throw new NoConnectException(e);
|
||||
}
|
||||
connected = true;
|
||||
return con;
|
||||
}
|
||||
|
||||
private boolean connected = false;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* -*- 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.lib.uno;
|
||||
|
||||
/**
|
||||
* Marker interface implemented by proxies for UNO objects.
|
||||
*
|
||||
* <p>Currently, this interface is used internally by
|
||||
* <code>com.sun.star.lib.uno.environments.java.java_environment</code> to
|
||||
* distinguish between proxies and local objects. Any proxy object that shall
|
||||
* be registered at the <code>java_environment</code> must implement this marker
|
||||
* interface.</p>
|
||||
*/
|
||||
public interface Proxy {
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,43 @@
|
||||
/* -*- 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.lib.uno.bridges.java_remote;
|
||||
|
||||
import com.sun.star.bridge.XBridge;
|
||||
|
||||
/**
|
||||
* A back door to access the bridge associated with a bridged object.
|
||||
*/
|
||||
public final class BridgedObject {
|
||||
/**
|
||||
* Obtains the bridge associated with a bridged object.
|
||||
*
|
||||
* @param obj a reference to a (Java representation of a) UNO object;
|
||||
* must not be null.
|
||||
* @return the bridge associated with the given object, if it is indeed
|
||||
* bridged; otherwise, null is returned.
|
||||
*/
|
||||
public static XBridge getBridge(Object obj) {
|
||||
return ProxyFactory.getBridge(obj);
|
||||
}
|
||||
|
||||
private BridgedObject() {} // do not instantiate
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,198 @@
|
||||
/* -*- 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.lib.uno.bridges.java_remote;
|
||||
|
||||
import com.sun.star.bridge.XBridge;
|
||||
import com.sun.star.lib.util.AsynchronousFinalizer;
|
||||
import com.sun.star.uno.IQueryInterface;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
/**
|
||||
* A factory for proxies specific to the <code>java_remote_bridge</code>.
|
||||
*
|
||||
* <p>Eventually, this class should be united with all other proxy classes
|
||||
* specific to certain bridges (for example, the JNI bridge), resulting in a
|
||||
* generic proxy class.</p>
|
||||
*/
|
||||
final class ProxyFactory {
|
||||
public ProxyFactory(RequestHandler requestHandler, XBridge bridge) {
|
||||
this.requestHandler = requestHandler;
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
public Object create(String oid, Type type) {
|
||||
return Proxy.newProxyInstance(
|
||||
getClass().getClassLoader(),
|
||||
new Class[] { com.sun.star.lib.uno.Proxy.class,
|
||||
IQueryInterface.class, type.getZClass() },
|
||||
new Handler(oid, type));
|
||||
}
|
||||
|
||||
public boolean isProxy(Object obj) {
|
||||
if (Proxy.isProxyClass(obj.getClass())) {
|
||||
InvocationHandler h = Proxy.getInvocationHandler(obj);
|
||||
return h instanceof Handler && ((Handler) h).matches(this);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() throws InterruptedException {
|
||||
asynchronousFinalizer.drain();
|
||||
}
|
||||
|
||||
public static XBridge getBridge(Object obj) {
|
||||
if (Proxy.isProxyClass(obj.getClass())) {
|
||||
InvocationHandler h = Proxy.getInvocationHandler(obj);
|
||||
if (h instanceof Handler) {
|
||||
return ((Handler) h).getBridge();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static int getDebugCount() {
|
||||
synchronized (debugCountLock) {
|
||||
return debugCount;
|
||||
}
|
||||
}
|
||||
|
||||
private static void incrementDebugCount() {
|
||||
synchronized (debugCountLock) {
|
||||
++debugCount;
|
||||
}
|
||||
}
|
||||
|
||||
private static void decrementDebugCount() {
|
||||
synchronized (debugCountLock) {
|
||||
--debugCount;
|
||||
}
|
||||
}
|
||||
|
||||
private final class Handler implements InvocationHandler {
|
||||
public Handler(String oid, Type type) {
|
||||
this.oid = oid;
|
||||
this.type = type;
|
||||
incrementDebugCount();
|
||||
}
|
||||
|
||||
public boolean matches(ProxyFactory factory) {
|
||||
return ProxyFactory.this == factory;
|
||||
}
|
||||
|
||||
public XBridge getBridge() {
|
||||
return bridge;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args)
|
||||
throws Throwable
|
||||
{
|
||||
if (method.equals(METHOD_EQUALS) || method.equals(METHOD_IS_SAME)) {
|
||||
return Boolean.valueOf(args[0] != null
|
||||
&& oid.equals(UnoRuntime.generateOid(args[0])));
|
||||
} else if (method.equals(METHOD_HASH_CODE)) {
|
||||
return Integer.valueOf(oid.hashCode());
|
||||
} else if (method.equals(METHOD_TO_STRING)) {
|
||||
return "[Proxy:" + System.identityHashCode(proxy) + "," + oid
|
||||
+ "," + type + "]";
|
||||
} else if (method.equals(METHOD_QUERY_INTERFACE)) {
|
||||
// See the comment in java_remote_bridge.mapInterfaceTo for one
|
||||
// reason why this implementation must not satisfy a request for
|
||||
// a super-interface with a proxy itself:
|
||||
return args[0].equals(type) ? proxy
|
||||
: request("queryInterface", args);
|
||||
} else if (method.equals(METHOD_GET_OID)) {
|
||||
return oid;
|
||||
} else {
|
||||
return request(method.getName(), args);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
decrementDebugCount();
|
||||
asynchronousFinalizer.add(new AsynchronousFinalizer.Job() {
|
||||
public void run() throws Throwable {
|
||||
request("release", null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Object request(String operation, Object[] args) throws Throwable
|
||||
{
|
||||
Object res = requestHandler.sendRequest(oid, type, operation, args);
|
||||
// Avoid early finalization of this object, while an invoke ->
|
||||
// request call is still ongoing; as finalize also calls request,
|
||||
// this should fulfil the condition from The Java Language
|
||||
// Specification, 3rd ed., that "if an object's finalizer can result
|
||||
// in synchronization on that object, then that object must be alive
|
||||
// and considered reachable whenever a lock is held on it:"
|
||||
synchronized (this) {
|
||||
++dummy;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private final String oid;
|
||||
private final Type type;
|
||||
@SuppressWarnings("unused")
|
||||
private int dummy = 0;
|
||||
}
|
||||
|
||||
private static final Method METHOD_EQUALS;
|
||||
private static final Method METHOD_HASH_CODE;
|
||||
private static final Method METHOD_TO_STRING;
|
||||
private static final Method METHOD_QUERY_INTERFACE;
|
||||
private static final Method METHOD_IS_SAME;
|
||||
private static final Method METHOD_GET_OID;
|
||||
static {
|
||||
try {
|
||||
METHOD_EQUALS = Object.class.getMethod(
|
||||
"equals", new Class[] { Object.class });
|
||||
METHOD_HASH_CODE = Object.class.getMethod(
|
||||
"hashCode", (Class[]) null);
|
||||
METHOD_TO_STRING = Object.class.getMethod(
|
||||
"toString", (Class[]) null);
|
||||
METHOD_QUERY_INTERFACE = IQueryInterface.class.getMethod(
|
||||
"queryInterface", new Class[] { Type.class });
|
||||
METHOD_IS_SAME = IQueryInterface.class.getMethod(
|
||||
"isSame", new Class[] { Object.class });
|
||||
METHOD_GET_OID = IQueryInterface.class.getMethod(
|
||||
"getOid", (Class[]) null);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Object debugCountLock = new Object();
|
||||
private static int debugCount = 0;
|
||||
|
||||
private final RequestHandler requestHandler;
|
||||
private final XBridge bridge;
|
||||
private final AsynchronousFinalizer asynchronousFinalizer =
|
||||
new AsynchronousFinalizer();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,35 @@
|
||||
/* -*- 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.lib.uno.bridges.java_remote;
|
||||
|
||||
import com.sun.star.uno.Type;
|
||||
|
||||
/**
|
||||
* The link between the proxies generated by <code>ProxyFactory</code> (which
|
||||
* receive requests in the form of method calls) and
|
||||
* <code>java_remote_bridge</code> (which passes those requests on to the remote
|
||||
* side).
|
||||
*/
|
||||
interface RequestHandler {
|
||||
Object sendRequest(String oid, Type type, String operation, Object[] args)
|
||||
throws Throwable;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,76 @@
|
||||
/* -*- 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.lib.uno.bridges.java_remote;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.sun.star.connection.XConnection;
|
||||
|
||||
|
||||
class XConnectionInputStream_Adapter extends InputStream {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
protected XConnection _xConnection;
|
||||
protected byte _bytes[][] = new byte[1][];
|
||||
|
||||
XConnectionInputStream_Adapter(XConnection xConnection) {
|
||||
if(xConnection == null) throw new NullPointerException("the XConnection must not be null");
|
||||
|
||||
if(DEBUG) System.err.println("#### " + getClass().getName() + " - instantiated ");
|
||||
|
||||
_xConnection = xConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int len;
|
||||
|
||||
try {
|
||||
len = _xConnection.read(_bytes, 1);
|
||||
} catch(com.sun.star.io.IOException ioException) {
|
||||
IOException ex = new IOException(ioException.getMessage());
|
||||
ex.initCause(ioException);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(DEBUG) System.err.println("#### " + getClass().getName() + " - one byte read:" + _bytes[0][0]);
|
||||
|
||||
return len == 0 ? -1 : _bytes[0][0] & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
try {
|
||||
len = _xConnection.read(_bytes, len - off);
|
||||
} catch(com.sun.star.io.IOException ioException) {
|
||||
IOException ex = new IOException(ioException.getMessage());
|
||||
ex.initCause(ioException);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
System.arraycopy(_bytes[0], 0, b, off, len);
|
||||
|
||||
return len == 0 ? -1 : len;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,89 @@
|
||||
/* -*- 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.lib.uno.bridges.java_remote;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.sun.star.connection.XConnection;
|
||||
|
||||
|
||||
class XConnectionOutputStream_Adapter extends OutputStream {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
protected XConnection _xConnection;
|
||||
protected byte _bytes[] = new byte[1];
|
||||
|
||||
XConnectionOutputStream_Adapter(XConnection xConnection) {
|
||||
if(DEBUG) System.err.println("#### " + this.getClass() + " - instantiated ");
|
||||
|
||||
_xConnection = xConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
_bytes[0] = (byte)b;
|
||||
|
||||
try {
|
||||
_xConnection.write(_bytes);
|
||||
} catch(com.sun.star.io.IOException ioException) {
|
||||
IOException ex = new IOException(ioException.getMessage());
|
||||
ex.initCause(ioException);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if(DEBUG) System.err.println("#### " + this.getClass() + " - one byte written:" + _bytes[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
byte bytes[] ;
|
||||
|
||||
if(off == 0 && len == b.length) {
|
||||
bytes = b;
|
||||
} else {
|
||||
bytes = new byte[len];
|
||||
|
||||
System.arraycopy(b, off, bytes, 0, len);
|
||||
}
|
||||
|
||||
try {
|
||||
_xConnection.write(bytes);
|
||||
} catch(com.sun.star.io.IOException ioException) {
|
||||
IOException ex = new IOException(ioException.getMessage());
|
||||
ex.initCause(ioException);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
try {
|
||||
_xConnection.flush();
|
||||
} catch(com.sun.star.io.IOException ioException) {
|
||||
IOException ex = new IOException(ioException.getMessage());
|
||||
ex.initCause(ioException);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,700 @@
|
||||
/* -*- 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.lib.uno.bridges.java_remote;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.sun.star.bridge.XBridge;
|
||||
import com.sun.star.bridge.XInstanceProvider;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.lang.DisposedException;
|
||||
import com.sun.star.lang.EventObject;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XEventListener;
|
||||
import com.sun.star.lib.uno.environments.java.java_environment;
|
||||
import com.sun.star.lib.uno.environments.remote.IProtocol;
|
||||
import com.sun.star.lib.uno.environments.remote.IReceiver;
|
||||
import com.sun.star.lib.uno.environments.remote.IThreadPool;
|
||||
import com.sun.star.lib.uno.environments.remote.Job;
|
||||
import com.sun.star.lib.uno.environments.remote.Message;
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadId;
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadPoolManager;
|
||||
import com.sun.star.lib.uno.typedesc.MethodDescription;
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import com.sun.star.lib.util.DisposeListener;
|
||||
import com.sun.star.lib.util.DisposeNotifier;
|
||||
import com.sun.star.uno.Any;
|
||||
import com.sun.star.uno.IBridge;
|
||||
import com.sun.star.uno.IEnvironment;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.TypeClass;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XInterface;
|
||||
|
||||
/**
|
||||
* This class implements a remote bridge.
|
||||
*
|
||||
* <p>Therefore various interfaces are implemented.</p>
|
||||
*
|
||||
* <p>The protocol to used is passed by name, the bridge
|
||||
* then looks for it under <code>com.sun.star.lib.uno.protocols</code>.</p>
|
||||
*
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class java_remote_bridge
|
||||
implements IBridge, IReceiver, RequestHandler, XBridge, XComponent,
|
||||
DisposeNotifier
|
||||
{
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final class MessageDispatcher extends Thread {
|
||||
public MessageDispatcher() {
|
||||
super("MessageDispatcher");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (;;) {
|
||||
synchronized (this) {
|
||||
if (terminate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Message msg = _iProtocol.readMessage();
|
||||
Object obj = null;
|
||||
if (msg.isRequest()) {
|
||||
String oid = msg.getObjectId();
|
||||
Type type = new Type(msg.getType());
|
||||
int fid = msg.getMethod().getIndex();
|
||||
if (fid == MethodDescription.ID_RELEASE) {
|
||||
_java_environment.revokeInterface(oid, type);
|
||||
remRefHolder(type, oid);
|
||||
if (msg.isSynchronous()) {
|
||||
sendReply(false, msg.getThreadId(), null);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
obj = _java_environment.getRegisteredInterface(
|
||||
oid, type);
|
||||
if (obj == null
|
||||
&& fid == MethodDescription.ID_QUERY_INTERFACE)
|
||||
{
|
||||
if (_xInstanceProvider == null) {
|
||||
sendReply(
|
||||
true, msg.getThreadId(),
|
||||
new com.sun.star.uno.RuntimeException(
|
||||
"unknown OID " + oid));
|
||||
continue;
|
||||
} else {
|
||||
UnoRuntime.setCurrentContext(
|
||||
msg.getCurrentContext());
|
||||
try {
|
||||
obj = _xInstanceProvider.getInstance(oid);
|
||||
} catch (com.sun.star.uno.RuntimeException e) {
|
||||
sendReply(true, msg.getThreadId(), e);
|
||||
continue;
|
||||
} catch (Exception e) {
|
||||
sendReply(
|
||||
true, msg.getThreadId(),
|
||||
new com.sun.star.uno.RuntimeException(
|
||||
e.toString()));
|
||||
continue;
|
||||
} finally {
|
||||
UnoRuntime.setCurrentContext(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_iThreadPool.putJob(
|
||||
new Job(obj, java_remote_bridge.this, msg));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
dispose(e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void terminate() {
|
||||
terminate = true;
|
||||
}
|
||||
|
||||
private boolean terminate = false;
|
||||
}
|
||||
|
||||
protected XConnection _xConnection;
|
||||
|
||||
protected XInstanceProvider _xInstanceProvider;
|
||||
|
||||
protected String _name = "remote";
|
||||
private final String protocol;
|
||||
protected IProtocol _iProtocol;
|
||||
protected IEnvironment _java_environment;
|
||||
protected MessageDispatcher _messageDispatcher;
|
||||
protected final AtomicInteger _life_count = new AtomicInteger(); // determines if this bridge is alive, which is controlled by acquire and release calls
|
||||
|
||||
private final ArrayList<XEventListener> _listeners = new ArrayList<XEventListener>();
|
||||
|
||||
protected IThreadPool _iThreadPool;
|
||||
|
||||
// Variable disposed must only be used while synchronized on this object:
|
||||
private boolean disposed = false;
|
||||
|
||||
/**
|
||||
* This method is for testing only.
|
||||
*/
|
||||
int getLifeCount() {
|
||||
return _life_count.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is for testing only.
|
||||
*/
|
||||
IProtocol getProtocol() {
|
||||
return _iProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ref holder stuff strongly holds objects mapped out via this bridge
|
||||
* (the java_environment only holds them weakly).
|
||||
*
|
||||
* <p>When this bridge is disposed, all remaining ref holder entries are
|
||||
* released.</p>
|
||||
*/
|
||||
private static final class RefHolder {
|
||||
public RefHolder(Type type, Object object) {
|
||||
this.type = type;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void acquire() {
|
||||
++count;
|
||||
}
|
||||
|
||||
public boolean release() {
|
||||
return --count == 0;
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
@SuppressWarnings("unused")
|
||||
private final Object object;
|
||||
private int count = 1;
|
||||
}
|
||||
|
||||
private final HashMap<String, LinkedList<RefHolder>> refHolders = new HashMap<String, LinkedList<RefHolder>>();
|
||||
// from OID (String) to LinkedList of RefHolder
|
||||
|
||||
private boolean hasRefHolder(String oid, Type type) {
|
||||
synchronized (refHolders) {
|
||||
LinkedList<RefHolder> l = refHolders.get(oid);
|
||||
if (l != null) {
|
||||
for (RefHolder rh : l) {
|
||||
if (type.isSupertypeOf(rh.getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
final void addRefHolder(Object obj, Type type, String oid) {
|
||||
synchronized (refHolders) {
|
||||
LinkedList<RefHolder> l = refHolders.get(oid);
|
||||
if (l == null) {
|
||||
l = new LinkedList<RefHolder>();
|
||||
refHolders.put(oid, l);
|
||||
}
|
||||
boolean found = false;
|
||||
for (Iterator<RefHolder> i = l.iterator(); !found && i.hasNext();) {
|
||||
RefHolder rh = i.next();
|
||||
if (rh.getType().equals(type)) {
|
||||
found = true;
|
||||
rh.acquire();
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
l.add(new RefHolder(type, obj));
|
||||
}
|
||||
}
|
||||
acquire();
|
||||
}
|
||||
|
||||
final void remRefHolder(Type type, String oid) {
|
||||
synchronized (refHolders) {
|
||||
LinkedList<RefHolder> l = refHolders.get(oid);
|
||||
if (l == null) {
|
||||
return;
|
||||
}
|
||||
for (RefHolder rh : l) {
|
||||
if (rh.getType().equals(type)) {
|
||||
try {
|
||||
if (rh.release()) {
|
||||
l.remove(rh);
|
||||
if (l.isEmpty()) {
|
||||
refHolders.remove(oid);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final void freeHolders() {
|
||||
synchronized (refHolders) {
|
||||
for (Iterator<Map.Entry<String,LinkedList<RefHolder>>> i1 = refHolders.entrySet().iterator(); i1.hasNext();)
|
||||
{
|
||||
Map.Entry<String,LinkedList<RefHolder>> e = i1.next();
|
||||
String oid = e.getKey();
|
||||
LinkedList<RefHolder> l = e.getValue();
|
||||
for (Iterator<RefHolder> i2 = l.iterator(); i2.hasNext();) {
|
||||
RefHolder rh = i2.next();
|
||||
for (boolean done = false; !done;) {
|
||||
done = rh.release();
|
||||
_java_environment.revokeInterface(oid, rh.getType());
|
||||
release();
|
||||
}
|
||||
}
|
||||
}
|
||||
refHolders.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public java_remote_bridge(
|
||||
IEnvironment java_environment, IEnvironment remote_environment,
|
||||
Object[] args)
|
||||
throws Exception
|
||||
{
|
||||
_java_environment = java_environment;
|
||||
String proto = (String) args[0];
|
||||
_xConnection = (XConnection) args[1];
|
||||
_xInstanceProvider = (XInstanceProvider) args[2];
|
||||
if (args.length > 3) {
|
||||
_name = (String) args[3];
|
||||
}
|
||||
String attr;
|
||||
int i = proto.indexOf(',');
|
||||
if (i >= 0) {
|
||||
protocol = proto.substring(0, i);
|
||||
attr = proto.substring(i + 1);
|
||||
} else {
|
||||
protocol = proto;
|
||||
attr = null;
|
||||
}
|
||||
_iProtocol = (IProtocol) Class.forName(
|
||||
"com.sun.star.lib.uno.protocols." + protocol + "." + protocol).
|
||||
getConstructor(
|
||||
new Class[] {
|
||||
IBridge.class, String.class, InputStream.class,
|
||||
OutputStream.class }).
|
||||
newInstance(
|
||||
new Object[] {
|
||||
this, attr,
|
||||
new XConnectionInputStream_Adapter(_xConnection),
|
||||
new XConnectionOutputStream_Adapter(_xConnection) });
|
||||
proxyFactory = new ProxyFactory(this, this);
|
||||
_iThreadPool = ThreadPoolManager.create();
|
||||
_messageDispatcher = new MessageDispatcher();
|
||||
_messageDispatcher.start();
|
||||
_iProtocol.init();
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
EventObject eventObject = new EventObject(this);
|
||||
|
||||
Iterator<XEventListener> elements = _listeners.iterator();
|
||||
while(elements.hasNext()) {
|
||||
XEventListener xEventListener = elements.next();
|
||||
|
||||
try {
|
||||
xEventListener.disposing(eventObject);
|
||||
}
|
||||
catch(com.sun.star.uno.RuntimeException runtimeException) {
|
||||
// we are here not interested in any exceptions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new bridge.
|
||||
* <p> This method is not part of the provided <code>api</code>
|
||||
* and should only be used by the UNO runtime.</p>
|
||||
*
|
||||
* @param args the custom parameters: arg[0] == protocol_name,
|
||||
* arg[1] == xConnection, arg[2] == xInstanceProvider.
|
||||
*
|
||||
* @deprecated as of UDK 1.0
|
||||
*/
|
||||
@Deprecated
|
||||
public java_remote_bridge(Object args[]) throws Exception {
|
||||
this(UnoRuntime.getEnvironment("java", null), UnoRuntime.getEnvironment("remote", null), args);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.uno.IBridge#mapInterfaceTo
|
||||
*/
|
||||
public Object mapInterfaceTo(Object object, Type type) {
|
||||
checkDisposed();
|
||||
if (object == null) {
|
||||
return null;
|
||||
} else {
|
||||
String[] oid = new String[1];
|
||||
object = _java_environment.registerInterface(object, oid, type);
|
||||
if (!proxyFactory.isProxy(object)) {
|
||||
// This branch must be taken iff object either is no proxy at
|
||||
// all or a proxy from some other bridge. There are objects
|
||||
// that behave like objects for this bridge but that are not
|
||||
// detected as such by proxyFactory.isProxy. The only known
|
||||
// case of such objects is com.sun.star.comp.beans.Wrapper,
|
||||
// which implements com.sun.star.lib.uno.Proxy and effectively
|
||||
// is a second proxy around a proxy that can be from this
|
||||
// bridge. For that case, there is no problem, however: Since
|
||||
// the proxies generated by ProxyFactory send each
|
||||
// queryInterface to the original object (i.e., they do not
|
||||
// short-circuit requests for a super-interface to themselves),
|
||||
// there will always be an appropriate ProxyFactory-proxy
|
||||
// registered at the _java_environment, so that the object
|
||||
// returned by _java_environment.registerInterface will never be
|
||||
// a com.sun.star.comp.beans.Wrapper.
|
||||
addRefHolder(object, type, oid[0]);
|
||||
}
|
||||
return oid[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps an object from destination environment to the source environment.
|
||||
*
|
||||
* @param oId the object to map.
|
||||
* @param type the interface under which is to be mapped.
|
||||
* @return the object in the source environment.
|
||||
*
|
||||
* @see com.sun.star.uno.IBridge#mapInterfaceFrom
|
||||
*/
|
||||
public Object mapInterfaceFrom(Object oId, Type type) {
|
||||
checkDisposed();
|
||||
// TODO What happens if an exception is thrown after the call to
|
||||
// acquire, but before it is guaranteed that a pairing release will be
|
||||
// called eventually?
|
||||
acquire();
|
||||
String oid = (String) oId;
|
||||
Object object = _java_environment.getRegisteredInterface(oid, type);
|
||||
if (object == null) {
|
||||
object = _java_environment.registerInterface(
|
||||
proxyFactory.create(oid, type), new String[] { oid }, type);
|
||||
// the proxy sends a release when finalized
|
||||
} else if (!hasRefHolder(oid, type)) {
|
||||
sendInternalRequest(oid, type, "release", null);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the source environment.
|
||||
*
|
||||
* @return the source environment of this bridge.
|
||||
* @see com.sun.star.uno.IBridge#getSourceEnvironment
|
||||
*/
|
||||
public IEnvironment getSourceEnvironment() {
|
||||
return _java_environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the destination environment.
|
||||
*
|
||||
* @return the destination environment of this bridge.
|
||||
* @see com.sun.star.uno.IBridge#getTargetEnvironment
|
||||
*/
|
||||
public IEnvironment getTargetEnvironment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the life count.
|
||||
*
|
||||
* @see com.sun.star.uno.IBridge#acquire
|
||||
*/
|
||||
public void acquire() {
|
||||
if(DEBUG) {
|
||||
int x = _life_count.incrementAndGet();
|
||||
System.err.println("##### " + getClass().getName() + ".acquire:" + x);
|
||||
} else {
|
||||
_life_count.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the life count.
|
||||
*
|
||||
* <p>If the life count drops to zero, the bridge disposes itself.</p>
|
||||
*
|
||||
* @see com.sun.star.uno.IBridge#release
|
||||
*/
|
||||
public void release() {
|
||||
int x = _life_count.decrementAndGet();
|
||||
if (x <= 0) {
|
||||
dispose(new Throwable("end of life"));
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
dispose(new Throwable("user dispose"));
|
||||
}
|
||||
|
||||
private void dispose(Throwable throwable) {
|
||||
synchronized (this) {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
for (Iterator<DisposeListener> i = disposeListeners.iterator(); i.hasNext();) {
|
||||
i.next().notifyDispose(this);
|
||||
}
|
||||
|
||||
_iProtocol.terminate();
|
||||
|
||||
try {
|
||||
_messageDispatcher.terminate();
|
||||
|
||||
try {
|
||||
_xConnection.close();
|
||||
} catch (com.sun.star.io.IOException e) {
|
||||
System.err.println(
|
||||
getClass().getName() + ".dispose - IOException:" + e);
|
||||
}
|
||||
|
||||
if (Thread.currentThread() != _messageDispatcher
|
||||
&& _messageDispatcher.isAlive())
|
||||
{
|
||||
_messageDispatcher.join(1000);
|
||||
if (_messageDispatcher.isAlive()) {
|
||||
_messageDispatcher.interrupt();
|
||||
_messageDispatcher.join();
|
||||
}
|
||||
}
|
||||
|
||||
// interrupt all jobs queued by this bridge
|
||||
_iThreadPool.dispose(throwable);
|
||||
|
||||
// release all out-mapped objects and all in-mapped proxies:
|
||||
freeHolders();
|
||||
// assert _java_environment instanceof java_environment;
|
||||
((java_environment) _java_environment).revokeAllProxies();
|
||||
|
||||
proxyFactory.dispose();
|
||||
|
||||
if (DEBUG) {
|
||||
if (_life_count.get() != 0) {
|
||||
System.err.println(getClass().getName()
|
||||
+ ".dispose - life count (proxies left):"
|
||||
+ _life_count);
|
||||
}
|
||||
_java_environment.list();
|
||||
}
|
||||
|
||||
// clear members
|
||||
_xConnection = null;
|
||||
_java_environment = null;
|
||||
_messageDispatcher = null;
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println(getClass().getName()
|
||||
+ ".dispose - InterruptedException:" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.bridge.XBridge#getInstance
|
||||
*/
|
||||
public Object getInstance(String instanceName) {
|
||||
Type t = new Type(XInterface.class);
|
||||
return sendInternalRequest(
|
||||
instanceName, t, "queryInterface", new Object[] { t });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the name of this bridge.
|
||||
*
|
||||
* @return the name of this bridge.
|
||||
* @see com.sun.star.bridge.XBridge#getName
|
||||
*/
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a description of the connection type and protocol used.
|
||||
*
|
||||
* @return connection type and protocol.
|
||||
* @see com.sun.star.bridge.XBridge#getDescription
|
||||
*/
|
||||
public String getDescription() {
|
||||
return protocol + "," + _xConnection.getDescription();
|
||||
}
|
||||
|
||||
public void sendReply(boolean exception, ThreadId threadId, Object result) {
|
||||
if (DEBUG) {
|
||||
System.err.println("##### " + getClass().getName() + ".sendReply: "
|
||||
+ exception + " " + result);
|
||||
}
|
||||
|
||||
checkDisposed();
|
||||
|
||||
try {
|
||||
_iProtocol.writeReply(exception, threadId, result);
|
||||
} catch (IOException e) {
|
||||
dispose(e);
|
||||
throw (DisposedException)
|
||||
(new DisposedException("unexpected " + e).initCause(e));
|
||||
} catch (RuntimeException e) {
|
||||
dispose(e);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
dispose(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public Object sendRequest(
|
||||
String oid, Type type, String operation, Object[] params)
|
||||
throws Throwable
|
||||
{
|
||||
Object result = null;
|
||||
|
||||
checkDisposed();
|
||||
|
||||
ThreadId threadId = _iThreadPool.getThreadId();
|
||||
Object handle = _iThreadPool.attach(threadId);
|
||||
try {
|
||||
boolean sync;
|
||||
try {
|
||||
sync = _iProtocol.writeRequest(
|
||||
oid, TypeDescription.getTypeDescription(type), operation,
|
||||
threadId, params);
|
||||
} catch (IOException e) {
|
||||
dispose(e);
|
||||
throw (DisposedException)
|
||||
new DisposedException(e.toString()).initCause(e);
|
||||
}
|
||||
if (sync && Thread.currentThread() != _messageDispatcher) {
|
||||
result = _iThreadPool.enter(handle, threadId);
|
||||
}
|
||||
} finally {
|
||||
_iThreadPool.detach(handle, threadId);
|
||||
if(operation.equals("release"))
|
||||
release(); // kill this bridge, if this was the last proxy
|
||||
}
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".sendRequest left:" + result);
|
||||
|
||||
// On the wire (at least in URP), the result of queryInterface is
|
||||
// transported as an ANY, but in Java it shall be transported as a
|
||||
// direct reference to the UNO object (represented as a Java Object),
|
||||
// never boxed in a com.sun.star.uno.Any:
|
||||
if (operation.equals("queryInterface") && result instanceof Any) {
|
||||
Any a = (Any) result;
|
||||
if (a.getType().getTypeClass() == TypeClass.INTERFACE) {
|
||||
result = a.getObject();
|
||||
} else {
|
||||
result = null; // should never happen
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object sendInternalRequest(
|
||||
String oid, Type type, String operation, Object[] arguments)
|
||||
{
|
||||
try {
|
||||
return sendRequest(oid, type, operation, arguments);
|
||||
} catch (Error e) {
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Unexpected " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods XComponent.
|
||||
*/
|
||||
public void addEventListener(XEventListener xEventListener) {
|
||||
_listeners.add(xEventListener);
|
||||
}
|
||||
|
||||
public void removeEventListener(XEventListener xEventListener) {
|
||||
_listeners.remove(xEventListener);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see DisposeNotifier#addDisposeListener
|
||||
*/
|
||||
public void addDisposeListener(DisposeListener listener) {
|
||||
synchronized (this) {
|
||||
if (!disposed) {
|
||||
disposeListeners.add(listener);
|
||||
return;
|
||||
}
|
||||
}
|
||||
listener.notifyDispose(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function must only be called while synchronized on this object.
|
||||
*/
|
||||
private synchronized void checkDisposed() {
|
||||
if (disposed) {
|
||||
throw new DisposedException("java_remote_bridge " + this
|
||||
+ " is disposed");
|
||||
}
|
||||
}
|
||||
|
||||
private final ProxyFactory proxyFactory;
|
||||
|
||||
// Access to disposeListeners must be synchronized on <CODE>this</CODE>:
|
||||
private final ArrayList<DisposeListener> disposeListeners = new ArrayList<DisposeListener>();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,312 @@
|
||||
/* -*- 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.lib.uno.environments.java;
|
||||
|
||||
import com.sun.star.uno.IEnvironment;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The java_environment is the environment where objects and
|
||||
* interfaces are registered, which are mapped out of java or
|
||||
* into java.
|
||||
*
|
||||
* <p>The java_environment implements the <code>IEnvironment</code> interface
|
||||
* defined in the uno runtime.</p>
|
||||
*
|
||||
* @see com.sun.star.uno.UnoRuntime
|
||||
* @see com.sun.star.uno.IEnvironment
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public final class java_environment implements IEnvironment {
|
||||
public java_environment(Object context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.uno.IEnvironment#getContext
|
||||
*/
|
||||
public Object getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.uno.IEnvironment#getName
|
||||
*/
|
||||
public String getName() {
|
||||
return "java";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.uno.IEnvironment#registerInterface
|
||||
*/
|
||||
public Object registerInterface(Object object, String[] oid, Type type) {
|
||||
if (oid[0] == null) {
|
||||
oid[0] = UnoRuntime.generateOid(object);
|
||||
}
|
||||
return (isProxy(object) ? proxies : localObjects).register(
|
||||
object, oid[0], type);
|
||||
}
|
||||
|
||||
/**
|
||||
* You have to revoke ANY interface that has been registered via this
|
||||
* method.
|
||||
*
|
||||
* @param oid object id of interface to be revoked.
|
||||
* @param type the type description of the interface.
|
||||
* @see com.sun.star.uno.IEnvironment#revokeInterface
|
||||
*/
|
||||
public void revokeInterface(String oid, Type type) {
|
||||
if (!proxies.revoke(oid, type)) {
|
||||
localObjects.revoke(oid, type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an interface identified by its object id and type from this
|
||||
* environment.
|
||||
*
|
||||
* @param oid object id of interface to be retrieved.
|
||||
* @param type the type description of the interface to be retrieved.
|
||||
* @see com.sun.star.uno.IEnvironment#getRegisteredInterface
|
||||
*/
|
||||
public Object getRegisteredInterface(String oid, Type type) {
|
||||
Object o = proxies.get(oid, type);
|
||||
if (o == null) {
|
||||
o = localObjects.get(oid, type);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the object identifier for a registered interface from this
|
||||
* environment.
|
||||
*
|
||||
* @param object a registered interface.
|
||||
* @see com.sun.star.uno.IEnvironment#getRegisteredObjectIdentifier
|
||||
*/
|
||||
public String getRegisteredObjectIdentifier(Object object) {
|
||||
return UnoRuntime.generateOid(object);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.sun.star.uno.IEnvironment#list
|
||||
*/
|
||||
public void list() {
|
||||
// TODO???
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes all registered proxy interfaces.
|
||||
*
|
||||
* <p>This method should be part of <code>IEnvironment</code>. It is called
|
||||
* from <code>com.sun.star.lib.uno.bridges.java_remote.<!--
|
||||
* -->java_remote_bridge.dispose</code>.</p>
|
||||
*/
|
||||
public void revokeAllProxies() {
|
||||
proxies.clear();
|
||||
}
|
||||
|
||||
// TODO What's this??? java.lang.Object#equals requires reflexivity...
|
||||
//
|
||||
// Maybe this was hacked in so that different bridges use different
|
||||
// instances of java_environment. That is desirable for the following
|
||||
// reason: An OID is bridged in over bridge A, a proxy is created on the
|
||||
// Java side, and recorded in the java_environment. The same OID is then
|
||||
// bridged in over another bridge B. If there were only one
|
||||
// java_environment shared by both bridges, the proxy from bridge A would be
|
||||
// reused. If now bridge A is taken down programmatically (e.g., because
|
||||
// some controlling code somehow deduced that no objects are mapped over
|
||||
// that bridge any longer), but the proxy is still used by bridge B, using
|
||||
// the proxy would now result in errors. The explicit API to control
|
||||
// bridges forbids to transparently share proxies between bridges, and using
|
||||
// different java_environment instances for different bridges is the way to
|
||||
// enforce this.
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final class Registry {
|
||||
public synchronized Object register(
|
||||
Object object, String oid, Type type)
|
||||
{
|
||||
cleanUp();
|
||||
Level1Entry l1 = level1map.get(oid);
|
||||
if (l1 != null) {
|
||||
Level2Entry l2 = l1.level2map.get(type);
|
||||
if (l2 != null) {
|
||||
Object o = l2.get();
|
||||
if (o != null) {
|
||||
l2.acquire();
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO If a holder references an unreachable object, but still has
|
||||
// a positive count, it is replaced with a new holder (referencing a
|
||||
// reachable object, and with a count of 1). Any later calls to
|
||||
// revoke that should decrement the count of the previous holder
|
||||
// would now decrement the count of the new holder, removing it
|
||||
// prematurely. This is a design flaw that will be fixed when
|
||||
// IEnvironment.revokeInterface is changed to no longer use
|
||||
// counting. (And this problem is harmless, as currently a holder
|
||||
// either references a strongly held object and uses register/revoke
|
||||
// to control it, or references a weakly held proxy and never
|
||||
// revokes it.)
|
||||
if (l1 == null) {
|
||||
l1 = new Level1Entry();
|
||||
level1map.put(oid, l1);
|
||||
}
|
||||
l1.level2map.put(type, new Level2Entry(oid, type, object, queue));
|
||||
return object;
|
||||
}
|
||||
|
||||
public synchronized boolean revoke(String oid, Type type) {
|
||||
Level1Entry l1 = level1map.get(oid);
|
||||
Level2Entry l2 = null;
|
||||
if (l1 != null) {
|
||||
l2 = l1.level2map.get(type);
|
||||
if (l2 != null && l2.release()) {
|
||||
removeLevel2Entry(l1, oid, type);
|
||||
}
|
||||
}
|
||||
cleanUp();
|
||||
return l2 != null;
|
||||
}
|
||||
|
||||
public synchronized Object get(String oid, Type type) {
|
||||
Level1Entry l1 = level1map.get(oid);
|
||||
return l1 == null ? null : l1.find(type);
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
level1map.clear();
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
// must only be called while synchronized on this Registry:
|
||||
private void cleanUp() {
|
||||
for (;;) {
|
||||
Object tmp = queue.poll();
|
||||
Level2Entry l2 = (Level2Entry) tmp;
|
||||
if (l2 == null) {
|
||||
break;
|
||||
}
|
||||
// It is possible that a Level2Entry e1 for the OID/type pair
|
||||
// (o,t) becomes weakly reachable, then another Level2Entry e2
|
||||
// is registered for the same pair (o,t) (a new Level2Entry is
|
||||
// created since now e1.get() == null), and only then e1 is
|
||||
// enqueued. To not erroneously remove the new e2 in that case,
|
||||
// check whether the map still contains e1:
|
||||
Level1Entry l1 = level1map.get(l2.oid);
|
||||
if (l1 != null && l1.level2map.get(l2.type) == l2) {
|
||||
removeLevel2Entry(l1, l2.oid, l2.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// must only be called while synchronized on this Registry:
|
||||
private void removeLevel2Entry(Level1Entry l1, String oid, Type type) {
|
||||
l1.level2map.remove(type);
|
||||
if (l1.level2map.isEmpty()) {
|
||||
level1map.remove(oid);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Level1Entry {
|
||||
// must only be called while synchronized on enclosing Registry:
|
||||
public Object find(Type type) {
|
||||
// First, look for an exactly matching entry; then, look for an
|
||||
// arbitrary entry for a subtype of the request type:
|
||||
Level2Entry l2 = level2map.get(type);
|
||||
if (l2 != null) {
|
||||
Object o = l2.get();
|
||||
if (o != null) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
for (Iterator<Level2Entry> i = level2map.values().iterator();
|
||||
i.hasNext();)
|
||||
{
|
||||
l2 = i.next();
|
||||
if (type.isSupertypeOf(l2.type)) {
|
||||
Object o = l2.get();
|
||||
if (o != null) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final HashMap<Type, Level2Entry> level2map =
|
||||
new HashMap<Type, Level2Entry>();
|
||||
}
|
||||
|
||||
private static final class Level2Entry extends WeakReference<Object> {
|
||||
public Level2Entry(
|
||||
String oid, Type type, Object object, ReferenceQueue<Object> queue)
|
||||
{
|
||||
super(object, queue);
|
||||
this.oid = oid;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
// must only be called while synchronized on enclosing Registry:
|
||||
public void acquire() {
|
||||
++count;
|
||||
}
|
||||
|
||||
// must only be called while synchronized on enclosing Registry:
|
||||
public boolean release() {
|
||||
return --count == 0;
|
||||
}
|
||||
|
||||
public final String oid;
|
||||
public final Type type;
|
||||
|
||||
private int count = 1;
|
||||
}
|
||||
|
||||
private final HashMap<String, Level1Entry> level1map =
|
||||
new HashMap<String, Level1Entry>();
|
||||
private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
|
||||
}
|
||||
|
||||
private boolean isProxy(Object object) {
|
||||
return object instanceof com.sun.star.lib.uno.Proxy;
|
||||
}
|
||||
|
||||
private static final Registry localObjects = new Registry();
|
||||
|
||||
private final Object context;
|
||||
private final Registry proxies = new Registry();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,93 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An abstraction of remote bridge protocols.
|
||||
*
|
||||
* <p>A class implementing a given protocol <var>prot</var> must be named
|
||||
* <code>com.sun.star.lib.uno.protocols.<var>prot</var>.<var>prot</var></code>
|
||||
* and must have a public constructor that takes four arguments: The first
|
||||
* argument of type <code>com.sun.star.uno.IBridge</code> must not be null. The
|
||||
* second argument of type <code>String</code> represents any attributes; it may
|
||||
* be null if there are no attributes. The third argument of type
|
||||
* <code>java.io.InputStream</code> must not be null. The fourth argument of
|
||||
* type <code>java.io.OutputStream</code> must not be null.</p>
|
||||
*/
|
||||
public interface IProtocol {
|
||||
/**
|
||||
* Initializes the connection.
|
||||
*
|
||||
* <p>This method must be called exactly once, after the
|
||||
* <code>readMessage</code> loop has already been established.</p>
|
||||
*/
|
||||
void init() throws IOException;
|
||||
|
||||
void terminate();
|
||||
|
||||
/**
|
||||
* Reads a request or reply message.
|
||||
*
|
||||
* <p>Access to this method from multiple threads must be properly
|
||||
* synchronized.</p>
|
||||
*
|
||||
* @return a non-null message; if the input stream is exhausted, a
|
||||
* <code>java.io.IOException</code> is thrown instead.
|
||||
*/
|
||||
Message readMessage() throws IOException;
|
||||
|
||||
/**
|
||||
* Writes a request message.
|
||||
*
|
||||
* @param oid a non-null OID.
|
||||
* @param type a non-null UNO type.
|
||||
* @param function a non-null function (the name of a UNO interface method
|
||||
* or attribute compatible with the given <code>type</code>, or either
|
||||
* <code>"queryInterface"</code> or <code>"release"</code>).
|
||||
* @param tid a non-null TID.
|
||||
* @param arguments a list of UNO arguments compatible with the given
|
||||
* <code>type</code> and <code>function</code>; may be null to represent
|
||||
* an empty list.
|
||||
* @return <code>true</code> if the request message is sent as a synchronous
|
||||
* request.
|
||||
*/
|
||||
boolean writeRequest(
|
||||
String oid, TypeDescription type, String function, ThreadId tid,
|
||||
Object[] arguments)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Writes a reply message.
|
||||
*
|
||||
* @param exception <code>true</code> if the reply corresponds to a raised
|
||||
* exception.
|
||||
* @param tid a non-null TID.
|
||||
* @param result if <code>exception</code> is <code>true</code>, a non-null
|
||||
* UNO exception; otherwise, a UNO return value, which may be null to
|
||||
* represent a <code>VOID</code> return value.
|
||||
*/
|
||||
void writeReply(boolean exception, ThreadId tid, Object result)
|
||||
throws IOException;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
/**
|
||||
* An abstraction for giving back a reply for a request.
|
||||
*
|
||||
* @see com.sun.star.uno.IQueryInterface
|
||||
*/
|
||||
public interface IReceiver {
|
||||
/**
|
||||
* Send back a reply for a request.
|
||||
*
|
||||
* @param exception <CODE>true</CODE> if an exception (instead of a normal
|
||||
* result) is sent back.
|
||||
* @param threadId the thread ID of the request.
|
||||
* @param result the result of executing the request, or an exception thrown
|
||||
* while executing the request.
|
||||
*/
|
||||
void sendReply(boolean exception, ThreadId threadId, Object result);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,115 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
/**
|
||||
* This interface is an abstraction of the various threadpool implementations.
|
||||
*
|
||||
* @see com.sun.star.lib.uno.environments.remote.ThreadPoolManager
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public interface IThreadPool {
|
||||
/**
|
||||
* Retrieves the global threadId for the current thread.
|
||||
*
|
||||
* @return the thread id.
|
||||
*/
|
||||
ThreadId getThreadId();
|
||||
|
||||
/**
|
||||
* Attaches this thread to the thread pool.
|
||||
*
|
||||
* @see #enter
|
||||
*/
|
||||
void attach();
|
||||
|
||||
/**
|
||||
* As above, but hands in an already existing instance of the threadid of
|
||||
* the current thread.
|
||||
*
|
||||
* <p>The function exists for performance.</p>
|
||||
*
|
||||
* @return Returns a handle which can be used in enter and detach calls.
|
||||
* @see #attach
|
||||
*/
|
||||
Object attach( ThreadId id );
|
||||
|
||||
/**
|
||||
* Detaches this thread from the thread pool.
|
||||
* @see #enter
|
||||
*/
|
||||
void detach();
|
||||
|
||||
/**
|
||||
* As above, but hands in an already existing instance of the threadid of
|
||||
* the current thread and a handle returned by attach.
|
||||
*
|
||||
* <p>The function exists for performance.</p>
|
||||
*
|
||||
* @see #attach()
|
||||
* @see #detach()
|
||||
*/
|
||||
void detach( Object handle, ThreadId id );
|
||||
|
||||
/**
|
||||
* Lets this thread enter the thread pool.
|
||||
*
|
||||
* <p>This thread then executes all jobs put via <code>putJob</code> until
|
||||
* a reply job arrives.</p>
|
||||
*
|
||||
* @see #putJob
|
||||
*/
|
||||
Object enter() throws Throwable;
|
||||
|
||||
/**
|
||||
* As above but hands in an already existing instance of the threadid of
|
||||
* the current thread and a handle returned by attach.
|
||||
*
|
||||
* <p>This thread then executes all jobs put via <code>putJob</code> until
|
||||
* a reply job arrives.</p>
|
||||
*
|
||||
* @see #putJob
|
||||
*/
|
||||
Object enter( Object handle, ThreadId id ) throws Throwable;
|
||||
|
||||
/**
|
||||
* Queues a job into the jobQueue of the thread belonging to the jobs
|
||||
* threadId.
|
||||
*
|
||||
* @param job the job
|
||||
*/
|
||||
void putJob(Job job);
|
||||
|
||||
/**
|
||||
* Disposes this thread pool, thus releasing all threads by throwing a
|
||||
* <code>DisposedException</code> with the given <code>Throwable</code> cause.
|
||||
*
|
||||
* @param throwable the cause
|
||||
*/
|
||||
void dispose(Throwable throwable);
|
||||
|
||||
|
||||
/**
|
||||
* Destroys the thread pool and tries to join all created threads immediately.
|
||||
*/
|
||||
void destroy();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,124 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
/**
|
||||
* This class implements a java thread pool.
|
||||
*
|
||||
* @see com.sun.star.uno.UnoRuntime
|
||||
* @see com.sun.star.lib.uno.environments.remote.NativeThreadPool
|
||||
* @see com.sun.star.lib.uno.environments.remote.IThreadPool
|
||||
* @see com.sun.star.lib.uno.environments.remote.Job
|
||||
* @see com.sun.star.lib.uno.environments.remote.JobQueue
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class JavaThreadPool implements IThreadPool {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
JavaThreadPoolFactory _javaThreadPoolFactory;
|
||||
|
||||
JavaThreadPool(JavaThreadPoolFactory javaThreadPoolFactory) {
|
||||
_javaThreadPoolFactory = javaThreadPoolFactory;
|
||||
}
|
||||
|
||||
public ThreadId getThreadId() {
|
||||
return JavaThreadPoolFactory.getThreadId();
|
||||
}
|
||||
|
||||
public Object attach( ThreadId threadId )
|
||||
{
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".attach - id:" + threadId);
|
||||
JobQueue jobQueue = _javaThreadPoolFactory.getJobQueue(threadId);
|
||||
if(jobQueue == null)
|
||||
jobQueue = new JobQueue(_javaThreadPoolFactory, threadId, false);
|
||||
|
||||
// acquiring the jobQueue registers it at the ThreadPoolFactory
|
||||
jobQueue.acquire();
|
||||
return jobQueue;
|
||||
}
|
||||
|
||||
public void attach() {
|
||||
attach( getThreadId() );
|
||||
}
|
||||
|
||||
public void detach( Object handle, ThreadId id )
|
||||
{
|
||||
((JobQueue)handle).release();
|
||||
}
|
||||
|
||||
public void detach() {
|
||||
ThreadId threadId = getThreadId();
|
||||
detach(_javaThreadPoolFactory.getJobQueue(threadId), threadId );
|
||||
}
|
||||
|
||||
|
||||
public Object enter( ) throws Throwable {
|
||||
ThreadId threadId = getThreadId();
|
||||
return enter( _javaThreadPoolFactory.getJobQueue( threadId ), threadId );
|
||||
}
|
||||
|
||||
public Object enter( Object handle, ThreadId threadId ) throws Throwable {
|
||||
return ((JobQueue)handle).enter(this);
|
||||
}
|
||||
|
||||
public void putJob(Job job) {
|
||||
if (!job.isRequest() || job.isSynchronous()) {
|
||||
JobQueue jobQueue = _javaThreadPoolFactory.getJobQueue(job.getThreadId());
|
||||
|
||||
// this has not be synchronized, cause
|
||||
// sync jobs can only come over one bridge
|
||||
// (cause the thread blocks on other side)
|
||||
if(jobQueue == null)
|
||||
jobQueue = new JobQueue(_javaThreadPoolFactory, job.getThreadId(), true);
|
||||
|
||||
// put job acquires the queue and registers it at the ThreadPoolFactory
|
||||
jobQueue.putJob(job, this);
|
||||
}
|
||||
else {
|
||||
// this has to be synchronized, cause
|
||||
// async jobs of the same thread can come
|
||||
// over different bridges
|
||||
synchronized(_javaThreadPoolFactory) {
|
||||
JobQueue async_jobQueue = _javaThreadPoolFactory.getAsyncJobQueue(job.getThreadId());
|
||||
|
||||
// ensure there is jobQueue
|
||||
if(async_jobQueue == null) // so, there is really no async queue
|
||||
async_jobQueue = new JobQueue(_javaThreadPoolFactory, job.getThreadId());
|
||||
|
||||
// put job acquires the queue and registers it at the ThreadPoolFactory
|
||||
async_jobQueue.putJob(job, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose(Throwable throwable) {
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".dispose:" + throwable);
|
||||
|
||||
_javaThreadPoolFactory.dispose(this, throwable);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,87 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
final class JavaThreadPoolFactory {
|
||||
|
||||
public IThreadPool createThreadPool() {
|
||||
return new JavaThreadPool(this);
|
||||
}
|
||||
|
||||
public void addJobQueue(JobQueue jobQueue) {
|
||||
synchronized (jobQueues) {
|
||||
jobQueues.put(jobQueue.getThreadId(), jobQueue);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeJobQueue(JobQueue jobQueue) {
|
||||
synchronized (jobQueues) {
|
||||
jobQueues.remove(jobQueue.getThreadId());
|
||||
}
|
||||
}
|
||||
|
||||
public JobQueue getJobQueue(ThreadId threadId) {
|
||||
synchronized (jobQueues) {
|
||||
return jobQueues.get(threadId);
|
||||
}
|
||||
}
|
||||
|
||||
public JobQueue getAsyncJobQueue(ThreadId threadId) {
|
||||
JobQueue q = getJobQueue(threadId);
|
||||
return q == null ? null : q._async_jobQueue;
|
||||
}
|
||||
|
||||
public void dispose(Object disposeId, Throwable throwable) {
|
||||
JobQueue[] qs;
|
||||
synchronized (jobQueues) {
|
||||
Collection<JobQueue> c = jobQueues.values();
|
||||
qs = c.toArray(new JobQueue[c.size()]);
|
||||
}
|
||||
for (int i = 0; i < qs.length; ++i) {
|
||||
qs[i].dispose(disposeId, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static ThreadId getThreadId() {
|
||||
Thread t = Thread.currentThread();
|
||||
if (t instanceof JobQueue.JobDispatcher) {
|
||||
return ((JobQueue.JobDispatcher) t).getThreadId();
|
||||
} else {
|
||||
ThreadId id;
|
||||
synchronized (threadIdMap) {
|
||||
id = threadIdMap.get(t);
|
||||
if (id == null) {
|
||||
id = ThreadId.createFresh();
|
||||
threadIdMap.put(t, id);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
private static final WeakHashMap<Thread, ThreadId> threadIdMap = new WeakHashMap<Thread, ThreadId>();
|
||||
private final HashMap<ThreadId, JobQueue> jobQueues = new HashMap<ThreadId, JobQueue>();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,163 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import com.sun.star.lib.uno.typedesc.MethodDescription;
|
||||
import com.sun.star.uno.Any;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XCurrentContext;
|
||||
|
||||
/**
|
||||
* The Job is an abstraction for tasks which have to be done
|
||||
* remotely because of a method invocation.
|
||||
*
|
||||
* @see com.sun.star.lib.uno.environments.remote.ThreadId
|
||||
* @see com.sun.star.lib.uno.environments.remote.IReceiver
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class Job {
|
||||
protected IReceiver _iReceiver;
|
||||
protected Message _iMessage;
|
||||
Object _disposeId;
|
||||
|
||||
protected Object _object;
|
||||
|
||||
public Job(Object object, IReceiver iReceiver, Message iMessage) {
|
||||
_object = object;
|
||||
_iReceiver = iReceiver;
|
||||
_iMessage = iMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a <code>queryInterface</code> call.
|
||||
*
|
||||
* @return the result of the call (should be an <code>Any</code>).
|
||||
*/
|
||||
protected Object dispatch_queryInterface(Type type) {
|
||||
Class<?> zInterface = type.getTypeDescription().getZClass();
|
||||
|
||||
Object result = null;
|
||||
|
||||
Object face = UnoRuntime.queryInterface(zInterface, _object);
|
||||
// the hell knows why, but empty interfaces a given back as void anys
|
||||
if(face != null)
|
||||
result = new Any(type, face);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return the result of the message.
|
||||
*/
|
||||
public Object execute() throws Throwable {
|
||||
if (_iMessage.isRequest()) {
|
||||
Object result = null;
|
||||
Throwable exception = null;
|
||||
MethodDescription md = _iMessage.getMethod();
|
||||
Object[] args = _iMessage.getArguments();
|
||||
XCurrentContext oldCC = UnoRuntime.getCurrentContext();
|
||||
UnoRuntime.setCurrentContext(_iMessage.getCurrentContext());
|
||||
try {
|
||||
result = md.getIndex() == MethodDescription.ID_QUERY_INTERFACE
|
||||
? dispatch_queryInterface((Type) args[0])
|
||||
: md.getMethod().invoke(_object, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
exception = e.getCause();
|
||||
if (exception == null) {
|
||||
exception = e;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
} finally {
|
||||
UnoRuntime.setCurrentContext(oldCC);
|
||||
}
|
||||
if (_iMessage.isSynchronous()) {
|
||||
if (exception == null) {
|
||||
_iReceiver.sendReply(
|
||||
false, _iMessage.getThreadId(), result);
|
||||
} else {
|
||||
// Here we have to be aware of non-UNO exceptions, because
|
||||
// they may kill a remote side which does not know anything
|
||||
// about their types:
|
||||
if (!(exception instanceof com.sun.star.uno.Exception)
|
||||
&& !(exception instanceof
|
||||
com.sun.star.uno.RuntimeException))
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
exception.printStackTrace(new PrintWriter(writer));
|
||||
exception = new com.sun.star.uno.RuntimeException(
|
||||
"Java exception: <" + writer + ">", null);
|
||||
}
|
||||
_iReceiver.sendReply(
|
||||
true, _iMessage.getThreadId(), exception);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else if (_iMessage.isAbnormalTermination()) {
|
||||
throw remoteUnoRequestRaisedException(_iMessage.getResult());
|
||||
} else {
|
||||
return _iMessage.getResult();
|
||||
}
|
||||
}
|
||||
|
||||
public ThreadId getThreadId() {
|
||||
return _iMessage.getThreadId();
|
||||
}
|
||||
|
||||
public boolean isRequest() {
|
||||
return _iMessage.isRequest();
|
||||
}
|
||||
|
||||
public boolean isSynchronous() {
|
||||
return _iMessage.isSynchronous();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
// _oId = null;
|
||||
// _iReceiver = null;
|
||||
// _threadId = null;
|
||||
// _object = null;
|
||||
// _operation = null;
|
||||
// _param = null;
|
||||
// _exception = null;
|
||||
// _zInterface = null;
|
||||
// _disposeId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of this method is chosen to generate a somewhat self-explanatory
|
||||
* stack trace.
|
||||
*/
|
||||
private Exception remoteUnoRequestRaisedException(Object exception) {
|
||||
Exception e = (Exception) exception;
|
||||
e.fillInStackTrace();
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,373 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.star.lang.DisposedException;
|
||||
|
||||
/**
|
||||
* The <code>JobQueue</code> implements a queue for jobs.
|
||||
*
|
||||
* <p>For every jobs thread id exists a job queue which is registered
|
||||
* at the <code>ThreadPool</code>.</p>
|
||||
*
|
||||
* <p>A JobQueue is split into a sync job queue and an async job queue.
|
||||
* The sync job queue is the registered queue, it delegates async jobs
|
||||
* (put by <code>putjob</code>) into the async queue, which is only
|
||||
* known by the sync queue.</p>
|
||||
*
|
||||
* @see com.sun.star.lib.uno.environments.remote.IThreadPool
|
||||
* @see com.sun.star.lib.uno.environments.remote.Job
|
||||
* @see com.sun.star.lib.uno.environments.remote.ThreadId
|
||||
* @since UDK1.0
|
||||
*/
|
||||
public class JobQueue {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
final ArrayList<Job> jobList = new ArrayList<Job>();
|
||||
|
||||
private ThreadId _threadId; // the thread id of the queue
|
||||
protected int _ref_count = 0; // the stack deepness
|
||||
private boolean _createThread; // create a worker thread, if needed
|
||||
private boolean _createThread_now; // create a worker thread, if needed
|
||||
private Thread _worker_thread; // the thread that does the jobs
|
||||
|
||||
private Object _disposeId; // the active dispose id
|
||||
private Object _doDispose = null;
|
||||
private Throwable _throwable;
|
||||
|
||||
JobQueue _async_jobQueue; // chaining job queues for asyncs
|
||||
protected JobQueue _sync_jobQueue; // chaining job queues for syncs
|
||||
|
||||
private boolean _active = false;
|
||||
|
||||
private JavaThreadPoolFactory _javaThreadPoolFactory;
|
||||
|
||||
/**
|
||||
* A thread for dispatching jobs.
|
||||
*/
|
||||
class JobDispatcher extends Thread {
|
||||
Object _disposeId;
|
||||
|
||||
JobDispatcher(Object disposeId) {
|
||||
super("JobDispatcher");
|
||||
|
||||
if(DEBUG) System.err.println("JobQueue$JobDispatcher.<init>:" + _threadId);
|
||||
|
||||
_disposeId = disposeId;
|
||||
}
|
||||
|
||||
ThreadId getThreadId() {
|
||||
return _threadId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if(DEBUG) System.err.println("ThreadPool$JobDispatcher.run: " + Thread.currentThread());
|
||||
|
||||
try {
|
||||
enter(2000, _disposeId);
|
||||
} catch(Throwable throwable) {
|
||||
synchronized (JobQueue.this) {
|
||||
if(!jobList.isEmpty() || _active) { // there was a job in progress, so give a stack
|
||||
System.err.println(getClass().getName() + " - exception occurred:" + throwable);
|
||||
throwable.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
release();
|
||||
}
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".run - exit:" + _threadId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an async job queue with the given thread id which belongs to
|
||||
* the given sync job queue.
|
||||
*
|
||||
* @param threadId the thread id.
|
||||
* @see com.sun.star.lib.uno.environments.remote.ThreadId
|
||||
*/
|
||||
JobQueue(JavaThreadPoolFactory javaThreadPoolFactory, ThreadId threadId) {
|
||||
_javaThreadPoolFactory = javaThreadPoolFactory;
|
||||
_threadId = ThreadId.createFresh();
|
||||
|
||||
_sync_jobQueue = javaThreadPoolFactory.getJobQueue(threadId);
|
||||
if(_sync_jobQueue == null) {
|
||||
_sync_jobQueue = new JobQueue(javaThreadPoolFactory, threadId, true);
|
||||
_sync_jobQueue.acquire();
|
||||
}
|
||||
|
||||
_sync_jobQueue._async_jobQueue = this;
|
||||
|
||||
_createThread = true;
|
||||
_createThread_now = true;
|
||||
|
||||
acquire();
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + " - init:" + _threadId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a sync job queue with the given thread id and the given thread.
|
||||
*
|
||||
* @param threadId the thread id.
|
||||
* @param createThread if true, the queue creates a worker thread if needed.
|
||||
* @see com.sun.star.lib.uno.environments.remote.ThreadId
|
||||
*/
|
||||
JobQueue(JavaThreadPoolFactory javaThreadPoolFactory, ThreadId threadId, boolean createThread){
|
||||
_javaThreadPoolFactory = javaThreadPoolFactory;
|
||||
_threadId = threadId;
|
||||
_createThread = createThread;
|
||||
_createThread_now = createThread;
|
||||
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + " - init:" + _threadId + " " + createThread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the thread id of this queue.
|
||||
*
|
||||
* @return the thread id.
|
||||
* @see com.sun.star.lib.uno.environments.remote.ThreadId
|
||||
*/
|
||||
ThreadId getThreadId() {
|
||||
return _threadId;
|
||||
}
|
||||
|
||||
synchronized void acquire() {
|
||||
// add only synchronous queues .
|
||||
if(_ref_count <= 0 && _sync_jobQueue == null )
|
||||
_javaThreadPoolFactory.addJobQueue(this);
|
||||
|
||||
++ _ref_count;
|
||||
}
|
||||
|
||||
synchronized void release() {
|
||||
-- _ref_count;
|
||||
|
||||
if(_ref_count <= 0) {
|
||||
// only synchronous queues needs to be removed .
|
||||
if( _sync_jobQueue == null )
|
||||
_javaThreadPoolFactory.removeJobQueue(this);
|
||||
|
||||
|
||||
if(_sync_jobQueue != null) {
|
||||
_sync_jobQueue._async_jobQueue = null;
|
||||
_sync_jobQueue.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job from the queue.
|
||||
*
|
||||
* @param waitTime the maximum amount of time to wait for a job.
|
||||
* @return a job or null if timed out.
|
||||
*/
|
||||
private Job removeJob(int waitTime) {
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".removeJob:" + jobList + " " + _threadId);
|
||||
|
||||
Job job = null;
|
||||
synchronized (this) {
|
||||
// wait max. waitTime time for a job to enter the queue
|
||||
boolean waited = false;
|
||||
while(jobList.isEmpty() && (waitTime == 0 || !waited)) {
|
||||
if(_doDispose == _disposeId) {
|
||||
_doDispose = null;
|
||||
throw (DisposedException)
|
||||
new DisposedException().initCause(_throwable);
|
||||
}
|
||||
|
||||
// notify sync queues
|
||||
notifyAll();
|
||||
|
||||
try {
|
||||
// wait for new job
|
||||
wait(waitTime);
|
||||
} catch(InterruptedException interruptedException) {
|
||||
throw new com.sun.star.uno.RuntimeException(getClass().getName() + ".removeJob - unexpected:" + interruptedException);
|
||||
}
|
||||
|
||||
// signal that we have already waited once
|
||||
waited = true;
|
||||
}
|
||||
|
||||
|
||||
if(!jobList.isEmpty()) {
|
||||
job = jobList.remove(0);
|
||||
_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
// always wait for asynchron jobqueue to be finished !
|
||||
if(job != null && _async_jobQueue != null) {
|
||||
synchronized(_async_jobQueue) {
|
||||
// wait for async queue to be empty and last job to be done
|
||||
while(_async_jobQueue._active || !_async_jobQueue.jobList.isEmpty()) {
|
||||
if(DEBUG) System.err.println("waiting for async:" + _async_jobQueue.jobList + " " + _async_jobQueue._worker_thread);
|
||||
|
||||
if(_doDispose == _disposeId) {
|
||||
_doDispose = null;
|
||||
throw (DisposedException)
|
||||
new DisposedException().initCause(_throwable);
|
||||
}
|
||||
|
||||
try {
|
||||
_async_jobQueue.wait();
|
||||
} catch(InterruptedException interruptedException) {
|
||||
throw new com.sun.star.uno.RuntimeException(getClass().getName() + ".removeJob - unexpected:" + interruptedException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a job into the queue.
|
||||
*
|
||||
* @param job the job.
|
||||
* @param disposeId a dispose id.
|
||||
*/
|
||||
synchronized void putJob(Job job, Object disposeId) {
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".putJob todoes: " + " job:" + job);
|
||||
|
||||
jobList.add(job);
|
||||
|
||||
if(_worker_thread == null && _createThread && _createThread_now) { // if there is no thread, which dispatches and if shall create one, create one
|
||||
|
||||
acquire();
|
||||
|
||||
_createThread_now = false;
|
||||
new JobDispatcher(disposeId).start();
|
||||
}
|
||||
|
||||
// always notify possible waiters
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enters the job queue.
|
||||
*
|
||||
* @param disposeId a dispose id.
|
||||
* @return the result of the final job (reply).
|
||||
*/
|
||||
Object enter(Object disposeId) throws Throwable {
|
||||
return enter(0, disposeId); // wait infinitely
|
||||
}
|
||||
|
||||
/**
|
||||
* Enters the job queue.
|
||||
*
|
||||
* @param waitTime the maximum amount of time to wait for a job (0 means wait infinitely).
|
||||
* @param disposeId a dispose id.
|
||||
* @return the result of the final job (reply).
|
||||
*/
|
||||
Object enter(int waitTime, Object disposeId) throws Throwable {
|
||||
if(DEBUG) System.err.println("#####" + getClass().getName() + ".enter: " + _threadId);
|
||||
|
||||
boolean quit = false;
|
||||
|
||||
Object hold_disposeId = _disposeId;
|
||||
_disposeId = disposeId;
|
||||
|
||||
Object result = null;
|
||||
|
||||
Thread hold_worker_thread = _worker_thread;
|
||||
_worker_thread = Thread.currentThread();
|
||||
|
||||
while(!quit) {
|
||||
Job job = null;
|
||||
|
||||
try {
|
||||
job = removeJob(waitTime);
|
||||
|
||||
if(job != null) {
|
||||
try {
|
||||
result = job.execute();
|
||||
}
|
||||
finally {
|
||||
_active = false;
|
||||
}
|
||||
|
||||
if (!job.isRequest()) {
|
||||
job.dispose();
|
||||
|
||||
quit = true;
|
||||
}
|
||||
|
||||
job = null;
|
||||
}
|
||||
else
|
||||
quit = true;
|
||||
|
||||
|
||||
}
|
||||
finally { // ensure that this queue becomes disposed, if necessary
|
||||
if(DEBUG) System.err.println("##### " + getClass().getName() + ".enter leaving: " + _threadId + " " + _worker_thread + " " + hold_worker_thread + " " + result);
|
||||
|
||||
synchronized(this) {
|
||||
if(job != null || (quit && jobList.isEmpty())) {
|
||||
_worker_thread = hold_worker_thread;
|
||||
|
||||
_createThread_now = true;
|
||||
|
||||
_disposeId = hold_disposeId;
|
||||
|
||||
if(_sync_jobQueue != null)
|
||||
notifyAll(); // notify waiters (e.g. this is an asyncQueue and there is a sync waiting)
|
||||
}
|
||||
else
|
||||
quit = false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given disposeId is registered, interrupts the worker thread.
|
||||
*
|
||||
* @param disposeId the dispose id.
|
||||
*/
|
||||
synchronized void dispose(Object disposeId, Throwable throwable) {
|
||||
if(_sync_jobQueue == null) { // dispose only sync queues
|
||||
_doDispose = disposeId;
|
||||
_throwable = throwable;
|
||||
|
||||
// get thread out of wait and let it throw the throwable
|
||||
if(DEBUG) System.err.println(getClass().getName() + ".dispose - notifying thread");
|
||||
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,189 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
import com.sun.star.lib.uno.typedesc.MethodDescription;
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import com.sun.star.uno.XCurrentContext;
|
||||
|
||||
/**
|
||||
* A remote request or reply message.
|
||||
*/
|
||||
public class Message {
|
||||
public Message(
|
||||
ThreadId threadId, boolean request, String objectId,
|
||||
TypeDescription type, MethodDescription method, boolean synchronous,
|
||||
XCurrentContext currentContext, boolean abnormalTermination,
|
||||
Object result, Object[] arguments)
|
||||
{
|
||||
this.threadId = threadId;
|
||||
this.request = request;
|
||||
this.objectId = objectId;
|
||||
this.type = type;
|
||||
this.method = method;
|
||||
this.synchronous = synchronous;
|
||||
this.currentContext = currentContext;
|
||||
this.abnormalTermination = abnormalTermination;
|
||||
this.result = result;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread ID of the message.
|
||||
*
|
||||
* <p>Valid for all kinds of messages.</p>
|
||||
*
|
||||
* @return the (non-<code>null</code>) thread ID.
|
||||
*/
|
||||
public final ThreadId getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the message is a request or a reply.
|
||||
*
|
||||
* <p>Valid for all kinds of messages.</p>
|
||||
*
|
||||
* @return <code>true</code> for a request, <code>false</code> for a reply.
|
||||
*/
|
||||
public final boolean isRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object ID of a request message.
|
||||
*
|
||||
* <p>Valid only for request messages.</p>
|
||||
*
|
||||
* @return the (non-<code>null</code>) object ID for a request,
|
||||
* <code>null</code> for a reply.
|
||||
*/
|
||||
public final String getObjectId() {
|
||||
return objectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of a request message.
|
||||
*
|
||||
* <p>Valid only for request messages.</p>
|
||||
*
|
||||
* @return the (non-<code>null</code>) type for a request, <code>null</code>
|
||||
* for a reply.
|
||||
*/
|
||||
public final TypeDescription getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the method description of a request message.
|
||||
*
|
||||
* <p>Valid only for request messages. The returned
|
||||
* <code>MethodDescription</code> is consistent with the type of the
|
||||
* message.</p>
|
||||
*
|
||||
* @return the (non-<code>null</code>) method description for a request,
|
||||
* <code>null</code> for a reply.
|
||||
*/
|
||||
public final MethodDescription getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the request message is synchronous.
|
||||
*
|
||||
* <p>Valid only for request messages.</p>
|
||||
*
|
||||
* @return <code>true</code> for a synchronous request, <code>false</code>
|
||||
* for an asynchronous request or a reply.
|
||||
*/
|
||||
public final boolean isSynchronous() {
|
||||
return synchronous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current context of a request message.
|
||||
*
|
||||
* <p>Valid only for request messages.</p>
|
||||
*
|
||||
* @return the current context (which may be <code>null</code>) for a
|
||||
* request, <code>null</code> for a reply.
|
||||
*/
|
||||
public XCurrentContext getCurrentContext() {
|
||||
return currentContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the reply message represents abnormal termination.
|
||||
*
|
||||
* <p>Valid only for reply messages.</p>
|
||||
*
|
||||
* @return <code>true</code> for a reply that represents abnormal
|
||||
* termination, <code>false</code> for a reply that represents normal
|
||||
* termination or a request.
|
||||
*/
|
||||
public final boolean isAbnormalTermination() {
|
||||
return abnormalTermination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of a reply message.
|
||||
*
|
||||
* <p>Valid only for reply messages.</p>
|
||||
*
|
||||
* @return any (possibly <code>null</code>) return value for a reply that
|
||||
* represents normal termination, the (non-<code>null</code>) exception for
|
||||
* a reply that represents abnormal termination, <code>null</code> for a
|
||||
* request.
|
||||
*/
|
||||
public final Object getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arguments of a message.
|
||||
*
|
||||
* <p>Valid only for request messages and reply messages that represent
|
||||
* normal termination. Any returned array must not be modified.</p>
|
||||
*
|
||||
* @return the in and in– {
|
||||
* }out arguments for a request (possibly
|
||||
* <code>null</code> for a parameterless function), the out and in– {
|
||||
* }out
|
||||
* arguments for a reply that represents normal termination (possibly
|
||||
* <code>null</code> for a parameterless function), <code>null</code> for a
|
||||
* reply that represents abnormal termination.
|
||||
*/
|
||||
public final Object[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
private final ThreadId threadId;
|
||||
private final boolean request;
|
||||
private final String objectId;
|
||||
private final TypeDescription type;
|
||||
private final MethodDescription method;
|
||||
private final boolean synchronous;
|
||||
private final XCurrentContext currentContext;
|
||||
private final boolean abnormalTermination;
|
||||
private final Object result;
|
||||
private final Object[] arguments;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
final class NativeThreadPool implements IThreadPool {
|
||||
public NativeThreadPool() {
|
||||
pool = create();
|
||||
}
|
||||
|
||||
public ThreadId getThreadId() {
|
||||
return new ThreadId(threadId());
|
||||
}
|
||||
|
||||
public void attach() {
|
||||
attach(pool);
|
||||
}
|
||||
|
||||
public Object attach(ThreadId id) {
|
||||
attach();
|
||||
return null;
|
||||
}
|
||||
|
||||
public void detach() {
|
||||
detach(pool);
|
||||
}
|
||||
|
||||
public void detach(Object handle, ThreadId id) {
|
||||
detach();
|
||||
}
|
||||
|
||||
public Object enter() throws Throwable {
|
||||
Job job = enter(pool);
|
||||
if (job == null) {
|
||||
throw dispose;
|
||||
}
|
||||
return job.execute();
|
||||
}
|
||||
|
||||
public Object enter(Object handle, ThreadId id) throws Throwable {
|
||||
return enter();
|
||||
}
|
||||
|
||||
public void putJob(Job job) {
|
||||
putJob(
|
||||
pool, job.getThreadId().getBytes(), job, job.isRequest(),
|
||||
job.isRequest() && !job.isSynchronous());
|
||||
}
|
||||
|
||||
public void dispose(Throwable throwable) {
|
||||
dispose = throwable;
|
||||
dispose(pool);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroy(pool);
|
||||
}
|
||||
|
||||
// The native implementation is in
|
||||
// bridges/source/jni_uno/nativethreadpool.cxx:
|
||||
static {
|
||||
System.loadLibrary("java_uno");
|
||||
}
|
||||
private static native byte[] threadId();
|
||||
private static native long create();
|
||||
private static native void attach(long pool);
|
||||
private static native Job enter(long pool);
|
||||
private static native void detach(long pool);
|
||||
private static native void putJob(
|
||||
long pool, byte[] threadId, Job job, boolean request, boolean oneWay);
|
||||
private static native void dispose(long pool);
|
||||
private static native void destroy(long pool);
|
||||
|
||||
private final long pool;
|
||||
private volatile Throwable dispose;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,109 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
public final class ThreadId {
|
||||
public static ThreadId createFresh() {
|
||||
long c = count.getAndIncrement();
|
||||
try {
|
||||
return new ThreadId((PREFIX + c).getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("this cannot happen: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public ThreadId(byte[] id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is equal to this one.
|
||||
*
|
||||
* @param obj the reference object with which to compare.
|
||||
* @return <code>true</code> if this object is the same as the obj argument;
|
||||
* <code>false</code> otherwise.
|
||||
*
|
||||
* @see java.lang.Object#equals
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof ThreadId
|
||||
&& Arrays.equals(id, ((ThreadId) obj).id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the object.
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @see java.lang.Object#hashCode
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
// Same algorithm as java.util.List.hashCode (also see Java 1.5
|
||||
// java.util.Arrays.hashCode(byte[])):
|
||||
h = 1;
|
||||
for (int i = 0; i < id.length; ++i) {
|
||||
h = 31 * h + id[i];
|
||||
}
|
||||
hash = h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object.
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
* @see java.lang.Object#toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer b = new StringBuffer("[ThreadId:");
|
||||
for (int i = 0; i < id.length; ++i) {
|
||||
String n = Integer.toHexString(id[i] & 0xFF);
|
||||
if (n.length() == 1) {
|
||||
b.append('0');
|
||||
}
|
||||
b.append(n);
|
||||
}
|
||||
b.append(']');
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private static final String PREFIX = "java:" + UnoRuntime.getUniqueKey() + ":";
|
||||
private static final AtomicLong count = new AtomicLong(0);
|
||||
|
||||
private final byte[] id;
|
||||
private int hash = 0;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,74 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
/**
|
||||
* Manages the UNO thread pool factory.
|
||||
*
|
||||
* <P>The thread pool factory is a process-wide resource. It is important that
|
||||
* all UNO environments within a process share the same thread pool mechanisms:
|
||||
* if a synchronous UNO call is bridged out from one local UNO environment over
|
||||
* one remote bridge, and recursively calls back into another local UNO
|
||||
* environment over another remote bridge, the code in the second environment
|
||||
* should be executed in the thread that did the original call from the first
|
||||
* environment.</P>
|
||||
*
|
||||
* <P>There are both a Java and a native thread pool factory. A pure Java
|
||||
* process will always use the Java thread pool factory. A mixed process uses
|
||||
* the system property <CODE>org.openoffice.native</CODE> (to be set by the
|
||||
* native code that starts the JVM) to determine which implementation
|
||||
* to use.</P>
|
||||
*/
|
||||
public final class ThreadPoolManager {
|
||||
/**
|
||||
* Creates a thread pool instance.
|
||||
*
|
||||
* @return a new thread pool instance; will never be <CODE>null</CODE>.
|
||||
*/
|
||||
public static synchronized IThreadPool create() {
|
||||
if (useNative) {
|
||||
return new NativeThreadPool();
|
||||
} else {
|
||||
if (javaFactory == null) {
|
||||
javaFactory = new JavaThreadPoolFactory();
|
||||
}
|
||||
return javaFactory.createThreadPool();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Leads to using the native thread pool factory, unless a Java thread pool
|
||||
* has already been created.
|
||||
*
|
||||
* @return <CODE>false</CODE> if a Java thread pool has already been created.
|
||||
*/
|
||||
public static synchronized boolean useNative() {
|
||||
useNative = javaFactory == null;
|
||||
return useNative;
|
||||
}
|
||||
|
||||
private static boolean useNative
|
||||
= System.getProperty("org.openoffice.native") != null;
|
||||
private static JavaThreadPoolFactory javaFactory = null;
|
||||
|
||||
private ThreadPoolManager() {} // do not instantiate
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,66 @@
|
||||
/* -*- 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.lib.uno.environments.remote;
|
||||
|
||||
import com.sun.star.uno.IEnvironment;
|
||||
import com.sun.star.uno.Type;
|
||||
|
||||
public final class remote_environment implements IEnvironment {
|
||||
public remote_environment(Object context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Object getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "remote";
|
||||
}
|
||||
|
||||
public Object registerInterface(Object object, String[] oid, Type type) {
|
||||
throw new UnsupportedOperationException(
|
||||
"java_remote environment is not functional");
|
||||
}
|
||||
|
||||
public void revokeInterface(String oid, Type type) {
|
||||
throw new UnsupportedOperationException(
|
||||
"java_remote environment is not functional");
|
||||
}
|
||||
|
||||
public Object getRegisteredInterface(String oid, Type type) {
|
||||
throw new UnsupportedOperationException(
|
||||
"java_remote environment is not functional");
|
||||
}
|
||||
|
||||
public String getRegisteredObjectIdentifier(Object object) {
|
||||
throw new UnsupportedOperationException(
|
||||
"java_remote environment is not functional");
|
||||
}
|
||||
|
||||
public void list() {
|
||||
throw new UnsupportedOperationException(
|
||||
"java_remote environment is not functional");
|
||||
}
|
||||
|
||||
private final Object context;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,114 @@
|
||||
/* -*- 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.lib.uno.protocols.urp;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* An LRU cache for arbitrary objects.
|
||||
*
|
||||
* <p>This class is not synchronized, as any necessary synchronization will already
|
||||
* take place in the client.</p>
|
||||
*/
|
||||
final class Cache {
|
||||
/**
|
||||
* Create a cache.
|
||||
*
|
||||
* @param size the maximum cache size, must be between 0, inclusive, and
|
||||
* NOT_CACHED, exclusive.
|
||||
*/
|
||||
public Cache(int size) {
|
||||
maxSize = size;
|
||||
}
|
||||
|
||||
public int add(boolean[] found, Object content) {
|
||||
Entry e = map.get(content);
|
||||
found[0] = e != null;
|
||||
if (e == null) {
|
||||
if (map.size() < maxSize) {
|
||||
// There is still room for a new entry at the front:
|
||||
e = new Entry(content, map.size(), null, first);
|
||||
if (first == null) {
|
||||
last = e;
|
||||
} else {
|
||||
first.prev = e;
|
||||
}
|
||||
first = e;
|
||||
} else if (last != null) {
|
||||
// Take last entry out and recycle as new front:
|
||||
map.remove(last.content);
|
||||
e = last;
|
||||
e.content = content;
|
||||
if (first != last) {
|
||||
// Reached only if maxSize > 1:
|
||||
last = last.prev;
|
||||
last.next = null;
|
||||
e.prev = null;
|
||||
e.next = first;
|
||||
first.prev = e;
|
||||
first = e;
|
||||
}
|
||||
} else {
|
||||
// Reached iff maxSize == 0:
|
||||
return NOT_CACHED;
|
||||
}
|
||||
map.put(content, e);
|
||||
} else if (e != first) {
|
||||
// Move to front (reached only if maxSize > 1):
|
||||
e.prev.next = e.next;
|
||||
if (e.next == null) {
|
||||
last = e.prev;
|
||||
} else {
|
||||
e.next.prev = e.prev;
|
||||
}
|
||||
e.prev = null;
|
||||
e.next = first;
|
||||
first.prev = e;
|
||||
first = e;
|
||||
}
|
||||
return e.index;
|
||||
}
|
||||
|
||||
public static final int NOT_CACHED = 0xFFFF;
|
||||
|
||||
private static final class Entry {
|
||||
public Entry(Object content, int index, Entry prev, Entry next) {
|
||||
this.content = content;
|
||||
this.index = index;
|
||||
this.prev = prev;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public Object content;
|
||||
public int index;
|
||||
public Entry prev;
|
||||
public Entry next;
|
||||
}
|
||||
|
||||
// first/last form a list of 0 to maxSize entries, most recently used first;
|
||||
// map contains the same entries; each entry has a unique index in the range
|
||||
// 0 to maxSize - 1
|
||||
private final int maxSize;
|
||||
private final HashMap<Object, Entry> map = new HashMap<Object, Entry>(); // from Object to Entry
|
||||
private Entry first = null;
|
||||
private Entry last = null;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,355 @@
|
||||
/* -*- 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.lib.uno.protocols.urp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadId;
|
||||
import com.sun.star.lib.uno.typedesc.FieldDescription;
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import com.sun.star.uno.Any;
|
||||
import com.sun.star.uno.Enum;
|
||||
import com.sun.star.uno.IBridge;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.TypeClass;
|
||||
import com.sun.star.uno.XInterface;
|
||||
|
||||
final class Marshal {
|
||||
public Marshal(IBridge bridge, short cacheSize) {
|
||||
this.bridge = bridge;
|
||||
objectIdCache = new Cache(cacheSize);
|
||||
threadIdCache = new Cache(cacheSize);
|
||||
typeCache = new Cache(cacheSize);
|
||||
}
|
||||
|
||||
public void write8Bit(int value) {
|
||||
try {
|
||||
output.writeByte(value);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void write16Bit(int value) {
|
||||
try {
|
||||
output.writeShort(value);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeObjectId(String objectId) {
|
||||
try {
|
||||
if (objectId == null) {
|
||||
writeStringValue(null);
|
||||
write16Bit(0xFFFF);
|
||||
} else {
|
||||
boolean[] found = new boolean[1];
|
||||
int index = objectIdCache.add(found, objectId);
|
||||
writeStringValue(found[0] ? null : objectId);
|
||||
write16Bit(index);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeInterface(XInterface object, Type type) {
|
||||
writeObjectId((String) bridge.mapInterfaceTo(object, type));
|
||||
}
|
||||
|
||||
public void writeThreadId(ThreadId threadId) {
|
||||
try {
|
||||
byte[] data = threadId.getBytes();
|
||||
boolean[] found = new boolean[1];
|
||||
int index = threadIdCache.add(found, data);
|
||||
if (found[0]) {
|
||||
writeCompressedNumber(0);
|
||||
} else {
|
||||
writeCompressedNumber(data.length);
|
||||
writeBytes(data);
|
||||
}
|
||||
write16Bit(index);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeType(TypeDescription type) {
|
||||
try {
|
||||
TypeClass typeClass = type.getTypeClass();
|
||||
if (TypeDescription.isTypeClassSimple(typeClass)) {
|
||||
write8Bit(typeClass.getValue());
|
||||
} else {
|
||||
boolean[] found = new boolean[1];
|
||||
int index = typeCache.add(found, type.getTypeName());
|
||||
write8Bit(typeClass.getValue() | (found[0] ? 0 : 0x80));
|
||||
write16Bit(index);
|
||||
if (!found[0]) {
|
||||
writeStringValue(type.getTypeName());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeValue(TypeDescription type, Object value) {
|
||||
try {
|
||||
switch(type.getTypeClass().getValue()) {
|
||||
case TypeClass.VOID_value:
|
||||
break;
|
||||
|
||||
case TypeClass.BOOLEAN_value:
|
||||
writeBooleanValue((Boolean) value);
|
||||
break;
|
||||
|
||||
case TypeClass.BYTE_value:
|
||||
writeByteValue((Byte) value);
|
||||
break;
|
||||
|
||||
case TypeClass.SHORT_value:
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
writeShortValue((Short) value);
|
||||
break;
|
||||
|
||||
case TypeClass.LONG_value:
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
writeLongValue((Integer) value);
|
||||
break;
|
||||
|
||||
case TypeClass.HYPER_value:
|
||||
case TypeClass.UNSIGNED_HYPER_value:
|
||||
writeHyperValue((Long) value);
|
||||
break;
|
||||
|
||||
case TypeClass.FLOAT_value:
|
||||
writeFloatValue((Float) value);
|
||||
break;
|
||||
|
||||
case TypeClass.DOUBLE_value:
|
||||
writeDoubleValue((Double) value);
|
||||
break;
|
||||
|
||||
case TypeClass.CHAR_value:
|
||||
writeCharValue((Character) value);
|
||||
break;
|
||||
|
||||
case TypeClass.STRING_value:
|
||||
writeStringValue((String) value);
|
||||
break;
|
||||
|
||||
case TypeClass.TYPE_value:
|
||||
writeTypeValue((Type) value);
|
||||
break;
|
||||
|
||||
case TypeClass.ANY_value:
|
||||
writeAnyValue(value);
|
||||
break;
|
||||
|
||||
case TypeClass.SEQUENCE_value:
|
||||
writeSequenceValue(type, value);
|
||||
break;
|
||||
|
||||
case TypeClass.ENUM_value:
|
||||
writeEnumValue(type, (Enum) value);
|
||||
break;
|
||||
|
||||
case TypeClass.STRUCT_value:
|
||||
writeStructValue(type, value);
|
||||
break;
|
||||
|
||||
case TypeClass.EXCEPTION_value:
|
||||
writeExceptionValue(type, (Exception) value);
|
||||
break;
|
||||
|
||||
case TypeClass.INTERFACE_value:
|
||||
writeInterfaceValue(type, (XInterface) value);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad type descriptor " + type);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] reset() {
|
||||
byte[] data = buffer.toByteArray();
|
||||
buffer.reset();
|
||||
return data;
|
||||
}
|
||||
|
||||
private void writeBooleanValue(Boolean value) throws IOException {
|
||||
output.writeBoolean(value != null && value.booleanValue());
|
||||
}
|
||||
|
||||
private void writeByteValue(Byte value) {
|
||||
write8Bit(value == null ? 0 : value.byteValue());
|
||||
}
|
||||
|
||||
private void writeShortValue(Short value) {
|
||||
write16Bit(value == null ? 0 : value.shortValue());
|
||||
}
|
||||
|
||||
private void writeLongValue(Integer value) throws IOException {
|
||||
write32Bit(value == null ? 0 : value.intValue());
|
||||
}
|
||||
|
||||
private void writeHyperValue(Long value) throws IOException {
|
||||
output.writeLong(value == null ? 0 : value.longValue());
|
||||
}
|
||||
|
||||
private void writeFloatValue(Float value) throws IOException {
|
||||
output.writeFloat(value == null ? 0 : value.floatValue());
|
||||
}
|
||||
|
||||
private void writeDoubleValue(Double value) throws IOException {
|
||||
output.writeDouble(value == null ? 0 : value.doubleValue());
|
||||
}
|
||||
|
||||
private void writeCharValue(Character value) throws IOException {
|
||||
output.writeChar(value == null ? 0 : value.charValue());
|
||||
}
|
||||
|
||||
private void writeStringValue(String value) throws IOException {
|
||||
if (value == null) {
|
||||
writeCompressedNumber(0);
|
||||
} else {
|
||||
byte[] data = value.getBytes("UTF8");
|
||||
writeCompressedNumber(data.length);
|
||||
writeBytes(data);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTypeValue(Type value) throws ClassNotFoundException {
|
||||
writeType(
|
||||
TypeDescription.getTypeDescription(
|
||||
value == null ? Type.VOID : value));
|
||||
}
|
||||
|
||||
private void writeAnyValue(Object value) throws ClassNotFoundException {
|
||||
TypeDescription type;
|
||||
if (value == null || value instanceof XInterface) {
|
||||
type = TypeDescription.getTypeDescription(XInterface.class);
|
||||
} else if (value instanceof Any) {
|
||||
Any any = (Any) value;
|
||||
type = TypeDescription.getTypeDescription(any.getType());
|
||||
value = any.getObject();
|
||||
} else if (value.getClass() == Object.class) {
|
||||
// Avoid StackOverflowError:
|
||||
throw new IllegalArgumentException(
|
||||
"Object instance does not represent UNO value");
|
||||
} else {
|
||||
type = TypeDescription.getTypeDescription(value.getClass());
|
||||
}
|
||||
writeType(type);
|
||||
writeValue(type, value);
|
||||
}
|
||||
|
||||
private void writeSequenceValue(TypeDescription type, Object value) throws IOException {
|
||||
if (value == null) {
|
||||
writeCompressedNumber(0);
|
||||
} else {
|
||||
TypeDescription ctype = type.getComponentType();
|
||||
if (ctype.getTypeClass() == TypeClass.BYTE) {
|
||||
byte[] data = (byte[]) value;
|
||||
writeCompressedNumber(data.length);
|
||||
writeBytes(data);
|
||||
} else {
|
||||
int len = Array.getLength(value);
|
||||
writeCompressedNumber(len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
writeValue(ctype, Array.get(value, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEnumValue(TypeDescription type, Enum value) throws IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException {
|
||||
int n;
|
||||
if (value == null) {
|
||||
n = ((Enum)
|
||||
(type.getZClass().getMethod("getDefault", (Class[]) null).
|
||||
invoke(null, (Object[]) null))).
|
||||
getValue();
|
||||
} else {
|
||||
n = value.getValue();
|
||||
}
|
||||
write32Bit(n);
|
||||
}
|
||||
|
||||
private void writeStructValue(TypeDescription type, Object value) throws IllegalAccessException {
|
||||
FieldDescription[] fields = type.getFieldDescriptions();
|
||||
for (int i = 0; i < fields.length; ++i) {
|
||||
writeValue(
|
||||
fields[i].getTypeDescription(),
|
||||
value == null ? null : fields[i].getField().get(value));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeExceptionValue(TypeDescription type, Exception value) throws IllegalAccessException, IOException {
|
||||
writeStringValue(value == null ? null : value.getMessage());
|
||||
writeStructValue(type, value);
|
||||
}
|
||||
|
||||
private void writeInterfaceValue(TypeDescription type, XInterface value) {
|
||||
writeInterface(value, new Type(type));
|
||||
}
|
||||
|
||||
private void write32Bit(int value) throws IOException {
|
||||
output.writeInt(value);
|
||||
}
|
||||
|
||||
private void writeCompressedNumber(int number) throws IOException {
|
||||
if (number >= 0 && number < 0xFF) {
|
||||
write8Bit(number);
|
||||
} else {
|
||||
write8Bit(0xFF);
|
||||
write32Bit(number);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBytes(byte[] data) throws IOException {
|
||||
output.write(data);
|
||||
}
|
||||
|
||||
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
private final DataOutput output = new DataOutputStream(buffer);
|
||||
private final IBridge bridge;
|
||||
private final Cache objectIdCache;
|
||||
private final Cache threadIdCache;
|
||||
private final Cache typeCache;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* -*- 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.lib.uno.protocols.urp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadId;
|
||||
import com.sun.star.lib.uno.typedesc.MethodDescription;
|
||||
|
||||
final class PendingRequests {
|
||||
|
||||
public synchronized void push(ThreadId tid, Item item) {
|
||||
Stack<Item> s = map.get(tid);
|
||||
if (s == null) {
|
||||
s = new Stack<Item>();
|
||||
map.put(tid, s);
|
||||
}
|
||||
s.push(item);
|
||||
}
|
||||
|
||||
public synchronized Item pop(ThreadId tid) {
|
||||
Stack<Item> s = map.get(tid);
|
||||
Item i = s.pop();
|
||||
if (s.empty()) {
|
||||
map.remove(tid);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static final class Item {
|
||||
public Item(
|
||||
boolean internal, MethodDescription function, Object[] arguments)
|
||||
{
|
||||
this.internal = internal;
|
||||
this.function = function;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public final boolean internal;
|
||||
public final MethodDescription function;
|
||||
public final Object[] arguments;
|
||||
}
|
||||
|
||||
private final HashMap<ThreadId, Stack<Item>> map = new HashMap<ThreadId, Stack<Item>>(); // from ThreadId to Stack of Item
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,476 @@
|
||||
/* -*- 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.lib.uno.protocols.urp;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadId;
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import com.sun.star.uno.Any;
|
||||
import com.sun.star.uno.Enum;
|
||||
import com.sun.star.uno.IBridge;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.TypeClass;
|
||||
import com.sun.star.uno.XInterface;
|
||||
import com.sun.star.lib.uno.typedesc.FieldDescription;
|
||||
|
||||
final class Unmarshal {
|
||||
public Unmarshal(IBridge bridge, int cacheSize) {
|
||||
this.bridge = bridge;
|
||||
objectIdCache = new String[cacheSize];
|
||||
threadIdCache = new ThreadId[cacheSize];
|
||||
typeCache = new TypeDescription[cacheSize];
|
||||
reset(new byte[0]);
|
||||
}
|
||||
|
||||
public int read8Bit() {
|
||||
try {
|
||||
return input.readUnsignedByte();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int read16Bit() {
|
||||
try {
|
||||
return input.readUnsignedShort();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String readObjectId() {
|
||||
try {
|
||||
String id = readStringValue();
|
||||
int index = read16Bit();
|
||||
if (index == 0xFFFF) {
|
||||
if (id.length() == 0) {
|
||||
id = null;
|
||||
}
|
||||
} else {
|
||||
if (id.length() == 0) {
|
||||
id = objectIdCache[index];
|
||||
} else {
|
||||
objectIdCache[index] = id;
|
||||
}
|
||||
}
|
||||
return id;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object readInterface(Type type) {
|
||||
String id = readObjectId();
|
||||
return id == null ? null : bridge.mapInterfaceFrom(id, type);
|
||||
}
|
||||
|
||||
public ThreadId readThreadId() {
|
||||
try {
|
||||
int len = readCompressedNumber();
|
||||
byte[] data ;
|
||||
ThreadId id = null;
|
||||
if (len != 0) {
|
||||
data = new byte[len];
|
||||
readBytes(data);
|
||||
id = new ThreadId(data);
|
||||
}
|
||||
int index = read16Bit();
|
||||
if (index != 0xFFFF) {
|
||||
if (len == 0) {
|
||||
id = threadIdCache[index];
|
||||
} else {
|
||||
threadIdCache[index] = id;
|
||||
}
|
||||
}
|
||||
return id;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeDescription readType() {
|
||||
int b = read8Bit();
|
||||
TypeClass typeClass = TypeClass.fromInt(b & 0x7F);
|
||||
if (typeClass == null) {
|
||||
throw new RuntimeException(
|
||||
"Reading TYPE with bad type class " + (b & 0x7F));
|
||||
}
|
||||
if (TypeDescription.isTypeClassSimple(typeClass)) {
|
||||
if ((b & 0x80) != 0) {
|
||||
throw new RuntimeException(
|
||||
"Reading TYPE with bad type class/cache flag " + b);
|
||||
}
|
||||
return TypeDescription.getTypeDescription(typeClass);
|
||||
} else {
|
||||
int index = read16Bit();
|
||||
TypeDescription type;
|
||||
if ((b & 0x80) == 0) {
|
||||
if (index >= typeCache.length) {
|
||||
throw new RuntimeException(
|
||||
"Reading TYPE with bad cache index " + index);
|
||||
}
|
||||
type = typeCache[index];
|
||||
if (type == null) {
|
||||
throw new RuntimeException(
|
||||
"Reading TYPE with empty cache index " + index);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
type = TypeDescription.getTypeDescription(
|
||||
readStringValue());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (index != 0xFFFF) {
|
||||
if (index >= typeCache.length) {
|
||||
throw new RuntimeException(
|
||||
"Reading TYPE with bad cache index " + index);
|
||||
}
|
||||
typeCache[index] = type;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public Object readValue(TypeDescription type) {
|
||||
try {
|
||||
switch (type.getTypeClass().getValue()) {
|
||||
case TypeClass.VOID_value:
|
||||
return null;
|
||||
|
||||
case TypeClass.BOOLEAN_value:
|
||||
return readBooleanValue();
|
||||
|
||||
case TypeClass.BYTE_value:
|
||||
return readByteValue();
|
||||
|
||||
case TypeClass.SHORT_value:
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return readShortValue();
|
||||
|
||||
case TypeClass.LONG_value:
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
return readLongValue();
|
||||
|
||||
case TypeClass.HYPER_value:
|
||||
case TypeClass.UNSIGNED_HYPER_value:
|
||||
return readHyperValue();
|
||||
|
||||
case TypeClass.FLOAT_value:
|
||||
return readFloatValue();
|
||||
|
||||
case TypeClass.DOUBLE_value:
|
||||
return readDoubleValue();
|
||||
|
||||
case TypeClass.CHAR_value:
|
||||
return readCharValue();
|
||||
|
||||
case TypeClass.STRING_value:
|
||||
return readStringValue();
|
||||
|
||||
case TypeClass.TYPE_value:
|
||||
return readTypeValue();
|
||||
|
||||
case TypeClass.ANY_value:
|
||||
return readAnyValue();
|
||||
|
||||
case TypeClass.SEQUENCE_value:
|
||||
return readSequenceValue(type);
|
||||
|
||||
case TypeClass.ENUM_value:
|
||||
return readEnumValue(type);
|
||||
|
||||
case TypeClass.STRUCT_value:
|
||||
return readStructValue(type);
|
||||
|
||||
case TypeClass.EXCEPTION_value:
|
||||
return readExceptionValue(type);
|
||||
|
||||
case TypeClass.INTERFACE_value:
|
||||
return readInterfaceValue(type);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad type descriptor " + type);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMore() {
|
||||
try {
|
||||
return input.available() > 0;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(byte[] data) {
|
||||
input = new DataInputStream(new ByteArrayInputStream(data));
|
||||
}
|
||||
|
||||
private Boolean readBooleanValue() throws IOException {
|
||||
return input.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
|
||||
private Byte readByteValue() throws IOException {
|
||||
return Byte.valueOf(input.readByte());
|
||||
}
|
||||
|
||||
private Short readShortValue() throws IOException {
|
||||
return Short.valueOf(input.readShort());
|
||||
}
|
||||
|
||||
private Integer readLongValue() throws IOException {
|
||||
return Integer.valueOf(input.readInt());
|
||||
}
|
||||
|
||||
private Long readHyperValue() throws IOException {
|
||||
return Long.valueOf(input.readLong());
|
||||
}
|
||||
|
||||
private Float readFloatValue() throws IOException {
|
||||
return new Float(input.readFloat());
|
||||
}
|
||||
|
||||
private Double readDoubleValue() throws IOException {
|
||||
return new Double(input.readDouble());
|
||||
}
|
||||
|
||||
private Character readCharValue() throws IOException {
|
||||
return new Character(input.readChar());
|
||||
}
|
||||
|
||||
private String readStringValue() throws IOException {
|
||||
int len = readCompressedNumber();
|
||||
byte[] data = new byte[len];
|
||||
readBytes(data);
|
||||
try {
|
||||
return new String(data, "UTF8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Type readTypeValue() {
|
||||
return new Type(readType());
|
||||
}
|
||||
|
||||
private Object readAnyValue() throws IOException {
|
||||
TypeDescription type = readType();
|
||||
switch (type.getTypeClass().getValue()) {
|
||||
case TypeClass.VOID_value:
|
||||
return Any.VOID;
|
||||
|
||||
case TypeClass.BOOLEAN_value:
|
||||
return readBooleanValue();
|
||||
|
||||
case TypeClass.BYTE_value:
|
||||
return readByteValue();
|
||||
|
||||
case TypeClass.SHORT_value:
|
||||
return readShortValue();
|
||||
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return new Any(Type.UNSIGNED_SHORT, readShortValue());
|
||||
|
||||
case TypeClass.LONG_value:
|
||||
return readLongValue();
|
||||
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
return new Any(Type.UNSIGNED_LONG, readLongValue());
|
||||
|
||||
case TypeClass.HYPER_value:
|
||||
return readHyperValue();
|
||||
|
||||
case TypeClass.UNSIGNED_HYPER_value:
|
||||
return new Any(Type.UNSIGNED_HYPER, readHyperValue());
|
||||
|
||||
case TypeClass.FLOAT_value:
|
||||
return readFloatValue();
|
||||
|
||||
case TypeClass.DOUBLE_value:
|
||||
return readDoubleValue();
|
||||
|
||||
case TypeClass.CHAR_value:
|
||||
return readCharValue();
|
||||
|
||||
case TypeClass.STRING_value:
|
||||
return readStringValue();
|
||||
|
||||
case TypeClass.TYPE_value:
|
||||
return readTypeValue();
|
||||
|
||||
case TypeClass.SEQUENCE_value:
|
||||
{
|
||||
Object value = readSequenceValue(type);
|
||||
TypeDescription ctype = type.getComponentType();
|
||||
while (ctype.getTypeClass() == TypeClass.SEQUENCE) {
|
||||
ctype = ctype.getComponentType();
|
||||
}
|
||||
switch (ctype.getTypeClass().getValue()) {
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
case TypeClass.UNSIGNED_HYPER_value:
|
||||
return new Any(new Type(type), value);
|
||||
|
||||
case TypeClass.STRUCT_value:
|
||||
if (ctype.hasTypeArguments()) {
|
||||
return new Any(new Type(type), value);
|
||||
}
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
case TypeClass.ENUM_value:
|
||||
return readEnumValue(type);
|
||||
|
||||
case TypeClass.STRUCT_value:
|
||||
{
|
||||
Object value = readStructValue(type);
|
||||
return type.hasTypeArguments()
|
||||
? new Any(new Type(type), value) : value;
|
||||
}
|
||||
|
||||
case TypeClass.EXCEPTION_value:
|
||||
return readExceptionValue(type);
|
||||
|
||||
case TypeClass.INTERFACE_value:
|
||||
{
|
||||
Object value = readInterfaceValue(type);
|
||||
return type.getZClass() == XInterface.class
|
||||
? value : new Any(new Type(type), value);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Reading ANY with bad type " + type.getTypeClass());
|
||||
}
|
||||
}
|
||||
|
||||
private Object readSequenceValue(TypeDescription type) throws IOException {
|
||||
int len = readCompressedNumber();
|
||||
TypeDescription ctype = type.getComponentType();
|
||||
if (ctype.getTypeClass() == TypeClass.BYTE) {
|
||||
byte[] data = new byte[len];
|
||||
readBytes(data);
|
||||
return data;
|
||||
} else {
|
||||
Object value = Array.newInstance(
|
||||
ctype.getTypeClass() == TypeClass.ANY
|
||||
? Object.class : ctype.getZClass(), len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Array.set(value, i, readValue(ctype));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private Enum readEnumValue(TypeDescription type) throws IOException {
|
||||
try {
|
||||
return (Enum)
|
||||
type.getZClass().getMethod(
|
||||
"fromInt", new Class[] { int.class }).
|
||||
invoke(null, new Object[] { readLongValue() });
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Object readStructValue(TypeDescription type) {
|
||||
Object value;
|
||||
try {
|
||||
value = type.getZClass().newInstance();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
readFields(type, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
private Exception readExceptionValue(TypeDescription type) throws IOException {
|
||||
Exception value;
|
||||
try {
|
||||
value = (Exception)
|
||||
type.getZClass().getConstructor(new Class[] { String.class }).
|
||||
newInstance(new Object[] { readStringValue() });
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
readFields(type, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
private Object readInterfaceValue(TypeDescription type) {
|
||||
return readInterface(new Type(type));
|
||||
}
|
||||
|
||||
private int readCompressedNumber() throws IOException {
|
||||
int number = read8Bit();
|
||||
return number < 0xFF ? number : input.readInt();
|
||||
}
|
||||
|
||||
private void readBytes(byte[] data) throws IOException {
|
||||
input.readFully(data);
|
||||
}
|
||||
|
||||
private void readFields(TypeDescription type, Object value) {
|
||||
FieldDescription[] fields = type.getFieldDescriptions();
|
||||
for (int i = 0; i < fields.length; ++i) {
|
||||
try {
|
||||
fields[i].getField().set(
|
||||
value,
|
||||
readValue(
|
||||
fields[i].getTypeDescription()));
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final IBridge bridge;
|
||||
private final String[] objectIdCache;
|
||||
private final ThreadId[] threadIdCache;
|
||||
private final TypeDescription[] typeCache;
|
||||
private DataInputStream input;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,48 @@
|
||||
/* -*- 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.lib.uno.protocols.urp;
|
||||
|
||||
import com.sun.star.lib.uno.environments.remote.Message;
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadId;
|
||||
import com.sun.star.lib.uno.typedesc.MethodDescription;
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import com.sun.star.uno.XCurrentContext;
|
||||
|
||||
final class UrpMessage extends Message {
|
||||
public UrpMessage(
|
||||
ThreadId threadId, boolean request, String objectId,
|
||||
TypeDescription type, MethodDescription method, boolean synchronous,
|
||||
XCurrentContext currentContext, boolean abnormalTermination,
|
||||
Object result, Object[] arguments, boolean internal)
|
||||
{
|
||||
super(
|
||||
threadId, request, objectId, type, method, synchronous,
|
||||
currentContext, abnormalTermination, result, arguments);
|
||||
this.internal = internal;
|
||||
}
|
||||
|
||||
public boolean isInternal() {
|
||||
return internal;
|
||||
}
|
||||
|
||||
private final boolean internal;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,760 @@
|
||||
/* -*- 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.lib.uno.protocols.urp;
|
||||
|
||||
import com.sun.star.bridge.InvalidProtocolChangeException;
|
||||
import com.sun.star.bridge.ProtocolProperty;
|
||||
import com.sun.star.bridge.XProtocolProperties;
|
||||
import com.sun.star.lang.DisposedException;
|
||||
import com.sun.star.lib.uno.environments.remote.IProtocol;
|
||||
import com.sun.star.lib.uno.environments.remote.Message;
|
||||
import com.sun.star.lib.uno.environments.remote.ThreadId;
|
||||
import com.sun.star.lib.uno.typedesc.MethodDescription;
|
||||
import com.sun.star.lib.uno.typedesc.TypeDescription;
|
||||
import com.sun.star.uno.Any;
|
||||
import com.sun.star.uno.IBridge;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.TypeClass;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XCurrentContext;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* This class internally relies on the availability of Java UNO type information
|
||||
* for the interface type <code>com.sun.star.bridge.XProtocolProperties</code>,
|
||||
* even though URP itself does not rely on that type.
|
||||
*/
|
||||
public final class urp implements IProtocol {
|
||||
public urp(
|
||||
IBridge bridge, String attributes, InputStream input,
|
||||
OutputStream output)
|
||||
{
|
||||
this.input = new DataInputStream(input);
|
||||
this.output = new DataOutputStream(output);
|
||||
marshal = new Marshal(bridge, CACHE_SIZE);
|
||||
unmarshal = new Unmarshal(bridge, CACHE_SIZE);
|
||||
forceSynchronous = parseAttributes(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see IProtocol#init
|
||||
*/
|
||||
public void init() throws IOException {
|
||||
synchronized (monitor) {
|
||||
if (state == STATE_INITIAL0) {
|
||||
sendRequestChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see IProtocol#terminate
|
||||
*/
|
||||
public void terminate() {
|
||||
synchronized (monitor) {
|
||||
state = STATE_TERMINATED;
|
||||
initialized = true;
|
||||
monitor.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see IProtocol#readMessage
|
||||
*/
|
||||
public Message readMessage() throws IOException {
|
||||
for (;;) {
|
||||
if (!unmarshal.hasMore()) {
|
||||
unmarshal.reset(readBlock());
|
||||
if (!unmarshal.hasMore()) {
|
||||
throw new IOException("closeConnection message received");
|
||||
}
|
||||
}
|
||||
UrpMessage msg;
|
||||
int header = unmarshal.read8Bit();
|
||||
if ((header & HEADER_LONGHEADER) != 0) {
|
||||
if ((header & HEADER_REQUEST) != 0) {
|
||||
msg = readLongRequest(header);
|
||||
} else {
|
||||
msg = readReply(header);
|
||||
}
|
||||
} else {
|
||||
msg = readShortRequest(header);
|
||||
}
|
||||
if (msg.isInternal()) {
|
||||
handleInternalMessage(msg);
|
||||
} else {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see IProtocol#writeRequest
|
||||
*/
|
||||
public boolean writeRequest(
|
||||
String oid, TypeDescription type, String function, ThreadId tid,
|
||||
Object[] arguments)
|
||||
throws IOException
|
||||
{
|
||||
if (oid.equals(PROPERTIES_OID)) {
|
||||
throw new IllegalArgumentException("illegal OID " + oid);
|
||||
}
|
||||
synchronized (monitor) {
|
||||
while (!initialized) {
|
||||
try {
|
||||
monitor.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
if (state == STATE_TERMINATED) {
|
||||
throw new DisposedException();
|
||||
}
|
||||
return writeRequest(false, oid, type, function, tid, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see IProtocol#writeReply
|
||||
*/
|
||||
public void writeReply(boolean exception, ThreadId tid, Object result)
|
||||
throws IOException
|
||||
{
|
||||
synchronized (output) {
|
||||
writeQueuedReleases();
|
||||
int header = HEADER_LONGHEADER;
|
||||
PendingRequests.Item pending = pendingIn.pop(tid);
|
||||
TypeDescription resultType;
|
||||
TypeDescription[] argTypes;
|
||||
Object[] args;
|
||||
if (exception) {
|
||||
header |= HEADER_EXCEPTION;
|
||||
resultType = TypeDescription.getTypeDescription(TypeClass.ANY);
|
||||
argTypes = null;
|
||||
args = null;
|
||||
} else {
|
||||
resultType = pending.function.getReturnSignature();
|
||||
argTypes = pending.function.getOutSignature();
|
||||
args = pending.arguments;
|
||||
}
|
||||
if (!tid.equals(outL1Tid)) {
|
||||
header |= HEADER_NEWTID;
|
||||
outL1Tid = tid;
|
||||
} else {
|
||||
tid = null;
|
||||
}
|
||||
marshal.write8Bit(header);
|
||||
if (tid != null) {
|
||||
marshal.writeThreadId(tid);
|
||||
}
|
||||
marshal.writeValue(resultType, result);
|
||||
if (argTypes != null) {
|
||||
for (int i = 0; i < argTypes.length; ++i) {
|
||||
if (argTypes[i] != null) {
|
||||
marshal.writeValue(
|
||||
argTypes[i].getComponentType(),
|
||||
Array.get(args[i], 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
writeBlock(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRequestChange() throws IOException {
|
||||
if (propertiesTid == null) {
|
||||
propertiesTid = ThreadId.createFresh();
|
||||
}
|
||||
random = randomGenerator.nextInt();
|
||||
writeRequest(
|
||||
true, PROPERTIES_OID,
|
||||
TypeDescription.getTypeDescription(XProtocolProperties.class),
|
||||
PROPERTIES_FUN_REQUEST_CHANGE, propertiesTid,
|
||||
new Object[] { Integer.valueOf(random) });
|
||||
state = STATE_REQUESTED;
|
||||
}
|
||||
|
||||
private void handleInternalMessage(Message message) throws IOException {
|
||||
if (message.isRequest()) {
|
||||
String t = message.getType().getTypeName();
|
||||
if (!t.equals("com.sun.star.bridge.XProtocolProperties")) {
|
||||
throw new IOException(
|
||||
"read URP protocol properties request with unsupported"
|
||||
+ " type " + t);
|
||||
}
|
||||
int fid = message.getMethod().getIndex();
|
||||
switch (fid) {
|
||||
case PROPERTIES_FID_REQUEST_CHANGE:
|
||||
checkSynchronousPropertyRequest(message);
|
||||
synchronized (monitor) {
|
||||
switch (state) {
|
||||
case STATE_INITIAL0:
|
||||
case STATE_INITIAL:
|
||||
writeReply(
|
||||
false, message.getThreadId(), Integer.valueOf(1));
|
||||
state = STATE_WAIT;
|
||||
break;
|
||||
case STATE_REQUESTED:
|
||||
int n
|
||||
= ((Integer) message.getArguments()[0]).intValue();
|
||||
if (random < n) {
|
||||
writeReply(
|
||||
false, message.getThreadId(), Integer.valueOf(1));
|
||||
state = STATE_WAIT;
|
||||
} else if (random == n) {
|
||||
writeReply(
|
||||
false, message.getThreadId(), Integer.valueOf(-1));
|
||||
state = STATE_INITIAL;
|
||||
sendRequestChange();
|
||||
} else {
|
||||
writeReply(
|
||||
false, message.getThreadId(), Integer.valueOf(0));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
writeReply(
|
||||
true, message.getThreadId(),
|
||||
new com.sun.star.uno.RuntimeException(
|
||||
"read URP protocol properties requestChange"
|
||||
+ " request in illegal state"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROPERTIES_FID_COMMIT_CHANGE:
|
||||
checkSynchronousPropertyRequest(message);
|
||||
synchronized (monitor) {
|
||||
if (state == STATE_WAIT) {
|
||||
ProtocolProperty[] p = (ProtocolProperty[])
|
||||
message.getArguments()[0];
|
||||
boolean ok = true;
|
||||
boolean cc = false;
|
||||
int i = 0;
|
||||
for (; i < p.length; ++i) {
|
||||
if (p[i].Name.equals(PROPERTY_CURRENT_CONTEXT)) {
|
||||
cc = true;
|
||||
} else {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
writeReply(false, message.getThreadId(), null);
|
||||
} else {
|
||||
writeReply(
|
||||
true, message.getThreadId(),
|
||||
new InvalidProtocolChangeException(
|
||||
"", null, p[i], 1));
|
||||
}
|
||||
state = STATE_INITIAL;
|
||||
if (!initialized) {
|
||||
if (cc) {
|
||||
currentContext = true;
|
||||
initialized = true;
|
||||
monitor.notifyAll();
|
||||
} else {
|
||||
sendRequestChange();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeReply(
|
||||
true, message.getThreadId(),
|
||||
new com.sun.star.uno.RuntimeException(
|
||||
"read URP protocol properties commitChange"
|
||||
+ " request in illegal state"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException(
|
||||
"read URP protocol properties request with unsupported"
|
||||
+ " function ID " + fid);
|
||||
}
|
||||
} else {
|
||||
synchronized (monitor) {
|
||||
if (state == STATE_COMMITTED) {
|
||||
// commitChange reply:
|
||||
if (!message.isAbnormalTermination()) {
|
||||
currentContext = true;
|
||||
}
|
||||
state = STATE_INITIAL;
|
||||
initialized = true;
|
||||
monitor.notifyAll();
|
||||
} else {
|
||||
// requestChange reply:
|
||||
if (message.isAbnormalTermination()) {
|
||||
// remote side probably does not support negotiation:
|
||||
state = STATE_INITIAL;
|
||||
initialized = true;
|
||||
monitor.notifyAll();
|
||||
} else {
|
||||
int n = ((Integer) message.getResult()).intValue();
|
||||
switch (n) {
|
||||
case -1:
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
writeRequest(
|
||||
true, PROPERTIES_OID,
|
||||
TypeDescription.getTypeDescription(
|
||||
XProtocolProperties.class),
|
||||
PROPERTIES_FUN_COMMIT_CHANGE, propertiesTid,
|
||||
new Object[] {
|
||||
new ProtocolProperty[] {
|
||||
new ProtocolProperty(
|
||||
PROPERTY_CURRENT_CONTEXT,
|
||||
Any.VOID) } });
|
||||
state = STATE_COMMITTED;
|
||||
break;
|
||||
default:
|
||||
throw new IOException(
|
||||
"read URP protocol properties "
|
||||
+ PROPERTIES_FUN_REQUEST_CHANGE
|
||||
+ " reply with illegal return value " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSynchronousPropertyRequest(Message message)
|
||||
throws IOException
|
||||
{
|
||||
if (!message.isSynchronous()) {
|
||||
throw new IOException(
|
||||
"read URP protocol properties request for synchronous function"
|
||||
+ " marked as not SYNCHRONOUS");
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] readBlock() throws IOException {
|
||||
int size = input.readInt();
|
||||
input.readInt(); // ignore count
|
||||
byte[] bytes = new byte[size];
|
||||
input.readFully(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private UrpMessage readLongRequest(int header) throws IOException {
|
||||
boolean sync = false;
|
||||
if ((header & HEADER_MOREFLAGS) != 0) {
|
||||
if (unmarshal.read8Bit() != (HEADER_MUSTREPLY | HEADER_SYNCHRONOUS))
|
||||
{
|
||||
throw new IOException(
|
||||
"read URP request with bad MUSTREPLY/SYNCHRONOUS byte");
|
||||
}
|
||||
sync = true;
|
||||
}
|
||||
int funId = (header & HEADER_FUNCTIONID16) != 0
|
||||
? unmarshal.read16Bit() : unmarshal.read8Bit();
|
||||
if ((header & HEADER_NEWTYPE) != 0) {
|
||||
inL1Type = unmarshal.readType();
|
||||
if (inL1Type.getTypeClass() != TypeClass.INTERFACE) {
|
||||
throw new IOException(
|
||||
"read URP request with non-interface type " + inL1Type);
|
||||
}
|
||||
}
|
||||
if ((header & HEADER_NEWOID) != 0) {
|
||||
inL1Oid = unmarshal.readObjectId();
|
||||
}
|
||||
if ((header & HEADER_NEWTID) != 0) {
|
||||
inL1Tid = unmarshal.readThreadId();
|
||||
}
|
||||
return readRequest(funId, sync);
|
||||
}
|
||||
|
||||
private UrpMessage readShortRequest(int header) throws IOException {
|
||||
int funId = (header & HEADER_FUNCTIONID14) != 0
|
||||
? ((header & HEADER_FUNCTIONID) << 8) | unmarshal.read8Bit()
|
||||
: header & HEADER_FUNCTIONID;
|
||||
return readRequest(funId, false);
|
||||
}
|
||||
|
||||
private UrpMessage readRequest(int functionId, boolean forcedSynchronous)
|
||||
throws IOException
|
||||
{
|
||||
boolean internal = PROPERTIES_OID.equals(inL1Oid);
|
||||
// inL1Oid may be null in XInstanceProvider.getInstance("")
|
||||
XCurrentContext cc =
|
||||
(currentContext && !internal
|
||||
&& functionId != MethodDescription.ID_RELEASE)
|
||||
? (XCurrentContext) unmarshal.readInterface(
|
||||
new Type(XCurrentContext.class))
|
||||
: null;
|
||||
MethodDescription desc = inL1Type.getMethodDescription(functionId);
|
||||
if (desc == null) {
|
||||
throw new IOException(
|
||||
"read URP request with unsupported function ID " + functionId);
|
||||
}
|
||||
TypeDescription[] inSig = desc.getInSignature();
|
||||
TypeDescription[] outSig = desc.getOutSignature();
|
||||
Object[] args = new Object[inSig.length];
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
if (inSig[i] != null) {
|
||||
if (outSig[i] != null) {
|
||||
Object inout = Array.newInstance(
|
||||
outSig[i].getComponentType().getZClass(), 1);
|
||||
Array.set(
|
||||
inout, 0,
|
||||
unmarshal.readValue(
|
||||
outSig[i].getComponentType()));
|
||||
args[i] = inout;
|
||||
} else {
|
||||
args[i] = unmarshal.readValue(inSig[i]);
|
||||
}
|
||||
} else {
|
||||
args[i] = Array.newInstance(
|
||||
outSig[i].getComponentType().getZClass(), 1);
|
||||
}
|
||||
}
|
||||
boolean sync = forcedSynchronous || !desc.isOneway();
|
||||
if (sync) {
|
||||
pendingIn.push(
|
||||
inL1Tid, new PendingRequests.Item(internal, desc, args));
|
||||
}
|
||||
return new UrpMessage(
|
||||
inL1Tid, true, inL1Oid, inL1Type, desc, sync, cc, false, null, args,
|
||||
internal);
|
||||
}
|
||||
|
||||
private UrpMessage readReply(int header) {
|
||||
if ((header & HEADER_NEWTID) != 0) {
|
||||
inL1Tid = unmarshal.readThreadId();
|
||||
}
|
||||
PendingRequests.Item pending = pendingOut.pop(inL1Tid);
|
||||
TypeDescription resultType;
|
||||
TypeDescription[] argTypes;
|
||||
Object[] args;
|
||||
boolean exception = (header & HEADER_EXCEPTION) != 0;
|
||||
if (exception) {
|
||||
resultType = TypeDescription.getTypeDescription(TypeClass.ANY);
|
||||
argTypes = null;
|
||||
args = null;
|
||||
} else {
|
||||
resultType = pending.function.getReturnSignature();
|
||||
argTypes = pending.function.getOutSignature();
|
||||
args = pending.arguments;
|
||||
}
|
||||
Object result = resultType == null
|
||||
? null : unmarshal.readValue(resultType);
|
||||
if (argTypes != null) {
|
||||
for (int i = 0; i < argTypes.length; ++i) {
|
||||
if (argTypes[i] != null) {
|
||||
Array.set(
|
||||
args[i], 0,
|
||||
unmarshal.readValue(
|
||||
argTypes[i].getComponentType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new UrpMessage(
|
||||
inL1Tid, false, null, null, null, false, null, exception, result,
|
||||
args, pending.internal);
|
||||
}
|
||||
|
||||
private boolean writeRequest(
|
||||
boolean internal, String oid, TypeDescription type, String function,
|
||||
ThreadId tid, Object[] arguments)
|
||||
throws IOException
|
||||
{
|
||||
MethodDescription desc = type.getMethodDescription(function);
|
||||
synchronized (output) {
|
||||
if (desc.getIndex() == MethodDescription.ID_RELEASE
|
||||
&& releaseQueue.size() < MAX_RELEASE_QUEUE_SIZE)
|
||||
{
|
||||
releaseQueue.add(
|
||||
new QueuedRelease(internal, oid, type, desc, tid));
|
||||
return false;
|
||||
} else {
|
||||
writeQueuedReleases();
|
||||
return writeRequest(
|
||||
internal, oid, type, desc, tid, arguments, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean writeRequest(
|
||||
boolean internal, String oid, TypeDescription type,
|
||||
MethodDescription desc, ThreadId tid, Object[] arguments,
|
||||
boolean flush)
|
||||
throws IOException
|
||||
{
|
||||
int funId = desc.getIndex();
|
||||
if (funId < 0 || funId > MAX_FUNCTIONID16) {
|
||||
throw new IllegalArgumentException(
|
||||
"function ID " + funId + " out of range");
|
||||
}
|
||||
boolean forceSync = forceSynchronous
|
||||
&& funId != MethodDescription.ID_RELEASE;
|
||||
boolean moreFlags = forceSync && desc.isOneway();
|
||||
boolean longHeader = moreFlags;
|
||||
int header = 0;
|
||||
if (!type.equals(outL1Type)) {
|
||||
longHeader = true;
|
||||
header |= HEADER_NEWTYPE;
|
||||
outL1Type = type;
|
||||
} else {
|
||||
type = null;
|
||||
}
|
||||
if (!oid.equals(outL1Oid)) {
|
||||
longHeader = true;
|
||||
header |= HEADER_NEWOID;
|
||||
outL1Oid = oid;
|
||||
} else {
|
||||
oid = null;
|
||||
}
|
||||
if (!tid.equals(outL1Tid)) {
|
||||
longHeader = true;
|
||||
header |= HEADER_NEWTID;
|
||||
outL1Tid = tid;
|
||||
} else {
|
||||
tid = null;
|
||||
}
|
||||
if (funId > MAX_FUNCTIONID14) {
|
||||
longHeader = true;
|
||||
}
|
||||
if (longHeader) {
|
||||
header |= HEADER_LONGHEADER | HEADER_REQUEST;
|
||||
if (funId > MAX_FUNCTIONID8) {
|
||||
header |= HEADER_FUNCTIONID16;
|
||||
}
|
||||
if (moreFlags) {
|
||||
header |= HEADER_MOREFLAGS;
|
||||
}
|
||||
marshal.write8Bit(header);
|
||||
if (moreFlags) {
|
||||
marshal.write8Bit(HEADER_MUSTREPLY | HEADER_SYNCHRONOUS);
|
||||
}
|
||||
if (funId > MAX_FUNCTIONID8) {
|
||||
marshal.write16Bit(funId);
|
||||
} else {
|
||||
marshal.write8Bit(funId);
|
||||
}
|
||||
if (type != null) {
|
||||
marshal.writeType(type);
|
||||
}
|
||||
if (oid != null) {
|
||||
marshal.writeObjectId(oid);
|
||||
}
|
||||
if (tid != null) {
|
||||
marshal.writeThreadId(tid);
|
||||
}
|
||||
} else {
|
||||
if (funId > HEADER_FUNCTIONID) {
|
||||
marshal.write8Bit(HEADER_FUNCTIONID14 | (funId >> 8));
|
||||
}
|
||||
marshal.write8Bit(funId);
|
||||
}
|
||||
if (currentContext && !internal
|
||||
&& funId != MethodDescription.ID_RELEASE)
|
||||
{
|
||||
marshal.writeInterface(
|
||||
UnoRuntime.getCurrentContext(),
|
||||
new Type(XCurrentContext.class));
|
||||
}
|
||||
TypeDescription[] inSig = desc.getInSignature();
|
||||
TypeDescription[] outSig = desc.getOutSignature();
|
||||
for (int i = 0; i < inSig.length; ++i) {
|
||||
if (inSig[i] != null) {
|
||||
if (outSig[i] != null) {
|
||||
marshal.writeValue(
|
||||
outSig[i].getComponentType(),
|
||||
((Object[]) arguments[i])[0]);
|
||||
} else {
|
||||
marshal.writeValue(
|
||||
inSig[i], arguments[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean sync = forceSync || !desc.isOneway();
|
||||
if (sync) {
|
||||
pendingOut.push(
|
||||
outL1Tid, new PendingRequests.Item(internal, desc, arguments));
|
||||
}
|
||||
writeBlock(flush);
|
||||
return sync;
|
||||
}
|
||||
|
||||
private void writeBlock(boolean flush) throws IOException {
|
||||
byte[] data = marshal.reset();
|
||||
output.writeInt(data.length);
|
||||
output.writeInt(1);
|
||||
output.write(data);
|
||||
if (flush) {
|
||||
output.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeQueuedReleases() throws IOException {
|
||||
for (int i = releaseQueue.size(); i > 0;) {
|
||||
--i;
|
||||
QueuedRelease r = releaseQueue.get(i);
|
||||
writeRequest(
|
||||
r.internal, r.objectId, r.type, r.method, r.threadId, null,
|
||||
false);
|
||||
releaseQueue.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean parseAttributes(String attributes) {
|
||||
boolean forceSynchronous = true;
|
||||
if (attributes != null) {
|
||||
StringTokenizer t = new StringTokenizer(attributes, ",");
|
||||
while (t.hasMoreTokens()) {
|
||||
String a = t.nextToken();
|
||||
String v = null;
|
||||
int i = a.indexOf('=');
|
||||
if (i >= 0) {
|
||||
v = a.substring(i + 1);
|
||||
a = a.substring(0, i);
|
||||
}
|
||||
if (a.equalsIgnoreCase("ForceSynchronous")) {
|
||||
forceSynchronous = parseBooleanAttributeValue(a, v);
|
||||
} else if (a.equalsIgnoreCase("negotiate")) {
|
||||
// Ignored:
|
||||
parseBooleanAttributeValue(a, v);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"unknown protocol attribute " + a);
|
||||
}
|
||||
}
|
||||
}
|
||||
return forceSynchronous;
|
||||
}
|
||||
|
||||
private static boolean parseBooleanAttributeValue(
|
||||
String attribute, String value)
|
||||
{
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"missing value for protocol attribute " + attribute);
|
||||
}
|
||||
if (value.equals("0")) {
|
||||
return false;
|
||||
} else if (value.equals("1")) {
|
||||
return true;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"bad value " + value + " for protocol attribute " + attribute);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class QueuedRelease {
|
||||
public QueuedRelease(
|
||||
boolean internal, String objectId, TypeDescription type,
|
||||
MethodDescription method, ThreadId threadId)
|
||||
{
|
||||
this.internal = internal;
|
||||
this.objectId = objectId;
|
||||
this.type = type;
|
||||
this.method = method;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
public final boolean internal;
|
||||
public final String objectId;
|
||||
public final TypeDescription type;
|
||||
public final MethodDescription method;
|
||||
public final ThreadId threadId;
|
||||
}
|
||||
|
||||
private static final String PROPERTIES_OID = "UrpProtocolProperties";
|
||||
private static final int PROPERTIES_FID_REQUEST_CHANGE = 4;
|
||||
private static final String PROPERTIES_FUN_REQUEST_CHANGE = "requestChange";
|
||||
private static final int PROPERTIES_FID_COMMIT_CHANGE = 5;
|
||||
private static final String PROPERTIES_FUN_COMMIT_CHANGE = "commitChange";
|
||||
private static final String PROPERTY_CURRENT_CONTEXT = "CurrentContext";
|
||||
|
||||
private static final short CACHE_SIZE = 256;
|
||||
|
||||
private static final int HEADER_LONGHEADER = 0x80;
|
||||
private static final int HEADER_REQUEST = 0x40;
|
||||
private static final int HEADER_NEWTYPE = 0x20;
|
||||
private static final int HEADER_NEWOID = 0x10;
|
||||
private static final int HEADER_NEWTID = 0x08;
|
||||
private static final int HEADER_FUNCTIONID16 = 0x04;
|
||||
private static final int HEADER_MOREFLAGS = 0x01;
|
||||
private static final int HEADER_MUSTREPLY = 0x80;
|
||||
private static final int HEADER_SYNCHRONOUS = 0x40;
|
||||
private static final int HEADER_FUNCTIONID14 = 0x40;
|
||||
private static final int HEADER_FUNCTIONID = 0x3F;
|
||||
private static final int HEADER_EXCEPTION = 0x20;
|
||||
|
||||
private static final int MAX_FUNCTIONID16 = 0xFFFF;
|
||||
private static final int MAX_FUNCTIONID14 = 0x3FFF;
|
||||
private static final int MAX_FUNCTIONID8 = 0xFF;
|
||||
|
||||
private static final int STATE_INITIAL0 = 0;
|
||||
private static final int STATE_INITIAL = 1;
|
||||
private static final int STATE_REQUESTED = 2;
|
||||
private static final int STATE_COMMITTED = 3;
|
||||
private static final int STATE_WAIT = 4;
|
||||
private static final int STATE_TERMINATED = 5;
|
||||
|
||||
private static final int MAX_RELEASE_QUEUE_SIZE = 100;
|
||||
|
||||
private static final Random randomGenerator = new Random();
|
||||
|
||||
private final DataInput input;
|
||||
private final DataOutputStream output;
|
||||
|
||||
private final Marshal marshal;
|
||||
private final Unmarshal unmarshal;
|
||||
|
||||
private final boolean forceSynchronous;
|
||||
|
||||
private final PendingRequests pendingIn = new PendingRequests();
|
||||
private final PendingRequests pendingOut = new PendingRequests();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
private int state = STATE_INITIAL0;
|
||||
private boolean initialized = false;
|
||||
private ThreadId propertiesTid = null;
|
||||
private int random;
|
||||
private boolean currentContext = false;
|
||||
|
||||
private ThreadId inL1Tid = null;
|
||||
private String inL1Oid = null;
|
||||
private TypeDescription inL1Type = null;
|
||||
|
||||
private ThreadId outL1Tid = null;
|
||||
private String outL1Oid = null;
|
||||
private TypeDescription outL1Type = null;
|
||||
|
||||
private final ArrayList<QueuedRelease> releaseQueue = new ArrayList<QueuedRelease>(); // of QueuedRelease
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,117 @@
|
||||
/* -*- 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.lib.util;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Helper class to asynchronously execute finalize methods.
|
||||
*
|
||||
* <p>Current JVMs seem not to be robust against long-running finalize methods,
|
||||
* in that such long-running finalize methods may lead to OutOfMemoryErrors.
|
||||
* This class mitigates the problem by asynchronously shifting the bodies of
|
||||
* potentially long-running finalize methods into an extra thread. Classes that
|
||||
* make use of this in their finalize methods are the proxies used in the
|
||||
* intra-process JNI UNO bridge and the inter-process Java URP UNO bridge (where
|
||||
* in both cases finalizers lead to synchronous UNO release calls).</p>
|
||||
*
|
||||
* <p>Irrespective whether JVMs are getting more mature and should no longer
|
||||
* have problems with long-running finalize methods, at least the JNI UNO bridge
|
||||
* needs some way to stop finalization of proxies (to C++ objects) well before
|
||||
* process exit, as provided by drain().</p>
|
||||
*/
|
||||
public final class AsynchronousFinalizer {
|
||||
public AsynchronousFinalizer() {
|
||||
thread = new Thread("AsynchronousFinalizer") {
|
||||
@Override
|
||||
public void run() {
|
||||
for (;;) {
|
||||
Job j;
|
||||
synchronized (queue) {
|
||||
for (;;) {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
if (!queue.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
queue.wait();
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
j = queue.remove(0);
|
||||
}
|
||||
try {
|
||||
j.run();
|
||||
} catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job to be executed asynchronously.
|
||||
*
|
||||
* <p>The run method of the given job is called exactly once. If it terminates
|
||||
* abnormally by throwing any Throwable, that is ignored.</p>
|
||||
*
|
||||
* @param job represents the body of some finalize method; must not be null.
|
||||
*/
|
||||
public void add(Job job) {
|
||||
synchronized (queue) {
|
||||
boolean first = queue.isEmpty();
|
||||
queue.add(job);
|
||||
if (first) {
|
||||
queue.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drain() throws InterruptedException {
|
||||
synchronized (queue) {
|
||||
done = true;
|
||||
queue.notify();
|
||||
}
|
||||
// tdf#123481 Only join if we are not in our own thread, else we have a deadlock
|
||||
if (Thread.currentThread() != thread)
|
||||
thread.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface to represent bodies of finalize methods.
|
||||
*
|
||||
* Similar to <code>Runnable</code>, except that the run method may throw any
|
||||
* <code>Throwable</code> (which is effectively ignored by
|
||||
* <code>AsynchronousFinalizer.add</code>, similar to any <code>Throwables</code>
|
||||
* raised by finalize being ignored).
|
||||
*/
|
||||
public interface Job {
|
||||
void run() throws Throwable;
|
||||
}
|
||||
|
||||
private final LinkedList<Job> queue = new LinkedList<Job>();
|
||||
private final Thread thread;
|
||||
private boolean done = false;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,132 @@
|
||||
/* -*- 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.lib.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Helper functions to locate and load native files.
|
||||
*
|
||||
* <p>The methods in this class are designed to find the requested resources in
|
||||
* as many cases as possible. They search various places, roughly from most
|
||||
* specific to most general. This works well if a component is known to bring
|
||||
* with it a certain resource, and that resource has to be found. However, it
|
||||
* might not work very well in cases where you want to check whether a
|
||||
* component brings with it a certain resource or not: a similarly named
|
||||
* resource from another component might be found by the eager search
|
||||
* algorithm.</p>
|
||||
*/
|
||||
public final class NativeLibraryLoader {
|
||||
/**
|
||||
* Load a system library, using a given class loader to locate the library.
|
||||
*
|
||||
* <p>This is similar to <code>System.loadLibrary</code>.</p>
|
||||
*
|
||||
* @param loader a class loader; may be null.
|
||||
* @param libname the library name; how this name is mapped to a system
|
||||
* library name is system dependent.
|
||||
*/
|
||||
public static void loadLibrary(ClassLoader loader, String libname) {
|
||||
String sysname = System.mapLibraryName(libname);
|
||||
// At least Oracle's 1.7.0_51 now maps to .dylib rather than .jnilib:
|
||||
if (System.getProperty("os.name").startsWith("Mac")
|
||||
&& sysname.endsWith(".dylib"))
|
||||
{
|
||||
sysname
|
||||
= sysname.substring(0, sysname.length() - "dylib".length())
|
||||
+ "jnilib";
|
||||
}
|
||||
File path = getResource(loader, sysname);
|
||||
if (path == null) {
|
||||
// If the library cannot be found as a class loader resource, try
|
||||
// the global System.loadLibrary as a last resort:
|
||||
System.loadLibrary(libname);
|
||||
} else {
|
||||
System.load(path.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate a system resource, using a given class loader.
|
||||
*
|
||||
* <p>This is similar to <code>ClassLoader.getResource</code>, but only works
|
||||
* for local resources (local files), and adds additional functionality for
|
||||
* <code>URLClassLoaders</code>.</p>
|
||||
*
|
||||
* @param loader a class loader; may be null.
|
||||
* @param name a resource name (that is, the name of a file).
|
||||
* @return a File locating the resource, or null if the resource was not
|
||||
* found.
|
||||
*/
|
||||
public static File getResource(ClassLoader loader, String name) {
|
||||
if (loader != null) {
|
||||
File path = UrlToFileMapper.mapUrlToFile(loader.getResource(name));
|
||||
if (path != null) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
// URLClassLoaders work on lists of URLs, which are typically URLs
|
||||
// locating JAR files (scheme://auth/dir1/dir2/some.jar). The following
|
||||
// code looks for resource name beside the JAR file
|
||||
// (scheme://auth/dir1/dir2/name) and one directory up
|
||||
// (scheme://auth/dir1/name). The second step is important in a typical
|
||||
// OOo installation, where the JAR files are in the program/classes
|
||||
// directory while the shared libraries are in the program directory.
|
||||
if (!(loader instanceof URLClassLoader)) {
|
||||
return null;
|
||||
}
|
||||
URL[] urls = ((URLClassLoader) loader).getURLs();
|
||||
for (int i = 0; i < urls.length; ++i) {
|
||||
File path = UrlToFileMapper.mapUrlToFile(urls[i]);
|
||||
if (path != null) {
|
||||
File dir = path.isDirectory() ? path : path.getParentFile();
|
||||
if (dir != null) {
|
||||
path = new File(dir, name);
|
||||
if (path.exists()) {
|
||||
return path;
|
||||
}
|
||||
dir = dir.getParentFile();
|
||||
if (dir != null) {
|
||||
path = new File(dir, name);
|
||||
if (path.exists()) {
|
||||
return path;
|
||||
}
|
||||
// On macOS, dir is now the Resources dir,
|
||||
// we want to look in Frameworks
|
||||
if (System.getProperty("os.name").startsWith("Mac")
|
||||
&& dir.getName().equals("Resources")) {
|
||||
dir = dir.getParentFile();
|
||||
path = new File(dir, "Frameworks/" + name);
|
||||
if (path.exists()) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private NativeLibraryLoader() {} // do not instantiate
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,46 @@
|
||||
/* -*- 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.lib.util;
|
||||
|
||||
/**
|
||||
* jurt.jar internal string helper methods.
|
||||
*/
|
||||
public final class StringHelper
|
||||
{
|
||||
private StringHelper() {} // do not instantiate
|
||||
|
||||
public static String replace(String str, char from, String to) {
|
||||
StringBuffer b = new StringBuffer();
|
||||
for (int i = 0;;) {
|
||||
int j = str.indexOf(from, i);
|
||||
if (j == -1) {
|
||||
b.append(str.substring(i));
|
||||
break;
|
||||
} else {
|
||||
b.append(str.substring(i, j));
|
||||
b.append(to);
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* -*- 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.lib.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
/**
|
||||
* Maps Java URL representations to File representations, on any Java version.
|
||||
*
|
||||
* This used to be used to do URL to File mapping in pre-Java1.4 days, but since
|
||||
* we now require Java 1.5, it is largely unnecessary.
|
||||
*
|
||||
* @since UDK 3.2.8
|
||||
*/
|
||||
public final class UrlToFileMapper {
|
||||
|
||||
/**
|
||||
* Maps Java URL representations to File representations.
|
||||
*
|
||||
* @param url some URL, possibly null.
|
||||
* @return a corresponding File, or null on failure.
|
||||
*/
|
||||
public static File mapUrlToFile(URL url) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
// where encodedUrl is url.toString(), but since that may contain
|
||||
// unsafe characters (e.g., space, " "), it is encoded, as otherwise
|
||||
// the URI constructor might throw java.net.URISyntaxException (in
|
||||
// Java 1.5, URL.toURI might be used instead).
|
||||
String encodedUrl = encode(url.toString());
|
||||
URI uri = new URI(encodedUrl);
|
||||
try {
|
||||
return new File(uri);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new RuntimeException(ex); // should never happen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String encode(String url) {
|
||||
StringBuffer buf = new StringBuffer(url.length());
|
||||
for (int i = 0; i < url.length(); ++i) {
|
||||
char c = url.charAt(i);
|
||||
// The RFC 2732 <uric> characters: !$&'()*+,-./:;=?@[]_~ plus digits
|
||||
// and letters; additionally, do not encode % again.
|
||||
if (c >= 'a' && c <= 'z' || c >= '?' && c <= '['
|
||||
|| c >= '$' && c <= ';' || c == '!' || c == '=' || c == ']'
|
||||
|| c == '_' || c == '~')
|
||||
{
|
||||
buf.append(c);
|
||||
} else if (c == ' ') {
|
||||
buf.append("%20");
|
||||
} else {
|
||||
try {
|
||||
String enc = URLEncoder.encode(Character.toString(c), "UTF-8");
|
||||
buf.append(enc);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e); // should never happen
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private UrlToFileMapper() {}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,668 @@
|
||||
/* -*- 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.uno;
|
||||
|
||||
/**
|
||||
* This class provides static methods which aim at exploring the contents of an
|
||||
* Any and extracting its value.
|
||||
*
|
||||
* <p>All public methods take an Object argument that either is the immediate object,
|
||||
* such as Boolean, Type, interface implementation, or an Any that contains an
|
||||
* object.</p>
|
||||
*
|
||||
* <p>The methods which extract the value do a widening conversion. See the
|
||||
* method comments for the respective conversions.</p>
|
||||
*/
|
||||
public class AnyConverter
|
||||
{
|
||||
/**
|
||||
* Determines the type of an Any object.
|
||||
*
|
||||
* @param object any object.
|
||||
* @return type object.
|
||||
*/
|
||||
public static Type getType( Object object )
|
||||
{
|
||||
Type t;
|
||||
if (null == object)
|
||||
{
|
||||
t = m_XInterface_type;
|
||||
}
|
||||
else if (object instanceof Any)
|
||||
{
|
||||
t = ((Any)object).getType();
|
||||
// nested any
|
||||
if (TypeClass.ANY_value == t.getTypeClass().getValue())
|
||||
return getType( ((Any)object).getObject() );
|
||||
}
|
||||
else
|
||||
{
|
||||
t = new Type( object.getClass() );
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains the idl type <code>void</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any is void, false otherwise.
|
||||
*/
|
||||
public static boolean isVoid(Object object){
|
||||
return containsType(TypeClass.VOID, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>char</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a char, false otherwise.
|
||||
*/
|
||||
public static boolean isChar(Object object){
|
||||
return containsType(TypeClass.CHAR, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>boolean</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a boolean, false otherwise.
|
||||
*/
|
||||
public static boolean isBoolean(Object object){
|
||||
return containsType(TypeClass.BOOLEAN, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>byte</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a byte, false otherwise.
|
||||
*/
|
||||
public static boolean isByte(Object object){
|
||||
return containsType(TypeClass.BYTE, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>short</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a short, false otherwise.
|
||||
*/
|
||||
public static boolean isShort(Object object){
|
||||
return containsType(TypeClass.SHORT, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>long</code>
|
||||
* (which maps to a java-int).
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a int, false otherwise.
|
||||
*/
|
||||
public static boolean isInt(Object object){
|
||||
return containsType(TypeClass.LONG, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>hyper</code>
|
||||
* (which maps to a java-long).
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a long, false otherwise.
|
||||
*/
|
||||
public static boolean isLong(Object object){
|
||||
return containsType(TypeClass.HYPER, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>float</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a float, false otherwise.
|
||||
*/
|
||||
public static boolean isFloat(Object object){
|
||||
return containsType(TypeClass.FLOAT, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>double</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a double, false otherwise.
|
||||
*/
|
||||
public static boolean isDouble(Object object){
|
||||
return containsType(TypeClass.DOUBLE, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>string</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a string, false otherwise.
|
||||
*/
|
||||
public static boolean isString(Object object){
|
||||
return containsType(TypeClass.STRING, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>enum</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true if the any contains an enum, false otherwise.
|
||||
*/
|
||||
public static boolean isEnum(Object object)
|
||||
{
|
||||
return containsType(TypeClass.ENUM, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains a value of the idl type <code>type</code>.
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains a type, false otherwise.
|
||||
*/
|
||||
public static boolean isType(Object object){
|
||||
return containsType(TypeClass.TYPE, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains an interface, struct, exception, sequence or enum.
|
||||
*
|
||||
* <p>If <em>object</em> is an any with an interface type, then true is also
|
||||
* returned if the any contains a null reference. This is because interfaces
|
||||
* are allowed to have a null value contrary to other UNO types.</p>
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true if the any contains an object.
|
||||
*/
|
||||
public static boolean isObject(Object object)
|
||||
{
|
||||
int tc = getType(object).getTypeClass().getValue();
|
||||
return (TypeClass.INTERFACE_value == tc ||
|
||||
TypeClass.STRUCT_value == tc ||
|
||||
TypeClass.EXCEPTION_value == tc ||
|
||||
TypeClass.SEQUENCE_value == tc ||
|
||||
TypeClass.ENUM_value == tc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the any contains UNO idl sequence value (meaning a java array
|
||||
* containing elements which are values of UNO idl types).
|
||||
*
|
||||
* @param object the object to check.
|
||||
* @return true when the any contains an object which implements interfaces,
|
||||
* false otherwise.
|
||||
*/
|
||||
public static boolean isArray(Object object){
|
||||
return containsType(TypeClass.SEQUENCE, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Char object or an Any object containing a Char object into a
|
||||
* simple char.
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @return the char contained within the object.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no char is
|
||||
* contained within object.
|
||||
*
|
||||
* @see #isChar
|
||||
*/
|
||||
public static char toChar(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Character ret= (Character)convertSimple(TypeClass.CHAR, null, object);
|
||||
return ret.charValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Boolean object or an Any object containing a Boolean object
|
||||
* into a simple boolean.
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @return the boolean contained within the object
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no boolean is
|
||||
* contained within object
|
||||
*
|
||||
* @see #isBoolean
|
||||
*/
|
||||
public static boolean toBoolean(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Boolean ret= (Boolean)convertSimple(TypeClass.BOOLEAN, null, object);
|
||||
return ret.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Byte object or an Any object containing a Byte object into a
|
||||
* simple byte.
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @return the boolean contained within the object.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no byte is
|
||||
* contained within object.
|
||||
*
|
||||
* @see #isBoolean
|
||||
*/
|
||||
public static byte toByte(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Byte ret= (Byte)convertSimple(TypeClass.BYTE, null, object);
|
||||
return ret.byteValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number object into a simple short and allows widening conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Byte, Short or Any containing these types.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no short or
|
||||
* byte is contained within object.
|
||||
*
|
||||
* @return the short contained within the object.
|
||||
*/
|
||||
public static short toShort(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Short ret= (Short)convertSimple(TypeClass.SHORT, null, object);
|
||||
return ret.shortValue();
|
||||
}
|
||||
/**
|
||||
* Converts a number object into an idl unsigned short and allows widening
|
||||
* conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Anies containing idl unsigned short values.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no idl unsigned
|
||||
* short is contained within Any.
|
||||
*
|
||||
* @return an (unsigned) short.
|
||||
*/
|
||||
public static short toUnsignedShort(Object object)
|
||||
throws com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
Short ret= (Short)convertSimple(TypeClass.UNSIGNED_SHORT, null, object);
|
||||
return ret.shortValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number object into a simple int and allows widening conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Byte, Short, Integer or Any containing these
|
||||
* types.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no short, byte
|
||||
* or int is contained within object.
|
||||
*
|
||||
* @return the int contained within the object.
|
||||
*/
|
||||
public static int toInt(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Integer ret= (Integer) convertSimple( TypeClass.LONG, null, object);
|
||||
return ret.intValue();
|
||||
}
|
||||
/**
|
||||
* Converts a number object into an idl unsigned long and allows widening
|
||||
* conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Anies containing idl unsigned short or
|
||||
* unsigned long values.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no idl unsigned
|
||||
* short nor unsigned long is contained within Any.
|
||||
*
|
||||
* @return an (unsigned) int.
|
||||
*/
|
||||
public static int toUnsignedInt(Object object)
|
||||
throws com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
Integer ret = (Integer)convertSimple(TypeClass.UNSIGNED_LONG, null, object);
|
||||
return ret.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number object into a simple long and allows widening conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Byte, Short, Integer, Long or Any containing
|
||||
* these types.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no short, byte,
|
||||
* int or long is contained within object.
|
||||
*
|
||||
* @return the long contained within the object.
|
||||
*/
|
||||
public static long toLong(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Long ret= (Long) convertSimple( TypeClass.HYPER, null, object);
|
||||
return ret.longValue();
|
||||
}
|
||||
/**
|
||||
* Converts a number object into an idl unsigned hyper and allows widening
|
||||
* conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Anies containing idl unsigned short, unsigned
|
||||
* long or unsigned hyper values.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no idl unsigned
|
||||
* short, nor unsigned long nor unsigned hyper is contained within object.
|
||||
*
|
||||
* @return an (unsigned) long.
|
||||
*/
|
||||
public static long toUnsignedLong(Object object)
|
||||
throws com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
Long ret = (Long)convertSimple(TypeClass.UNSIGNED_HYPER, null, object);
|
||||
return ret.longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number object into a simple float and allows widening conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Byte, Short, Float or Any containing these
|
||||
* types.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no byte, short
|
||||
* or float is contained within object.
|
||||
*
|
||||
* @return the float contained within the object.
|
||||
*/
|
||||
public static float toFloat(Object object) throws com.sun.star.lang.IllegalArgumentException{
|
||||
Float ret= (Float) convertSimple( TypeClass.FLOAT,null, object);
|
||||
return ret.floatValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number object into a simple double and allows widening conversions.
|
||||
*
|
||||
* <p>Allowed argument types are Byte, Short, Int, Float, Double or Any
|
||||
* containing these types.</p>
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no byte, short,
|
||||
* int, float or double is contained within object.
|
||||
*
|
||||
* @return the double contained within the object.
|
||||
*/
|
||||
public static double toDouble(Object object) throws com.sun.star.lang.IllegalArgumentException {
|
||||
Double ret= (Double) convertSimple( TypeClass.DOUBLE, null, object);
|
||||
return ret.doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string or an any containing a string into a string.
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no string is
|
||||
* contained within object.
|
||||
*
|
||||
* @return the string contained within the object.
|
||||
*/
|
||||
public static String toString(Object object) throws com.sun.star.lang.IllegalArgumentException {
|
||||
return (String) convertSimple( TypeClass.STRING, null, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Type or an any containing a Type into a Type.
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no type is
|
||||
* contained within object.
|
||||
*
|
||||
* @return the type contained within the object.
|
||||
*/
|
||||
public static Type toType(Object object) throws com.sun.star.lang.IllegalArgumentException {
|
||||
return (Type) convertSimple( TypeClass.TYPE, null, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a UNO object (struct, exception, sequence, enum or interface) or
|
||||
* an Any containing these types into a UNO object of a specified destination
|
||||
* type.
|
||||
*
|
||||
* <p> For interfaces, the argument <em>object</em> is queried for the interface
|
||||
* specified by the <em>type</em> argument.</p>
|
||||
*
|
||||
* <p>That query (UnoRuntime.queryInterface) might return null, if the interface
|
||||
* is not implemented or a null-ref or a VOID any is given.</p>
|
||||
*
|
||||
* @param type type of the returned value.
|
||||
* @param object the object that is to be converted.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case conversion is
|
||||
* not possible.
|
||||
*
|
||||
* @return destination object.
|
||||
*/
|
||||
public static Object toObject(Type type, Object object)
|
||||
throws com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
return convertSimple( type.getTypeClass(), type, object );
|
||||
}
|
||||
/**
|
||||
* Converts a UNO object (struct, exception, sequence, enum or interface) or
|
||||
* an Any containing these types into a UNO object of a specified destination
|
||||
* type.
|
||||
*
|
||||
* <p>For interfaces, the argument <em>object</em> is queried for the interface
|
||||
* specified by the <em>type</em> argument. That query (UnoRuntime.queryInterface)
|
||||
* might return null, if the interface is not implemented or a null-ref or a
|
||||
* VOID any is given.</p>
|
||||
*
|
||||
* @param clazz class of the returned value.
|
||||
* @param object the object that is to be converted.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case conversion is
|
||||
* not possible.
|
||||
*
|
||||
* @return destination object.
|
||||
*/
|
||||
public static Object toObject(Class<?> clazz, Object object)
|
||||
throws com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
return toObject( new Type( clazz ), object );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array or an any containing an array into an array.
|
||||
*
|
||||
* @param object the object to convert.
|
||||
* @throws com.sun.star.lang.IllegalArgumentException in case no array is
|
||||
* contained within object.
|
||||
*
|
||||
* @return the array contained within the object.
|
||||
*/
|
||||
public static Object toArray( Object object) throws com.sun.star.lang.IllegalArgumentException {
|
||||
return convertSimple( TypeClass.SEQUENCE, null, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines the argument <em>object</em> if is correspond to the type in
|
||||
* argument <em>what</em>.
|
||||
*
|
||||
* <p><em>object</em> is either matched directly against the type or if it is
|
||||
* an any then the contained object is matched against the type.</p>
|
||||
*/
|
||||
private static boolean containsType( TypeClass what, Object object){
|
||||
return (getType(object).getTypeClass().getValue() == what.getValue());
|
||||
}
|
||||
|
||||
private static final Type m_XInterface_type = new Type( XInterface.class );
|
||||
|
||||
private static Object convertSimple( TypeClass destTClass, Type destType, Object object_ )
|
||||
throws com.sun.star.lang.IllegalArgumentException
|
||||
{
|
||||
Object object;
|
||||
Type type;
|
||||
if (object_ instanceof Any) {
|
||||
// unbox
|
||||
Any a = (Any)object_;
|
||||
object = a.getObject();
|
||||
type = a.getType();
|
||||
// nested any
|
||||
if (TypeClass.ANY_value == type.getTypeClass().getValue())
|
||||
return convertSimple( destTClass, destType, object );
|
||||
} else {
|
||||
object = object_;
|
||||
type = (null == object ? m_XInterface_type : new Type( object.getClass() ));
|
||||
}
|
||||
|
||||
int tc = type.getTypeClass().getValue();
|
||||
int dest_tc = destTClass.getValue();
|
||||
|
||||
if (null == object) {
|
||||
// special for interfaces
|
||||
if (TypeClass.INTERFACE_value == tc && dest_tc == tc)
|
||||
return null;
|
||||
} else {
|
||||
switch (dest_tc) {
|
||||
case TypeClass.CHAR_value:
|
||||
if (tc == TypeClass.CHAR_value)
|
||||
return object;
|
||||
break;
|
||||
case TypeClass.BOOLEAN_value:
|
||||
if (tc == TypeClass.BOOLEAN_value)
|
||||
return object;
|
||||
break;
|
||||
case TypeClass.BYTE_value:
|
||||
if (tc == TypeClass.BYTE_value)
|
||||
return object;
|
||||
break;
|
||||
case TypeClass.SHORT_value:
|
||||
switch (tc) {
|
||||
case TypeClass.BYTE_value:
|
||||
return Short.valueOf( ((Byte)object).byteValue() );
|
||||
case TypeClass.SHORT_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
switch (tc) {
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.LONG_value:
|
||||
switch (tc) {
|
||||
case TypeClass.BYTE_value:
|
||||
return Integer.valueOf( ((Byte)object).byteValue() );
|
||||
case TypeClass.SHORT_value:
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return Integer.valueOf( ((Short)object).shortValue() );
|
||||
case TypeClass.LONG_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
switch (tc) {
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return Integer.valueOf( ((Short)object).shortValue() );
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.HYPER_value:
|
||||
switch (tc) {
|
||||
case TypeClass.BYTE_value:
|
||||
return Long.valueOf( ((Byte)object).byteValue() );
|
||||
case TypeClass.SHORT_value:
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return Long.valueOf( ((Short)object).shortValue() );
|
||||
case TypeClass.LONG_value:
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
return Long.valueOf( ((Integer)object).intValue() );
|
||||
case TypeClass.HYPER_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.UNSIGNED_HYPER_value:
|
||||
switch (tc) {
|
||||
case TypeClass.UNSIGNED_SHORT_value:
|
||||
return Long.valueOf( ((Short)object).shortValue() );
|
||||
case TypeClass.UNSIGNED_LONG_value:
|
||||
return Long.valueOf( ((Integer)object).intValue() );
|
||||
case TypeClass.UNSIGNED_HYPER_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.FLOAT_value:
|
||||
switch (tc) {
|
||||
case TypeClass.BYTE_value:
|
||||
return new Float( ((Byte)object).byteValue() );
|
||||
case TypeClass.SHORT_value:
|
||||
return new Float( ((Short)object).shortValue() );
|
||||
case TypeClass.FLOAT_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.DOUBLE_value:
|
||||
switch (tc) {
|
||||
case TypeClass.BYTE_value:
|
||||
return new Double( ((Byte)object).byteValue() );
|
||||
case TypeClass.SHORT_value:
|
||||
return new Double( ((Short)object).shortValue() );
|
||||
case TypeClass.LONG_value:
|
||||
return new Double( ((Integer)object).intValue() );
|
||||
case TypeClass.FLOAT_value:
|
||||
return new Double( ((Float)object).floatValue() );
|
||||
case TypeClass.DOUBLE_value:
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.ENUM_value:
|
||||
if (tc == TypeClass.ENUM_value &&
|
||||
(null == destType || destType.equals( type ) /* optional destType */))
|
||||
{
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.STRING_value:
|
||||
if (tc == TypeClass.STRING_value)
|
||||
return object;
|
||||
break;
|
||||
case TypeClass.TYPE_value:
|
||||
if (tc == TypeClass.TYPE_value)
|
||||
return object;
|
||||
break;
|
||||
case TypeClass.INTERFACE_value:
|
||||
// Because object is a class, not an interface, it is
|
||||
// controversial what kind of Type "new Type(object.class)"
|
||||
// above should return (UNKNOWN or INTERFACE), so that we should
|
||||
// not check here for "tc == TypeClass.INTERFACE_value".
|
||||
// Instead, we check whether object (indirectly) derives from
|
||||
// XInterface:
|
||||
if (object instanceof XInterface)
|
||||
return UnoRuntime.queryInterface( destType, object );
|
||||
break;
|
||||
case TypeClass.STRUCT_value:
|
||||
case TypeClass.EXCEPTION_value:
|
||||
if (destType.isSupertypeOf(type)) {
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
case TypeClass.SEQUENCE_value:
|
||||
if (tc == TypeClass.SEQUENCE_value &&
|
||||
(null == destType || destType.equals( type ) /* optional destType */))
|
||||
{
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
"The Argument did not hold the proper type");
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,43 @@
|
||||
/* -*- 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.uno;
|
||||
|
||||
/**
|
||||
* The Ascii class represents the IDL build in type <code>ascii</code>.
|
||||
*
|
||||
* @deprecated do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Ascii {
|
||||
public final char ascii;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Ascii</code>.
|
||||
*
|
||||
* @deprecated do not use.
|
||||
* @param c the char value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Ascii(char c) {
|
||||
ascii = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,44 @@
|
||||
/* -*- 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.uno;
|
||||
|
||||
/**
|
||||
* The Ascii class represents the IDL build in type <code>asciistring</code>.
|
||||
*
|
||||
* @deprecated do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class AsciiString {
|
||||
public final String asciistring;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>AsciiString</code>.
|
||||
*
|
||||
* @deprecated do not use.
|
||||
* @param s the String value.
|
||||
*/
|
||||
@Deprecated
|
||||
public AsciiString(String s) {
|
||||
asciistring = s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* -*- 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.uno;
|
||||
|
||||
|
||||
/**
|
||||
* The mapping Exception.
|
||||
*
|
||||
* <p>The exception is replaced by the com.sun.star.lang.DisposedException.</p>
|
||||
*
|
||||
* @see com.sun.star.uno.UnoRuntime
|
||||
* @see com.sun.star.uno.IQueryInterface
|
||||
* @see com.sun.star.uno.IBridge
|
||||
*
|
||||
* @deprecated since UDK 3.0.2
|
||||
*/
|
||||
@Deprecated
|
||||
public class MappingException extends com.sun.star.uno.RuntimeException {
|
||||
/**
|
||||
* Constructs an empty <code>MappingException</code>.
|
||||
*/
|
||||
public MappingException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <code>MappingException</code> with a detail message.
|
||||
*
|
||||
* @param message the detail message.
|
||||
*/
|
||||
public MappingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <code>MappingException</code> with a detail message and a
|
||||
* context.
|
||||
*
|
||||
* @param message the detail message.
|
||||
* @param context the context.
|
||||
*/
|
||||
public MappingException(String message, Object context) {
|
||||
super(message, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,154 @@
|
||||
/* -*- 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.uno;
|
||||
|
||||
/**
|
||||
* This class holds weak reference to an object.
|
||||
*
|
||||
* <p>It actually holds a reference to a <code>com.sun.star.XAdapter</code>
|
||||
* implementation and obtains a hard reference if necessary.
|
||||
*/
|
||||
public class WeakReference
|
||||
{
|
||||
private OWeakRefListener m_listener;
|
||||
// There is no default constructor. Every instance must register itself with the
|
||||
// XAdapter interface, which is done in the constructors. Assume we have this code
|
||||
// WeakReference ref= new WeakReference();
|
||||
// ref = someOtherWeakReference;
|
||||
//
|
||||
// ref would not be notified (XReference.dispose()) because it did not register
|
||||
// itself. Therefore the XAdapter would be kept alive although this is not
|
||||
// necessary.
|
||||
|
||||
/**
|
||||
* Creates an instance of this class.
|
||||
*
|
||||
* @param obj another instance that is to be copied.
|
||||
*/
|
||||
public WeakReference(WeakReference obj)
|
||||
{
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
Object weakImpl = obj.get();
|
||||
if (weakImpl == null) {
|
||||
return;
|
||||
}
|
||||
XWeak weak = UnoRuntime.queryInterface(XWeak.class, weakImpl);
|
||||
if (weak != null) {
|
||||
XAdapter adapter = weak.queryAdapter();
|
||||
if (adapter != null)
|
||||
m_listener = new OWeakRefListener(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of this class.
|
||||
*
|
||||
* @param obj XWeak implementation.
|
||||
*/
|
||||
public WeakReference(Object obj)
|
||||
{
|
||||
XWeak weak= UnoRuntime.queryInterface(XWeak.class, obj);
|
||||
if (weak != null)
|
||||
{
|
||||
XAdapter adapter= weak.queryAdapter();
|
||||
if (adapter != null)
|
||||
m_listener= new OWeakRefListener(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hard reference to the object that is kept weak by this class.
|
||||
*
|
||||
* @return a hard reference to the XWeak implementation.
|
||||
*/
|
||||
public Object get()
|
||||
{
|
||||
if (m_listener != null)
|
||||
return m_listener.get();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of com.sun.star.uno.XReference for use with WeakReference.
|
||||
*
|
||||
* <p>It keeps the XAdapter implementation and registers always with it.
|
||||
* Deregistering occurs on notification by the adapter and the adapter is
|
||||
* released.</p>
|
||||
*/
|
||||
class OWeakRefListener implements XReference
|
||||
{
|
||||
private XAdapter m_adapter;
|
||||
|
||||
/**
|
||||
* The constructor registered this object with adapter.
|
||||
*
|
||||
* @param adapter the XAdapter implementation.
|
||||
*/
|
||||
OWeakRefListener( XAdapter adapter)
|
||||
{
|
||||
m_adapter= adapter;
|
||||
m_adapter.addReference(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method of <code>com.sun.star.uno.XReference</code>.
|
||||
*
|
||||
* <p>When called, it deregisters this object with the adapter and releases
|
||||
* the reference to it.</p>
|
||||
*/
|
||||
synchronized public void dispose()
|
||||
{
|
||||
if (m_adapter != null)
|
||||
{
|
||||
m_adapter.removeReference(this);
|
||||
m_adapter= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a hard reference to the object which is kept weak by the adapter
|
||||
* and returns it.
|
||||
*
|
||||
* @return hard reference to the otherwise weakly kept object.
|
||||
*/
|
||||
synchronized Object get()
|
||||
{
|
||||
Object retVal= null;
|
||||
if (m_adapter != null)
|
||||
{
|
||||
retVal= m_adapter.queryAdapted();
|
||||
if (retVal == null)
|
||||
{
|
||||
// If this object registered as listener with XAdapter while it was notifying
|
||||
// the listeners then this object might not have been notified. If queryAdapted
|
||||
// returned null then the weak kept object is dead and the listeners have already
|
||||
// been notified. And we missed it.
|
||||
m_adapter.removeReference(this);
|
||||
m_adapter= null;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
Reference in New Issue
Block a user