Add a FunctionBasedURPConnection and a websocket URP connector
- FunctionBasedURPConnection is used to enable a client to open a URP connection to a fresh Kit instance in COOL. - This URP connector can be used with that and https://github.com/CollaboraOnline/online/pull/6992 to use a Java Uno Remote Protocol client over websockets - For interoperability with existing Collabora Online websockets a prefix (urp ) is added to each message sent and a similar prefix (urp: ) is expected on each message recieved. This allows sending over the same websocket as other data is being transmitted through. If you are writing a bridge to work with this, you will need to add/strip the prefixes accordingly - This commit uses Java WebSocket (https://github.com/TooTallNate/Java-WebSocket) to send data over websockets. Change-Id: I2bda3d0b988bef7883f9b6829eeb5b7ae8075f27 Signed-off-by: Skyler Grey <skyler.grey@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151171 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
This commit is contained in:
parent
cb72f56977
commit
8e246331f6
27 changed files with 1792 additions and 1 deletions
|
@ -136,6 +136,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S
|
|||
$(call fetch_Optional,HYPHEN,HYPHEN_TARBALL) \
|
||||
$(call fetch_Optional,ICU,ICU_TARBALL) \
|
||||
$(call fetch_Optional,ICU,ICU_DATA_TARBALL) \
|
||||
$(call fetch_Optional,JAVA_WEBSOCKET,JAVA_WEBSOCKET_TARBALL) \
|
||||
$(call fetch_Optional,JFREEREPORT,JFREEREPORT_FLOW_ENGINE_TARBALL) \
|
||||
$(call fetch_Optional,JFREEREPORT,JFREEREPORT_FLUTE_TARBALL) \
|
||||
$(call fetch_Optional,JFREEREPORT,JFREEREPORT_LIBBASE_TARBALL) \
|
||||
|
|
|
@ -3915,6 +3915,17 @@ endef
|
|||
|
||||
endif # SYSTEM_JFREEREPORT
|
||||
|
||||
# no known distro packaged Java-Websocket at present
|
||||
|
||||
ifeq ($(ENABLE_JAVA),TRUE)
|
||||
$(eval $(call gb_Helper_register_jars_for_install,URE,ure, \
|
||||
java_websocket \
|
||||
))
|
||||
endif
|
||||
|
||||
define gb_Jar__use_java_websocket
|
||||
$(call gb_Jar_use_jar,$(1),java_websocket)
|
||||
endef
|
||||
|
||||
# Executables
|
||||
|
||||
|
|
11
configure.ac
11
configure.ac
|
@ -12690,6 +12690,17 @@ AC_SUBST(LIBASSUAN_LIBS)
|
|||
AC_SUBST(GPGMEPP_CFLAGS)
|
||||
AC_SUBST(GPGMEPP_LIBS)
|
||||
|
||||
AC_MSG_CHECKING([whether to build Java Websocket for the UNO remote websocket client])
|
||||
if test "$with_java" != "no"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
ENABLE_JAVA_WEBSOCKET=TRUE
|
||||
BUILD_TYPE="$BUILD_TYPE JAVA_WEBSOCKET"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
ENABLE_JAVA_WEBSOCKET=
|
||||
fi
|
||||
AC_SUBST(ENABLE_JAVA_WEBSOCKET)
|
||||
|
||||
AC_MSG_CHECKING([whether to build the Wiki Publisher extension])
|
||||
if test "x$enable_ext_wiki_publisher" = "xyes" -a "x$enable_extension_integration" != "xno" -a "$with_java" != "no"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
|
|
|
@ -3681,10 +3681,12 @@ void DesktopLOKTest::testABI()
|
|||
CPPUNIT_ASSERT_EQUAL(classOffset(15), offsetof(struct _LibreOfficeKitClass, dumpState));
|
||||
CPPUNIT_ASSERT_EQUAL(classOffset(16), offsetof(struct _LibreOfficeKitClass, extractRequest));
|
||||
CPPUNIT_ASSERT_EQUAL(classOffset(17), offsetof(struct _LibreOfficeKitClass, trimMemory));
|
||||
CPPUNIT_ASSERT_EQUAL(classOffset(18), offsetof(struct _LibreOfficeKitClass, startURP));
|
||||
CPPUNIT_ASSERT_EQUAL(classOffset(19), offsetof(struct _LibreOfficeKitClass, stopURP));
|
||||
|
||||
// When extending LibreOfficeKit with a new function pointer, add new assert for the offsetof the
|
||||
// new function pointer and bump this assert for the size of the class.
|
||||
CPPUNIT_ASSERT_EQUAL(classOffset(18), sizeof(struct _LibreOfficeKitClass));
|
||||
CPPUNIT_ASSERT_EQUAL(classOffset(20), sizeof(struct _LibreOfficeKitClass));
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(documentClassOffset(0), offsetof(struct _LibreOfficeKitDocumentClass, destroy));
|
||||
CPPUNIT_ASSERT_EQUAL(documentClassOffset(1), offsetof(struct _LibreOfficeKitDocumentClass, saveAs));
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
#include <queue>
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -86,6 +87,7 @@
|
|||
#include <comphelper/servicehelper.hxx>
|
||||
#include <comphelper/sequenceashashmap.hxx>
|
||||
|
||||
#include <com/sun/star/connection/XConnection.hpp>
|
||||
#include <com/sun/star/document/MacroExecMode.hpp>
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
#include <com/sun/star/container/XNameAccess.hpp>
|
||||
|
@ -108,6 +110,10 @@
|
|||
#include <com/sun/star/text/TextContentAnchorType.hpp>
|
||||
#include <com/sun/star/document/XRedlinesSupplier.hpp>
|
||||
#include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
|
||||
#include <com/sun/star/bridge/BridgeFactory.hpp>
|
||||
#include <com/sun/star/bridge/XBridgeFactory.hpp>
|
||||
#include <com/sun/star/bridge/XBridge.hpp>
|
||||
#include <com/sun/star/uno/XNamingService.hpp>
|
||||
|
||||
#include <com/sun/star/xml/crypto/SEInitializer.hpp>
|
||||
#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
|
||||
|
@ -121,6 +127,7 @@
|
|||
#include <com/sun/star/i18n/LocaleCalendar2.hpp>
|
||||
#include <com/sun/star/i18n/ScriptType.hpp>
|
||||
#include <com/sun/star/lang/DisposedException.hpp>
|
||||
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||||
|
||||
#include <editeng/flstitem.hxx>
|
||||
#ifdef IOS
|
||||
|
@ -228,6 +235,9 @@ using namespace css;
|
|||
using namespace vcl;
|
||||
using namespace desktop;
|
||||
using namespace utl;
|
||||
using namespace bridge;
|
||||
using namespace uno;
|
||||
using namespace lang;
|
||||
|
||||
static LibLibreOffice_Impl *gImpl = nullptr;
|
||||
static bool lok_preinit_2_called = false;
|
||||
|
@ -2567,6 +2577,13 @@ static char* lo_extractRequest(LibreOfficeKit* pThis,
|
|||
|
||||
static void lo_trimMemory(LibreOfficeKit* pThis, int nTarget);
|
||||
|
||||
static int
|
||||
lo_startURP(LibreOfficeKit* pThis, void* pReceiveURPFromLOContext, void** pSendURPToLOContext,
|
||||
int (*fnReceiveURPFromLO)(void* pContext, const signed char* pBuffer, int nLen),
|
||||
int (**pfnSendURPToLO)(void* pContext, const signed char* pBuffer, int nLen));
|
||||
|
||||
static void lo_stopURP(LibreOfficeKit* pThis, void* pSendURPToLOContext);
|
||||
|
||||
static void lo_runLoop(LibreOfficeKit* pThis,
|
||||
LibreOfficeKitPollCallback pPollCallback,
|
||||
LibreOfficeKitWakeCallback pWakeCallback,
|
||||
|
@ -2609,6 +2626,8 @@ LibLibreOffice_Impl::LibLibreOffice_Impl()
|
|||
m_pOfficeClass->dumpState = lo_dumpState;
|
||||
m_pOfficeClass->extractRequest = lo_extractRequest;
|
||||
m_pOfficeClass->trimMemory = lo_trimMemory;
|
||||
m_pOfficeClass->startURP = lo_startURP;
|
||||
m_pOfficeClass->stopURP = lo_stopURP;
|
||||
|
||||
gOfficeClass = m_pOfficeClass;
|
||||
}
|
||||
|
@ -3160,6 +3179,214 @@ static void lo_trimMemory(LibreOfficeKit* /* pThis */, int nTarget)
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class FunctionBasedURPInstanceProvider
|
||||
: public ::cppu::WeakImplHelper<css::bridge::XInstanceProvider>
|
||||
{
|
||||
private:
|
||||
css::uno::Reference<css::uno::XComponentContext> m_rContext;
|
||||
|
||||
public:
|
||||
FunctionBasedURPInstanceProvider(
|
||||
const css::uno::Reference<css::uno::XComponentContext>& rxContext);
|
||||
|
||||
// XInstanceProvider
|
||||
virtual css::uno::Reference<css::uno::XInterface>
|
||||
SAL_CALL getInstance(const OUString& aName) override;
|
||||
};
|
||||
|
||||
// InstanceProvider
|
||||
FunctionBasedURPInstanceProvider::FunctionBasedURPInstanceProvider(
|
||||
const Reference<XComponentContext>& rxContext)
|
||||
: m_rContext(rxContext)
|
||||
{
|
||||
}
|
||||
|
||||
Reference<XInterface> FunctionBasedURPInstanceProvider::getInstance(const OUString& aName)
|
||||
{
|
||||
Reference<XInterface> rInstance;
|
||||
|
||||
if (aName == "StarOffice.ServiceManager")
|
||||
{
|
||||
rInstance.set(m_rContext->getServiceManager());
|
||||
}
|
||||
else if (aName == "StarOffice.ComponentContext")
|
||||
{
|
||||
rInstance = m_rContext;
|
||||
}
|
||||
else if (aName == "StarOffice.NamingService")
|
||||
{
|
||||
Reference<XNamingService> rNamingService(
|
||||
m_rContext->getServiceManager()->createInstanceWithContext(
|
||||
"com.sun.star.uno.NamingService", m_rContext),
|
||||
UNO_QUERY);
|
||||
if (rNamingService.is())
|
||||
{
|
||||
rNamingService->registerObject("StarOffice.ServiceManager",
|
||||
m_rContext->getServiceManager());
|
||||
rNamingService->registerObject("StarOffice.ComponentContext", m_rContext);
|
||||
rInstance = rNamingService;
|
||||
}
|
||||
}
|
||||
return rInstance;
|
||||
}
|
||||
|
||||
class FunctionBasedURPConnection : public cppu::WeakImplHelper<css::connection::XConnection>
|
||||
{
|
||||
public:
|
||||
explicit FunctionBasedURPConnection(void*, int (*)(void* pContext, const signed char* pBuffer,
|
||||
int nLen));
|
||||
~FunctionBasedURPConnection();
|
||||
|
||||
// These overridden member functions use "read" and "write" from the point of view of LO,
|
||||
// i.e. the opposite to how startURP() uses them.
|
||||
virtual sal_Int32 SAL_CALL read(Sequence<sal_Int8>& aReadBytes,
|
||||
sal_Int32 nBytesToRead) override;
|
||||
virtual void SAL_CALL write(const Sequence<sal_Int8>& aData) override;
|
||||
virtual void SAL_CALL flush() override;
|
||||
virtual void SAL_CALL close() override;
|
||||
virtual OUString SAL_CALL getDescription() override;
|
||||
void setBridge(Reference<XBridge>);
|
||||
int addClientURPToBuffer(const signed char* pBuffer, int nLen);
|
||||
void* getContext();
|
||||
inline static int g_connectionCount = 0;
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::deque<signed char>> m_pBuffer;
|
||||
void* m_pRecieveFromLOContext;
|
||||
int (*m_fnReceiveURPFromLO)(void* pContext, const signed char* pBuffer, int nLen);
|
||||
Reference<XBridge> m_URPBridge;
|
||||
std::atomic<bool> m_closed = false;
|
||||
std::condition_variable m_URPInBuffer;
|
||||
std::mutex m_bufferMutex;
|
||||
};
|
||||
|
||||
FunctionBasedURPConnection::FunctionBasedURPConnection(
|
||||
void* pRecieveFromLOContext,
|
||||
int (*fnRecieveFromLO)(void* pContext, const signed char* pBuffer, int nLen))
|
||||
: m_pBuffer(std::make_shared<std::deque<signed char>>())
|
||||
, m_pRecieveFromLOContext(pRecieveFromLOContext)
|
||||
, m_fnReceiveURPFromLO(fnRecieveFromLO)
|
||||
{
|
||||
g_connectionCount++;
|
||||
}
|
||||
|
||||
FunctionBasedURPConnection::~FunctionBasedURPConnection()
|
||||
{
|
||||
Reference<XComponent> xComp(m_URPBridge, UNO_QUERY_THROW);
|
||||
xComp->dispose(); // TODO: check this doesn't deadlock
|
||||
}
|
||||
|
||||
int sendURPToLO(void* pContext /* FunctionBasedURPConnection* */, const signed char* pBuffer,
|
||||
int nLen)
|
||||
{
|
||||
return static_cast<FunctionBasedURPConnection*>(pContext)->addClientURPToBuffer(pBuffer, nLen);
|
||||
}
|
||||
|
||||
int FunctionBasedURPConnection::addClientURPToBuffer(const signed char* pBuffer, int nLen)
|
||||
{
|
||||
{
|
||||
std::scoped_lock lock(m_bufferMutex);
|
||||
|
||||
if (m_closed)
|
||||
{
|
||||
// We can't write URP to a closed connection
|
||||
SAL_WARN("lok.urp", "A client attempted to write URP to a closed "
|
||||
"FunctionBasedURPConnection... ignoring");
|
||||
return 0;
|
||||
}
|
||||
m_pBuffer->insert(m_pBuffer->end(), pBuffer, pBuffer + nLen);
|
||||
}
|
||||
m_URPInBuffer.notify_one();
|
||||
return nLen;
|
||||
}
|
||||
|
||||
void* FunctionBasedURPConnection::getContext() { return this; }
|
||||
|
||||
sal_Int32 FunctionBasedURPConnection::read(Sequence<sal_Int8>& aReadBytes, sal_Int32 nBytesToRead)
|
||||
{
|
||||
if (aReadBytes.getLength() != nBytesToRead)
|
||||
{
|
||||
aReadBytes.realloc(nBytesToRead);
|
||||
}
|
||||
|
||||
sal_Int8* result = aReadBytes.getArray();
|
||||
// As with osl::StreamPipe, we must always read nBytesToRead...
|
||||
|
||||
{
|
||||
std::unique_lock lock(m_bufferMutex);
|
||||
|
||||
if (nBytesToRead < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_URPInBuffer.wait(
|
||||
lock, [this, nBytesToRead] { return static_cast<sal_Int32>(m_pBuffer->size()) >= nBytesToRead; });
|
||||
|
||||
std::copy(m_pBuffer->begin(), m_pBuffer->begin() + nBytesToRead, result);
|
||||
m_pBuffer->erase(m_pBuffer->begin(), m_pBuffer->begin() + nBytesToRead);
|
||||
}
|
||||
|
||||
return nBytesToRead;
|
||||
}
|
||||
|
||||
void FunctionBasedURPConnection::write(const Sequence<sal_Int8>& aData)
|
||||
{
|
||||
m_fnReceiveURPFromLO(m_pRecieveFromLOContext, aData.getConstArray(), aData.getLength());
|
||||
}
|
||||
|
||||
void FunctionBasedURPConnection::flush() {}
|
||||
|
||||
void FunctionBasedURPConnection::close()
|
||||
{
|
||||
SAL_INFO("lok.urp", "Requested to close FunctionBasedURPConnection");
|
||||
m_closed = true;
|
||||
}
|
||||
|
||||
OUString FunctionBasedURPConnection::getDescription() { return ""; }
|
||||
|
||||
void FunctionBasedURPConnection::setBridge(Reference<XBridge> xBridge) { m_URPBridge = xBridge; }
|
||||
}
|
||||
|
||||
static int
|
||||
lo_startURP(LibreOfficeKit* /* pThis */, void* pRecieveFromLOContext, void** ppSendToLOContext,
|
||||
int (*fnReceiveURPFromLO)(void* pContext, const signed char* pBuffer, int nLen),
|
||||
int (**pfnSendURPToLO)(void* pContext, const signed char* pBuffer, int nLen))
|
||||
{
|
||||
// Here we will roughly do what desktop LO does when one passes a command-line switch like
|
||||
// --accept=socket,port=nnnn;urp;StarOffice.ServiceManager. Except that no listening socket will
|
||||
// be created. The communication to the URP will be through the fnReceiveURPFromLO and pfnSendURPToLO functions.
|
||||
|
||||
rtl::Reference<FunctionBasedURPConnection> connection(
|
||||
new FunctionBasedURPConnection(pRecieveFromLOContext, fnReceiveURPFromLO));
|
||||
|
||||
*pfnSendURPToLO = sendURPToLO;
|
||||
*ppSendToLOContext = connection->getContext();
|
||||
|
||||
Reference<XBridgeFactory> xBridgeFactory = css::bridge::BridgeFactory::create(xContext);
|
||||
|
||||
Reference<XInstanceProvider> xInstanceProvider(new FunctionBasedURPInstanceProvider(xContext));
|
||||
|
||||
Reference<XBridge> xBridge(xBridgeFactory->createBridge(
|
||||
"functionurp" + OUString::number(FunctionBasedURPConnection::g_connectionCount), "urp",
|
||||
connection, xInstanceProvider));
|
||||
|
||||
connection->setBridge(std::move(xBridge));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a function based URP connection that you started with lo_startURP above
|
||||
*
|
||||
* @param pSendToLOContext a pointer to the context you got back using your ppSendToLOContext before */
|
||||
static void lo_stopURP(LibreOfficeKit* /* pThis */,
|
||||
void* pSendToLOContext /* FunctionBasedURPConnection* */)
|
||||
{
|
||||
static_cast<FunctionBasedURPConnection*>(pSendToLOContext)->close();
|
||||
}
|
||||
|
||||
static void lo_registerCallback (LibreOfficeKit* pThis,
|
||||
LibreOfficeKitCallback pCallback,
|
||||
void* pData)
|
||||
|
|
|
@ -249,6 +249,11 @@ ICU_DATA_TARBALL := icu4c-73_2-data.zip
|
|||
# three static lines
|
||||
# so that git cherry-pick
|
||||
# will not run into conflicts
|
||||
JAVA_WEBSOCKET_SHA256SUM := a6828b35d1f938fee2335945f3d3c563cbbfa58ce7eb0bf72778d0fa7a550720
|
||||
JAVA_WEBSOCKET_TARBALL := Java-WebSocket-1.5.4.tar.gz
|
||||
# three static lines
|
||||
# so that git cherry-pick
|
||||
# will not run into conflicts
|
||||
JFREEREPORT_FLOW_ENGINE_SHA256SUM := 233f66e8d25c5dd971716d4200203a612a407649686ef3b52075d04b4c9df0dd
|
||||
JFREEREPORT_FLOW_ENGINE_TARBALL := ba2930200c9f019c2d93a8c88c651a0f-flow-engine-0.9.4.zip
|
||||
JFREEREPORT_FLUTE_SHA256SUM := 1b5b24f7bc543c0362b667692f78db8bab4ed6dafc6172f104d0bd3757d8a133
|
||||
|
|
1
external/Module_external.mk
vendored
1
external/Module_external.mk
vendored
|
@ -50,6 +50,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\
|
|||
$(call gb_Helper_optional,HUNSPELL,hunspell) \
|
||||
$(call gb_Helper_optional,HYPHEN,hyphen) \
|
||||
$(call gb_Helper_optional,ICU,icu) \
|
||||
$(call gb_Helper_optional,JAVA_WEBSOCKET,java_websocket) \
|
||||
$(call gb_Helper_optional,JFREEREPORT,jfreereport) \
|
||||
$(call gb_Helper_optional,LIBJPEG_TURBO,libjpeg-turbo) \
|
||||
$(call gb_Helper_optional,LCMS2,lcms2) \
|
||||
|
|
16
external/java_websocket/ExternalPackage_java_websocket.mk
vendored
Normal file
16
external/java_websocket/ExternalPackage_java_websocket.mk
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_ExternalPackage_ExternalPackage,java_websocket_project,java_websocket))
|
||||
|
||||
$(eval $(call gb_ExternalPackage_use_external_project,java_websocket_project,java_websocket))
|
||||
|
||||
$(eval $(call gb_ExternalPackage_add_file,java_websocket_project,$(LIBO_SHARE_JAVA_FOLDER)/java_websocket.jar,dist/java_websocket.jar))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
31
external/java_websocket/ExternalProject_java_websocket.mk
vendored
Normal file
31
external/java_websocket/ExternalProject_java_websocket.mk
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_ExternalProject_ExternalProject,java_websocket))
|
||||
|
||||
$(eval $(call gb_ExternalProject_register_targets,java_websocket,\
|
||||
build \
|
||||
))
|
||||
|
||||
$(call gb_ExternalProject_get_state_target,java_websocket,build) :
|
||||
$(call gb_Trace_StartRange,java_websocket,EXTERNAL)
|
||||
$(call gb_ExternalProject_run,build,\
|
||||
JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \
|
||||
$(ICECREAM_RUN) "$(ANT)" \
|
||||
$(if $(verbose),-v,-q) \
|
||||
-f build.xml \
|
||||
-Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \
|
||||
-Dant.build.javac.source=$(JAVA_SOURCE_VER) \
|
||||
-Dant.build.javac.target=$(JAVA_TARGET_VER) \
|
||||
$(if $(debug),-Dbuild.debug="on") \
|
||||
jar \
|
||||
)
|
||||
$(call gb_Trace_EndRange,java_websocket,EXTERNAL)
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
7
external/java_websocket/Makefile
vendored
Normal file
7
external/java_websocket/Makefile
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
|
||||
module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
include $(module_directory)/../../solenv/gbuild/partial_build.mk
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
18
external/java_websocket/Module_java_websocket.mk
vendored
Normal file
18
external/java_websocket/Module_java_websocket.mk
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_Module_Module,java_websocket))
|
||||
|
||||
$(eval $(call gb_Module_add_targets,java_websocket,\
|
||||
ExternalPackage_java_websocket \
|
||||
ExternalProject_java_websocket \
|
||||
UnpackedTarball_java_websocket \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
3
external/java_websocket/README
vendored
Normal file
3
external/java_websocket/README
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
Java WebSocket Implmentation from [https://github.com/TooTallNate/Java-WebSocket].
|
||||
|
||||
To send data over websockets, enabling uno over websockets.
|
21
external/java_websocket/UnpackedTarball_java_websocket.mk
vendored
Normal file
21
external/java_websocket/UnpackedTarball_java_websocket.mk
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_UnpackedTarball_UnpackedTarball,java_websocket))
|
||||
|
||||
$(eval $(call gb_UnpackedTarball_set_tarball,java_websocket,$(JAVA_WEBSOCKET_TARBALL),,java_websocket))
|
||||
|
||||
$(eval $(call gb_UnpackedTarball_set_patchlevel,java_websocket,1))
|
||||
|
||||
$(eval $(call gb_UnpackedTarball_add_patches,java_websocket,\
|
||||
external/java_websocket/patches/ant-build.patch \
|
||||
external/java_websocket/patches/no-slf4j.patch \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
26
external/java_websocket/patches/ant-build.patch
vendored
Normal file
26
external/java_websocket/patches/ant-build.patch
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ b/build.xml 2023-08-30 11:43:05.152647141 +0100
|
||||
@@ -0,0 +1,23 @@
|
||||
+<project default="all">
|
||||
+ <target name="all" depends="jar" />
|
||||
+
|
||||
+ <target name="compile">
|
||||
+ <mkdir dir="build/classes" />
|
||||
+ <javac includeantruntime="false" srcdir="src/main/java"
|
||||
+ destdir="build/classes">
|
||||
+ </javac>
|
||||
+ </target>
|
||||
+
|
||||
+ <target name="jar" depends="compile">
|
||||
+ <mkdir dir="dist"/>
|
||||
+ <jar destfile="dist/java_websocket.jar">
|
||||
+ <fileset dir="build/classes" includes="**/*.class" />
|
||||
+ </jar>
|
||||
+ </target>
|
||||
+
|
||||
+ <target name="clean">
|
||||
+ <delete dir="build" />
|
||||
+ <delete dir="dist" />
|
||||
+ </target>
|
||||
+
|
||||
+</project>
|
748
external/java_websocket/patches/no-slf4j.patch
vendored
Normal file
748
external/java_websocket/patches/no-slf4j.patch
vendored
Normal file
|
@ -0,0 +1,748 @@
|
|||
diff -ru a/src/main/java/org/java_websocket/AbstractWebSocket.java b/src/main/java/org/java_websocket/AbstractWebSocket.java
|
||||
--- a/src/main/java/org/java_websocket/AbstractWebSocket.java 2023-07-20 21:24:05.000000000 +0100
|
||||
+++ b/src/main/java/org/java_websocket/AbstractWebSocket.java 2023-08-30 12:06:11.004719499 +0100
|
||||
@@ -33,9 +33,7 @@
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.java_websocket.framing.CloseFrame;
|
||||
import org.java_websocket.util.NamedThreadFactory;
|
||||
-import org.slf4j.Logger;
|
||||
-import org.slf4j.LoggerFactory;
|
||||
-
|
||||
+import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Base class for additional implementations for the server as well as the client
|
||||
@@ -47,7 +45,7 @@
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
- private final Logger log = LoggerFactory.getLogger(AbstractWebSocket.class);
|
||||
+ private final Logger log = Logger.getLogger(AbstractWebSocket.class.getName());
|
||||
|
||||
/**
|
||||
* Attribute which allows you to deactivate the Nagle's algorithm
|
||||
@@ -118,12 +116,12 @@
|
||||
synchronized (syncConnectionLost) {
|
||||
this.connectionLostTimeout = TimeUnit.SECONDS.toNanos(connectionLostTimeout);
|
||||
if (this.connectionLostTimeout <= 0) {
|
||||
- log.trace("Connection lost timer stopped");
|
||||
+ log.fine("Connection lost timer stopped");
|
||||
cancelConnectionLostTimer();
|
||||
return;
|
||||
}
|
||||
if (this.websocketRunning) {
|
||||
- log.trace("Connection lost timer restarted");
|
||||
+ log.fine("Connection lost timer restarted");
|
||||
//Reset all the pings
|
||||
try {
|
||||
ArrayList<WebSocket> connections = new ArrayList<>(getConnections());
|
||||
@@ -135,7 +133,7 @@
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
- log.error("Exception during connection lost restart", e);
|
||||
+ log.severe("Exception during connection lost restart" + " : " + e);
|
||||
}
|
||||
restartConnectionLostTimer();
|
||||
}
|
||||
@@ -151,7 +149,7 @@
|
||||
synchronized (syncConnectionLost) {
|
||||
if (connectionLostCheckerService != null || connectionLostCheckerFuture != null) {
|
||||
this.websocketRunning = false;
|
||||
- log.trace("Connection lost timer stopped");
|
||||
+ log.fine("Connection lost timer stopped");
|
||||
cancelConnectionLostTimer();
|
||||
}
|
||||
}
|
||||
@@ -165,10 +163,10 @@
|
||||
protected void startConnectionLostTimer() {
|
||||
synchronized (syncConnectionLost) {
|
||||
if (this.connectionLostTimeout <= 0) {
|
||||
- log.trace("Connection lost timer deactivated");
|
||||
+ log.fine("Connection lost timer deactivated");
|
||||
return;
|
||||
}
|
||||
- log.trace("Connection lost timer started");
|
||||
+ log.fine("Connection lost timer started");
|
||||
this.websocketRunning = true;
|
||||
restartConnectionLostTimer();
|
||||
}
|
||||
@@ -228,14 +226,14 @@
|
||||
}
|
||||
WebSocketImpl webSocketImpl = (WebSocketImpl) webSocket;
|
||||
if (webSocketImpl.getLastPong() < minimumPongTime) {
|
||||
- log.trace("Closing connection due to no pong received: {}", webSocketImpl);
|
||||
+ log.fine("Closing connection due to no pong received: {}" + " : " + webSocketImpl);
|
||||
webSocketImpl.closeConnection(CloseFrame.ABNORMAL_CLOSE,
|
||||
"The connection was closed because the other endpoint did not respond with a pong in time. For more information check: https://github.com/TooTallNate/Java-WebSocket/wiki/Lost-connection-detection");
|
||||
} else {
|
||||
if (webSocketImpl.isOpen()) {
|
||||
webSocketImpl.sendPing();
|
||||
} else {
|
||||
- log.trace("Trying to ping a non open connection: {}", webSocketImpl);
|
||||
+ log.fine("Trying to ping a non open connection: {}" + " : " + webSocketImpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff -ru a/src/main/java/org/java_websocket/drafts/Draft_6455.java b/src/main/java/org/java_websocket/drafts/Draft_6455.java
|
||||
--- a/src/main/java/org/java_websocket/drafts/Draft_6455.java 2023-07-20 21:24:05.000000000 +0100
|
||||
+++ b/src/main/java/org/java_websocket/drafts/Draft_6455.java 2023-08-30 12:16:03.534083539 +0100
|
||||
@@ -66,8 +66,8 @@
|
||||
import org.java_websocket.protocols.Protocol;
|
||||
import org.java_websocket.util.Base64;
|
||||
import org.java_websocket.util.Charsetfunctions;
|
||||
-import org.slf4j.Logger;
|
||||
-import org.slf4j.LoggerFactory;
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Implementation for the RFC 6455 websocket protocol This is the recommended class for your
|
||||
@@ -110,7 +110,7 @@
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
- private final Logger log = LoggerFactory.getLogger(Draft_6455.class);
|
||||
+ private final Logger log = Logger.getLogger(Draft_6455.class.getName());
|
||||
|
||||
/**
|
||||
* Attribute for the used extension in this draft
|
||||
@@ -263,7 +263,7 @@
|
||||
throws InvalidHandshakeException {
|
||||
int v = readVersion(handshakedata);
|
||||
if (v != 13) {
|
||||
- log.trace("acceptHandshakeAsServer - Wrong websocket version.");
|
||||
+ log.fine("acceptHandshakeAsServer - Wrong websocket version.");
|
||||
return HandshakeState.NOT_MATCHED;
|
||||
}
|
||||
HandshakeState extensionState = HandshakeState.NOT_MATCHED;
|
||||
@@ -272,7 +272,7 @@
|
||||
if (knownExtension.acceptProvidedExtensionAsServer(requestedExtension)) {
|
||||
negotiatedExtension = knownExtension;
|
||||
extensionState = HandshakeState.MATCHED;
|
||||
- log.trace("acceptHandshakeAsServer - Matching extension found: {}", negotiatedExtension);
|
||||
+ log.fine("acceptHandshakeAsServer - Matching extension found: {}" + " : " + negotiatedExtension);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -281,7 +281,7 @@
|
||||
if (protocolState == HandshakeState.MATCHED && extensionState == HandshakeState.MATCHED) {
|
||||
return HandshakeState.MATCHED;
|
||||
}
|
||||
- log.trace("acceptHandshakeAsServer - No matching extension or protocol found.");
|
||||
+ log.fine("acceptHandshakeAsServer - No matching extension or protocol found.");
|
||||
return HandshakeState.NOT_MATCHED;
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
for (IProtocol knownProtocol : knownProtocols) {
|
||||
if (knownProtocol.acceptProvidedProtocol(requestedProtocol)) {
|
||||
protocol = knownProtocol;
|
||||
- log.trace("acceptHandshake - Matching protocol found: {}", protocol);
|
||||
+ log.fine("acceptHandshake - Matching protocol found: {}" + " : " + protocol);
|
||||
return HandshakeState.MATCHED;
|
||||
}
|
||||
}
|
||||
@@ -306,12 +306,12 @@
|
||||
public HandshakeState acceptHandshakeAsClient(ClientHandshake request, ServerHandshake response)
|
||||
throws InvalidHandshakeException {
|
||||
if (!basicAccept(response)) {
|
||||
- log.trace("acceptHandshakeAsClient - Missing/wrong upgrade or connection in handshake.");
|
||||
+ log.fine("acceptHandshakeAsClient - Missing/wrong upgrade or connection in handshake.");
|
||||
return HandshakeState.NOT_MATCHED;
|
||||
}
|
||||
if (!request.hasFieldValue(SEC_WEB_SOCKET_KEY) || !response
|
||||
.hasFieldValue(SEC_WEB_SOCKET_ACCEPT)) {
|
||||
- log.trace("acceptHandshakeAsClient - Missing Sec-WebSocket-Key or Sec-WebSocket-Accept");
|
||||
+ log.fine("acceptHandshakeAsClient - Missing Sec-WebSocket-Key or Sec-WebSocket-Accept");
|
||||
return HandshakeState.NOT_MATCHED;
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
seckeyChallenge = generateFinalKey(seckeyChallenge);
|
||||
|
||||
if (!seckeyChallenge.equals(seckeyAnswer)) {
|
||||
- log.trace("acceptHandshakeAsClient - Wrong key for Sec-WebSocket-Key.");
|
||||
+ log.fine("acceptHandshakeAsClient - Wrong key for Sec-WebSocket-Key.");
|
||||
return HandshakeState.NOT_MATCHED;
|
||||
}
|
||||
HandshakeState extensionState = HandshakeState.NOT_MATCHED;
|
||||
@@ -329,7 +329,7 @@
|
||||
if (knownExtension.acceptProvidedExtensionAsClient(requestedExtension)) {
|
||||
negotiatedExtension = knownExtension;
|
||||
extensionState = HandshakeState.MATCHED;
|
||||
- log.trace("acceptHandshakeAsClient - Matching extension found: {}", negotiatedExtension);
|
||||
+ log.fine("acceptHandshakeAsClient - Matching extension found: {}" + " : " + negotiatedExtension);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -338,7 +338,7 @@
|
||||
if (protocolState == HandshakeState.MATCHED && extensionState == HandshakeState.MATCHED) {
|
||||
return HandshakeState.MATCHED;
|
||||
}
|
||||
- log.trace("acceptHandshakeAsClient - No matching extension or protocol found.");
|
||||
+ log.fine("acceptHandshakeAsClient - No matching extension or protocol found.");
|
||||
return HandshakeState.NOT_MATCHED;
|
||||
}
|
||||
|
||||
@@ -467,8 +467,8 @@
|
||||
@Override
|
||||
public ByteBuffer createBinaryFrame(Framedata framedata) {
|
||||
getExtension().encodeFrame(framedata);
|
||||
- if (log.isTraceEnabled()) {
|
||||
- log.trace("afterEnconding({}): {}", framedata.getPayloadData().remaining(),
|
||||
+ if (log.isLoggable(Level.FINE)) {
|
||||
+ log.fine("afterEnconding({}): {}" + " : " + framedata.getPayloadData().remaining() + " : " +
|
||||
(framedata.getPayloadData().remaining() > 1000 ? "too big to display"
|
||||
: new String(framedata.getPayloadData().array())));
|
||||
}
|
||||
@@ -587,8 +587,8 @@
|
||||
}
|
||||
currentDecodingExtension.isFrameValid(frame);
|
||||
currentDecodingExtension.decodeFrame(frame);
|
||||
- if (log.isTraceEnabled()) {
|
||||
- log.trace("afterDecoding({}): {}", frame.getPayloadData().remaining(),
|
||||
+ if (log.isLoggable(Level.FINE)) {
|
||||
+ log.fine("afterDecoding({}): {}" + " : " + frame.getPayloadData().remaining() + " : " +
|
||||
(frame.getPayloadData().remaining() > 1000 ? "too big to display"
|
||||
: new String(frame.getPayloadData().array())));
|
||||
}
|
||||
@@ -615,7 +615,7 @@
|
||||
int payloadlength = oldPayloadlength;
|
||||
int realpacketsize = oldRealpacketsize;
|
||||
if (optcode == Opcode.PING || optcode == Opcode.PONG || optcode == Opcode.CLOSING) {
|
||||
- log.trace("Invalid frame: more than 125 octets");
|
||||
+ log.fine("Invalid frame: more than 125 octets");
|
||||
throw new InvalidFrameException("more than 125 octets");
|
||||
}
|
||||
if (payloadlength == 126) {
|
||||
@@ -647,15 +647,15 @@
|
||||
*/
|
||||
private void translateSingleFrameCheckLengthLimit(long length) throws LimitExceededException {
|
||||
if (length > Integer.MAX_VALUE) {
|
||||
- log.trace("Limit exedeed: Payloadsize is to big...");
|
||||
+ log.fine("Limit exedeed: Payloadsize is to big...");
|
||||
throw new LimitExceededException("Payloadsize is to big...");
|
||||
}
|
||||
if (length > maxFrameSize) {
|
||||
- log.trace("Payload limit reached. Allowed: {} Current: {}", maxFrameSize, length);
|
||||
+ log.fine("Payload limit reached. Allowed: {} Current: {}" + " : " + maxFrameSize + " : " + length);
|
||||
throw new LimitExceededException("Payload limit reached.", maxFrameSize);
|
||||
}
|
||||
if (length < 0) {
|
||||
- log.trace("Limit underflow: Payloadsize is to little...");
|
||||
+ log.fine("Limit underflow: Payloadsize is to little...");
|
||||
throw new LimitExceededException("Payloadsize is to little...");
|
||||
}
|
||||
}
|
||||
@@ -670,7 +670,7 @@
|
||||
private void translateSingleFrameCheckPacketSize(int maxpacketsize, int realpacketsize)
|
||||
throws IncompleteException {
|
||||
if (maxpacketsize < realpacketsize) {
|
||||
- log.trace("Incomplete frame: maxpacketsize < realpacketsize");
|
||||
+ log.fine("Incomplete frame: maxpacketsize < realpacketsize");
|
||||
throw new IncompleteException(realpacketsize);
|
||||
}
|
||||
}
|
||||
@@ -903,7 +903,7 @@
|
||||
} else if (!frame.isFin() || curop == Opcode.CONTINUOUS) {
|
||||
processFrameContinuousAndNonFin(webSocketImpl, frame, curop);
|
||||
} else if (currentContinuousFrame != null) {
|
||||
- log.error("Protocol error: Continuous frame sequence not completed.");
|
||||
+ log.severe("Protocol error: Continuous frame sequence not completed.");
|
||||
throw new InvalidDataException(CloseFrame.PROTOCOL_ERROR,
|
||||
"Continuous frame sequence not completed.");
|
||||
} else if (curop == Opcode.TEXT) {
|
||||
@@ -911,7 +911,7 @@
|
||||
} else if (curop == Opcode.BINARY) {
|
||||
processFrameBinary(webSocketImpl, frame);
|
||||
} else {
|
||||
- log.error("non control or continious frame expected");
|
||||
+ log.severe("non control or continious frame expected");
|
||||
throw new InvalidDataException(CloseFrame.PROTOCOL_ERROR,
|
||||
"non control or continious frame expected");
|
||||
}
|
||||
@@ -932,13 +932,13 @@
|
||||
} else if (frame.isFin()) {
|
||||
processFrameIsFin(webSocketImpl, frame);
|
||||
} else if (currentContinuousFrame == null) {
|
||||
- log.error("Protocol error: Continuous frame sequence was not started.");
|
||||
+ log.severe("Protocol error: Continuous frame sequence was not started.");
|
||||
throw new InvalidDataException(CloseFrame.PROTOCOL_ERROR,
|
||||
"Continuous frame sequence was not started.");
|
||||
}
|
||||
//Check if the whole payload is valid utf8, when the opcode indicates a text
|
||||
if (curop == Opcode.TEXT && !Charsetfunctions.isValidUTF8(frame.getPayloadData())) {
|
||||
- log.error("Protocol error: Payload is not UTF8");
|
||||
+ log.severe("Protocol error: Payload is not UTF8");
|
||||
throw new InvalidDataException(CloseFrame.NO_UTF8);
|
||||
}
|
||||
//Checking if the current continuous frame contains a correct payload with the other frames combined
|
||||
@@ -969,7 +969,7 @@
|
||||
* @param e the runtime exception
|
||||
*/
|
||||
private void logRuntimeException(WebSocketImpl webSocketImpl, RuntimeException e) {
|
||||
- log.error("Runtime exception during onWebsocketMessage", e);
|
||||
+ log.severe("Runtime exception during onWebsocketMessage" + " : " + e);
|
||||
webSocketImpl.getWebSocketListener().onWebsocketError(webSocketImpl, e);
|
||||
}
|
||||
|
||||
@@ -999,7 +999,7 @@
|
||||
private void processFrameIsFin(WebSocketImpl webSocketImpl, Framedata frame)
|
||||
throws InvalidDataException {
|
||||
if (currentContinuousFrame == null) {
|
||||
- log.trace("Protocol error: Previous continuous frame sequence not completed.");
|
||||
+ log.fine("Protocol error: Previous continuous frame sequence not completed.");
|
||||
throw new InvalidDataException(CloseFrame.PROTOCOL_ERROR,
|
||||
"Continuous frame sequence was not started.");
|
||||
}
|
||||
@@ -1036,7 +1036,7 @@
|
||||
*/
|
||||
private void processFrameIsNotFin(Framedata frame) throws InvalidDataException {
|
||||
if (currentContinuousFrame != null) {
|
||||
- log.trace("Protocol error: Previous continuous frame sequence not completed.");
|
||||
+ log.fine("Protocol error: Previous continuous frame sequence not completed.");
|
||||
throw new InvalidDataException(CloseFrame.PROTOCOL_ERROR,
|
||||
"Previous continuous frame sequence not completed.");
|
||||
}
|
||||
@@ -1102,7 +1102,7 @@
|
||||
long totalSize = getByteBufferListSize();
|
||||
if (totalSize > maxFrameSize) {
|
||||
clearBufferList();
|
||||
- log.trace("Payload limit reached. Allowed: {} Current: {}", maxFrameSize, totalSize);
|
||||
+ log.fine("Payload limit reached. Allowed: {} Current: {}" + " : " + maxFrameSize + " : " + totalSize);
|
||||
throw new LimitExceededException(maxFrameSize);
|
||||
}
|
||||
}
|
||||
diff -ru a/src/main/java/org/java_websocket/server/WebSocketServer.java b/src/main/java/org/java_websocket/server/WebSocketServer.java
|
||||
--- a/src/main/java/org/java_websocket/server/WebSocketServer.java 2023-07-20 21:24:05.000000000 +0100
|
||||
+++ b/src/main/java/org/java_websocket/server/WebSocketServer.java 2023-08-30 12:06:46.372798355 +0100
|
||||
@@ -67,8 +67,7 @@
|
||||
import org.java_websocket.framing.Framedata;
|
||||
import org.java_websocket.handshake.ClientHandshake;
|
||||
import org.java_websocket.handshake.Handshakedata;
|
||||
-import org.slf4j.Logger;
|
||||
-import org.slf4j.LoggerFactory;
|
||||
+import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* <tt>WebSocketServer</tt> is an abstract class that only takes care of the
|
||||
@@ -84,7 +83,7 @@
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
- private final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
|
||||
+ private final Logger log = Logger.getLogger(WebSocketServer.class.getName());
|
||||
|
||||
/**
|
||||
* Holds the list of active WebSocket connections. "Active" means WebSocket handshake is complete
|
||||
@@ -611,7 +610,7 @@
|
||||
try {
|
||||
selector.close();
|
||||
} catch (IOException e) {
|
||||
- log.error("IOException during selector.close", e);
|
||||
+ log.severe("IOException during selector.close" + " : " + e);
|
||||
onError(null, e);
|
||||
}
|
||||
}
|
||||
@@ -619,7 +618,7 @@
|
||||
try {
|
||||
server.close();
|
||||
} catch (IOException e) {
|
||||
- log.error("IOException during server.close", e);
|
||||
+ log.severe("IOException during server.close" + " : " + e);
|
||||
onError(null, e);
|
||||
}
|
||||
}
|
||||
@@ -677,13 +676,13 @@
|
||||
} catch (IOException e) {
|
||||
// there is nothing that must be done here
|
||||
}
|
||||
- log.trace("Connection closed because of exception", ex);
|
||||
+ log.fine("Connection closed because of exception" + " : " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFatal(WebSocket conn, Exception e) {
|
||||
- log.error("Shutdown due to fatal error", e);
|
||||
+ log.severe("Shutdown due to fatal error" + " : " + e);
|
||||
onError(conn, e);
|
||||
|
||||
String causeMessage = e.getCause() != null ? " caused by " + e.getCause().getClass().getName() : "";
|
||||
@@ -692,7 +691,7 @@
|
||||
stop(0, errorMessage);
|
||||
} catch (InterruptedException e1) {
|
||||
Thread.currentThread().interrupt();
|
||||
- log.error("Interrupt during stop", e);
|
||||
+ log.severe("Interrupt during stop" + " : " + e);
|
||||
onError(null, e1);
|
||||
}
|
||||
|
||||
@@ -760,8 +759,8 @@
|
||||
removed = this.connections.remove(ws);
|
||||
} else {
|
||||
//Don't throw an assert error if the ws is not in the list. e.g. when the other endpoint did not send any handshake. see #512
|
||||
- log.trace(
|
||||
- "Removing connection which is not in the connections collection! Possible no handshake received! {}",
|
||||
+ log.fine(
|
||||
+ "Removing connection which is not in the connections collection! Possible no handshake received! {}" + " : " +
|
||||
ws);
|
||||
}
|
||||
}
|
||||
@@ -1065,7 +1064,7 @@
|
||||
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
- log.error("Uncaught exception in thread {}: {}", t.getName(), e);
|
||||
+ log.severe("Uncaught exception in thread {}: {}" + " : " + t.getName() + " : " + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1089,11 +1088,11 @@
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (VirtualMachineError | ThreadDeath | LinkageError e) {
|
||||
- log.error("Got fatal error in worker thread {}", getName());
|
||||
+ log.severe("Got fatal error in worker thread {}" + " : " + getName());
|
||||
Exception exception = new Exception(e);
|
||||
handleFatal(ws, exception);
|
||||
} catch (Throwable e) {
|
||||
- log.error("Uncaught exception in thread {}: {}", getName(), e);
|
||||
+ log.severe("Uncaught exception in thread {}: {}" + " : " + getName() + " : " + e);
|
||||
if (ws != null) {
|
||||
Exception exception = new Exception(e);
|
||||
onWebsocketError(ws, exception);
|
||||
@@ -1113,7 +1112,7 @@
|
||||
try {
|
||||
ws.decode(buf);
|
||||
} catch (Exception e) {
|
||||
- log.error("Error while reading from remote connection", e);
|
||||
+ log.severe("Error while reading from remote connection" + " : " + e);
|
||||
} finally {
|
||||
pushBuffer(buf);
|
||||
}
|
||||
diff -ru a/src/main/java/org/java_websocket/SSLSocketChannel2.java b/src/main/java/org/java_websocket/SSLSocketChannel2.java
|
||||
--- a/src/main/java/org/java_websocket/SSLSocketChannel2.java 2023-07-20 21:24:05.000000000 +0100
|
||||
+++ b/src/main/java/org/java_websocket/SSLSocketChannel2.java 2023-08-30 12:05:33.937636854 +0100
|
||||
@@ -47,8 +47,8 @@
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import org.java_websocket.interfaces.ISSLChannel;
|
||||
-import org.slf4j.Logger;
|
||||
-import org.slf4j.LoggerFactory;
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Implements the relevant portions of the SocketChannel interface with the SSLEngine wrapper.
|
||||
@@ -66,7 +66,7 @@
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
- private final Logger log = LoggerFactory.getLogger(SSLSocketChannel2.class);
|
||||
+ private final Logger log = Logger.getLogger(SSLSocketChannel2.class.getName());
|
||||
|
||||
protected ExecutorService exec;
|
||||
|
||||
@@ -256,13 +256,13 @@
|
||||
inCrypt = ByteBuffer.allocate(netBufferMax);
|
||||
}
|
||||
}
|
||||
- if (inData.remaining() != 0 && log.isTraceEnabled()) {
|
||||
- log.trace(new String(inData.array(), inData.position(), inData.remaining()));
|
||||
+ if (inData.remaining() != 0 && log.isLoggable(Level.FINE)) {
|
||||
+ log.fine(new String(inData.array(), inData.position(), inData.remaining()));
|
||||
}
|
||||
inData.rewind();
|
||||
inData.flip();
|
||||
- if (inCrypt.remaining() != 0 && log.isTraceEnabled()) {
|
||||
- log.trace(new String(inCrypt.array(), inCrypt.position(), inCrypt.remaining()));
|
||||
+ if (inCrypt.remaining() != 0 && log.isLoggable(Level.FINE)) {
|
||||
+ log.fine(new String(inCrypt.array(), inCrypt.position(), inCrypt.remaining()));
|
||||
}
|
||||
inCrypt.rewind();
|
||||
inCrypt.flip();
|
||||
@@ -498,4 +498,4 @@
|
||||
saveCryptData = null;
|
||||
}
|
||||
}
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff -ru a/src/main/java/org/java_websocket/SSLSocketChannel.java b/src/main/java/org/java_websocket/SSLSocketChannel.java
|
||||
--- a/src/main/java/org/java_websocket/SSLSocketChannel.java 2023-07-20 21:24:05.000000000 +0100
|
||||
+++ b/src/main/java/org/java_websocket/SSLSocketChannel.java 2023-08-30 11:55:09.427244528 +0100
|
||||
@@ -39,8 +39,7 @@
|
||||
import javax.net.ssl.SSLSession;
|
||||
import org.java_websocket.interfaces.ISSLChannel;
|
||||
import org.java_websocket.util.ByteBufferUtils;
|
||||
-import org.slf4j.Logger;
|
||||
-import org.slf4j.LoggerFactory;
|
||||
+import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
@@ -70,7 +69,7 @@
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
- private final Logger log = LoggerFactory.getLogger(SSLSocketChannel.class);
|
||||
+ private final Logger log = Logger.getLogger(SSLSocketChannel.class.getName());
|
||||
|
||||
/**
|
||||
* The underlying socket channel
|
||||
@@ -148,7 +147,7 @@
|
||||
try {
|
||||
socketChannel.close();
|
||||
} catch (IOException e) {
|
||||
- log.error("Exception during the closing of the channel", e);
|
||||
+ log.severe("Exception during the closing of the channel" + " : " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,7 +175,7 @@
|
||||
try {
|
||||
result = engine.unwrap(peerNetData, peerAppData);
|
||||
} catch (SSLException e) {
|
||||
- log.error("SSLException during unwrap", e);
|
||||
+ log.severe("SSLException during unwrap" + " : " + e);
|
||||
throw e;
|
||||
}
|
||||
switch (result.getStatus()) {
|
||||
@@ -490,7 +489,7 @@
|
||||
try {
|
||||
engine.closeInbound();
|
||||
} catch (Exception e) {
|
||||
- log.error(
|
||||
+ log.severe(
|
||||
"This engine was forced to close inbound, without having received the proper SSL/TLS close notification message from the peer, due to end of stream.");
|
||||
}
|
||||
closeConnection();
|
||||
@@ -536,4 +535,4 @@
|
||||
public SSLEngine getSSLEngine() {
|
||||
return engine;
|
||||
}
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff -ru a/src/main/java/org/java_websocket/WebSocketImpl.java b/src/main/java/org/java_websocket/WebSocketImpl.java
|
||||
--- a/src/main/java/org/java_websocket/WebSocketImpl.java 2023-07-20 21:24:05.000000000 +0100
|
||||
+++ b/src/main/java/org/java_websocket/WebSocketImpl.java 2023-08-30 12:12:26.045577651 +0100
|
||||
@@ -61,8 +61,8 @@
|
||||
import org.java_websocket.protocols.IProtocol;
|
||||
import org.java_websocket.server.WebSocketServer.WebSocketWorker;
|
||||
import org.java_websocket.util.Charsetfunctions;
|
||||
-import org.slf4j.Logger;
|
||||
-import org.slf4j.LoggerFactory;
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Represents one end (client or server) of a single WebSocketImpl connection. Takes care of the
|
||||
@@ -95,7 +95,7 @@
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
- private final Logger log = LoggerFactory.getLogger(WebSocketImpl.class);
|
||||
+ private final Logger log = Logger.getLogger(WebSocketImpl.class.getName());
|
||||
|
||||
/**
|
||||
* Queue of buffers that need to be sent to the client.
|
||||
@@ -224,8 +224,8 @@
|
||||
*/
|
||||
public void decode(ByteBuffer socketBuffer) {
|
||||
assert (socketBuffer.hasRemaining());
|
||||
- if (log.isTraceEnabled()) {
|
||||
- log.trace("process({}): ({})", socketBuffer.remaining(),
|
||||
+ if (log.isLoggable(Level.FINE)) {
|
||||
+ log.fine("process({}): ({})" + " : " + socketBuffer.remaining() + " : " +
|
||||
(socketBuffer.remaining() > 1000 ? "too big to display"
|
||||
: new String(socketBuffer.array(), socketBuffer.position(), socketBuffer.remaining())));
|
||||
}
|
||||
@@ -280,7 +280,7 @@
|
||||
socketBuffer.reset();
|
||||
Handshakedata tmphandshake = d.translateHandshake(socketBuffer);
|
||||
if (!(tmphandshake instanceof ClientHandshake)) {
|
||||
- log.trace("Closing due to wrong handshake");
|
||||
+ log.fine("Closing due to wrong handshake");
|
||||
closeConnectionDueToWrongHandshake(
|
||||
new InvalidDataException(CloseFrame.PROTOCOL_ERROR, "wrong http function"));
|
||||
return false;
|
||||
@@ -293,11 +293,11 @@
|
||||
try {
|
||||
response = wsl.onWebsocketHandshakeReceivedAsServer(this, d, handshake);
|
||||
} catch (InvalidDataException e) {
|
||||
- log.trace("Closing due to wrong handshake. Possible handshake rejection", e);
|
||||
+ log.fine("Closing due to wrong handshake. Possible handshake rejection" + " : " + e);
|
||||
closeConnectionDueToWrongHandshake(e);
|
||||
return false;
|
||||
} catch (RuntimeException e) {
|
||||
- log.error("Closing due to internal server error", e);
|
||||
+ log.severe("Closing due to internal server error" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
closeConnectionDueToInternalServerError(e);
|
||||
return false;
|
||||
@@ -313,7 +313,7 @@
|
||||
}
|
||||
}
|
||||
if (draft == null) {
|
||||
- log.trace("Closing due to protocol error: no draft matches");
|
||||
+ log.fine("Closing due to protocol error: no draft matches");
|
||||
closeConnectionDueToWrongHandshake(
|
||||
new InvalidDataException(CloseFrame.PROTOCOL_ERROR, "no draft matches"));
|
||||
}
|
||||
@@ -322,7 +322,7 @@
|
||||
// special case for multiple step handshakes
|
||||
Handshakedata tmphandshake = draft.translateHandshake(socketBuffer);
|
||||
if (!(tmphandshake instanceof ClientHandshake)) {
|
||||
- log.trace("Closing due to protocol error: wrong http function");
|
||||
+ log.fine("Closing due to protocol error: wrong http function");
|
||||
flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
|
||||
return false;
|
||||
}
|
||||
@@ -333,7 +333,7 @@
|
||||
open(handshake);
|
||||
return true;
|
||||
} else {
|
||||
- log.trace("Closing due to protocol error: the handshake did finally not match");
|
||||
+ log.fine("Closing due to protocol error: the handshake did finally not match");
|
||||
close(CloseFrame.PROTOCOL_ERROR, "the handshake did finally not match");
|
||||
}
|
||||
return false;
|
||||
@@ -342,7 +342,7 @@
|
||||
draft.setParseMode(role);
|
||||
Handshakedata tmphandshake = draft.translateHandshake(socketBuffer);
|
||||
if (!(tmphandshake instanceof ServerHandshake)) {
|
||||
- log.trace("Closing due to protocol error: wrong http function");
|
||||
+ log.fine("Closing due to protocol error: wrong http function");
|
||||
flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
|
||||
return false;
|
||||
}
|
||||
@@ -352,11 +352,11 @@
|
||||
try {
|
||||
wsl.onWebsocketHandshakeReceivedAsClient(this, handshakerequest, handshake);
|
||||
} catch (InvalidDataException e) {
|
||||
- log.trace("Closing due to invalid data exception. Possible handshake rejection", e);
|
||||
+ log.fine("Closing due to invalid data exception. Possible handshake rejection" + " : " + e);
|
||||
flushAndClose(e.getCloseCode(), e.getMessage(), false);
|
||||
return false;
|
||||
} catch (RuntimeException e) {
|
||||
- log.error("Closing since client was never connected", e);
|
||||
+ log.severe("Closing since client was never connected" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
flushAndClose(CloseFrame.NEVER_CONNECTED, e.getMessage(), false);
|
||||
return false;
|
||||
@@ -364,12 +364,12 @@
|
||||
open(handshake);
|
||||
return true;
|
||||
} else {
|
||||
- log.trace("Closing due to protocol error: draft {} refuses handshake", draft);
|
||||
+ log.fine("Closing due to protocol error: draft {} refuses handshake" + " : " + draft);
|
||||
close(CloseFrame.PROTOCOL_ERROR, "draft " + draft + " refuses handshake");
|
||||
}
|
||||
}
|
||||
} catch (InvalidHandshakeException e) {
|
||||
- log.trace("Closing due to invalid handshake", e);
|
||||
+ log.fine("Closing due to invalid handshake" + " : " + e);
|
||||
close(e);
|
||||
}
|
||||
} catch (IncompleteHandshakeException e) {
|
||||
@@ -398,24 +398,24 @@
|
||||
try {
|
||||
frames = draft.translateFrame(socketBuffer);
|
||||
for (Framedata f : frames) {
|
||||
- log.trace("matched frame: {}", f);
|
||||
+ log.fine("matched frame: {}" + " : " + f);
|
||||
draft.processFrame(this, f);
|
||||
}
|
||||
} catch (LimitExceededException e) {
|
||||
if (e.getLimit() == Integer.MAX_VALUE) {
|
||||
- log.error("Closing due to invalid size of frame", e);
|
||||
+ log.severe("Closing due to invalid size of frame" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
}
|
||||
close(e);
|
||||
} catch (InvalidDataException e) {
|
||||
- log.error("Closing due to invalid data in frame", e);
|
||||
+ log.severe("Closing due to invalid data in frame" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
close(e);
|
||||
} catch (VirtualMachineError | ThreadDeath | LinkageError e) {
|
||||
- log.error("Got fatal error during frame processing");
|
||||
+ log.severe("Got fatal error during frame processing");
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
- log.error("Closing web socket due to an error during frame processing");
|
||||
+ log.severe("Closing web socket due to an error during frame processing");
|
||||
Exception exception = new Exception(e);
|
||||
wsl.onWebsocketError(this, exception);
|
||||
String errorMessage = "Got error " + e.getClass().getName();
|
||||
@@ -491,7 +491,7 @@
|
||||
sendFrame(closeFrame);
|
||||
}
|
||||
} catch (InvalidDataException e) {
|
||||
- log.error("generated frame is invalid", e);
|
||||
+ log.severe("generated frame is invalid" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
flushAndClose(CloseFrame.ABNORMAL_CLOSE, "generated frame is invalid", false);
|
||||
}
|
||||
@@ -551,9 +551,9 @@
|
||||
channel.close();
|
||||
} catch (IOException e) {
|
||||
if (e.getMessage() != null && e.getMessage().equals("Broken pipe")) {
|
||||
- log.trace("Caught IOException: Broken pipe during closeConnection()", e);
|
||||
+ log.fine("Caught IOException: Broken pipe during closeConnection()" + " : " + e);
|
||||
} else {
|
||||
- log.error("Exception during channel.close()", e);
|
||||
+ log.severe("Exception during channel.close()" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
}
|
||||
}
|
||||
@@ -601,7 +601,7 @@
|
||||
try {
|
||||
wsl.onWebsocketClosing(this, code, message, remote);
|
||||
} catch (RuntimeException e) {
|
||||
- log.error("Exception in onWebsocketClosing", e);
|
||||
+ log.severe("Exception in onWebsocketClosing" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
}
|
||||
if (draft != null) {
|
||||
@@ -678,7 +678,7 @@
|
||||
}
|
||||
ArrayList<ByteBuffer> outgoingFrames = new ArrayList<>();
|
||||
for (Framedata f : frames) {
|
||||
- log.trace("send frame: {}", f);
|
||||
+ log.fine("send frame: {}" + " : " + f);
|
||||
outgoingFrames.add(draft.createBinaryFrame(f));
|
||||
}
|
||||
write(outgoingFrames);
|
||||
@@ -729,7 +729,7 @@
|
||||
// Stop if the client code throws an exception
|
||||
throw new InvalidHandshakeException("Handshake data rejected by client.");
|
||||
} catch (RuntimeException e) {
|
||||
- log.error("Exception in startHandshake", e);
|
||||
+ log.severe("Exception in startHandshake" + " : " + e);
|
||||
wsl.onWebsocketError(this, e);
|
||||
throw new InvalidHandshakeException("rejected because of " + e);
|
||||
}
|
||||
@@ -739,8 +739,8 @@
|
||||
}
|
||||
|
||||
private void write(ByteBuffer buf) {
|
||||
- log.trace("write({}): {}", buf.remaining(),
|
||||
- buf.remaining() > 1000 ? "too big to display" : new String(buf.array()));
|
||||
+ log.fine("write({}): {}" + " : " + buf.remaining() + " : " +
|
||||
+ (buf.remaining() > 1000 ? "too big to display" : new String(buf.array())));
|
||||
|
||||
outQueue.add(buf);
|
||||
wsl.onWriteDemand(this);
|
||||
@@ -760,7 +760,7 @@
|
||||
}
|
||||
|
||||
private void open(Handshakedata d) {
|
||||
- log.trace("open using draft: {}", draft);
|
||||
+ log.fine("open using draft: {}" + " : " + draft);
|
||||
readyState = ReadyState.OPEN;
|
||||
updateLastPong();
|
||||
try {
|
|
@ -131,6 +131,15 @@ struct _LibreOfficeKitClass
|
|||
/// @see lok::Office::trimMemory
|
||||
/// @since LibreOffice 7.6
|
||||
void (*trimMemory) (LibreOfficeKit* pThis, int nTarget);
|
||||
|
||||
/// @see lok::Office::startURP
|
||||
int (*startURP)(LibreOfficeKit* pThis, void* pReceiveURPFromLOContext,
|
||||
void** ppSendURPToLOContext,
|
||||
int (*fnReceiveURPFromLO)(void* pContext, const signed char* pBuffer, int nLen),
|
||||
int (**pfnSendURPToLO)(void* pContext, const signed char* pBuffer, int nLen));
|
||||
|
||||
/// @see lok::Office::stopURP
|
||||
void (*stopURP)(LibreOfficeKit* pThis, void* pSendURPToLOContext);
|
||||
};
|
||||
|
||||
#define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize)
|
||||
|
|
|
@ -1166,6 +1166,32 @@ public:
|
|||
{
|
||||
mpThis->pClass->trimMemory(mpThis, nTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a UNO acceptor using the function pointers provides to read and write data to/from the acceptor.
|
||||
*
|
||||
* @param pReceiveURPFromLOContext A pointer that will be passed to your fnRecieveURPFromLO function
|
||||
* @param ppSendURPToLOContext A pointer to a pointer that you should give to the function passing URP to LO will be stored in this.
|
||||
* @param fnReceiveURPFromLO A function pointer that LO should use to pass URP back to the caller
|
||||
* @param pfnSendURPToLO A function pointer pointer that the caller should use to pass URP to LO will be stored in this.
|
||||
*/
|
||||
bool startURP(void* pReceiveURPFromLOContext, void** ppSendURPToLOContext,
|
||||
int (*fnReceiveURPFromLO)(void* pContext, const signed char* pBuffer, int nLen),
|
||||
int (**pfnSendURPToLO)(void* pContext, const signed char* pBuffer, int nLen))
|
||||
{
|
||||
return mpThis->pClass->startURP(mpThis, pReceiveURPFromLOContext, ppSendURPToLOContext,
|
||||
fnReceiveURPFromLO, pfnSendURPToLO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a function based URP connection you previously started with startURP
|
||||
*
|
||||
* @param pSendURPToLOContext the context you got back in the ppSendURPToLOContext argument when starting the connection
|
||||
*/
|
||||
void stopURP(void* pSendURPToLOContext)
|
||||
{
|
||||
mpThis->pClass->stopURP(mpThis, pSendURPToLOContext);
|
||||
}
|
||||
};
|
||||
|
||||
/// Factory method to create a lok::Office instance.
|
||||
|
|
|
@ -328,6 +328,7 @@ certain functionality.
|
|||
@li @c lok.tiledrendering
|
||||
@li @c lok.dialog
|
||||
@li @c lok.a11y - LOK accessibility
|
||||
@li @c lok.urp - Uno Remote Protocol
|
||||
|
||||
@section l10ntools
|
||||
|
||||
|
|
|
@ -253,6 +253,24 @@
|
|||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.</p>
|
||||
</div>
|
||||
<div class="JAVA_WEBSOCKET">
|
||||
<h2>Java WebSocket</h2>
|
||||
<p>The following software may be included in this product: Java WebSocket. Use of any of this software is governed
|
||||
by the terms of the license below:</p>
|
||||
<h3>The MIT License</h3>
|
||||
<p>Copyright (c) 2010-2020 Nathan Rajlich</p>
|
||||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
|
||||
<p>The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.</p>
|
||||
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.</p>
|
||||
</div>
|
||||
<div class="JFREEREPORT">
|
||||
<h2>Flute</h2>
|
||||
<p>The following software may be included in this product: Flute. Use of any of this software is governed by the
|
||||
|
|
|
@ -18,11 +18,16 @@ $(eval $(call gb_Jar_use_jars,libreoffice, \
|
|||
unoloader \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Jar_use_externals,libreoffice,\
|
||||
java_websocket \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Jar_set_packageroot,libreoffice,com))
|
||||
|
||||
$(eval $(call gb_Jar_set_manifest,libreoffice,$(SRCDIR)/ridljar/util/manifest))
|
||||
|
||||
$(eval $(call gb_Jar_add_manifest_classpath,libreoffice, \
|
||||
java_websocket.jar \
|
||||
unoloader.jar \
|
||||
$(if $(filter MACOSX,$(OS)),../../Frameworks/,../) \
|
||||
))
|
||||
|
@ -63,6 +68,9 @@ $(eval $(call gb_Jar_add_sourcefiles,libreoffice,\
|
|||
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/connections/websocket/ConnectionDescriptor \
|
||||
ridljar/com/sun/star/lib/connections/websocket/WebsocketConnection \
|
||||
ridljar/com/sun/star/lib/connections/websocket/websocketConnector \
|
||||
ridljar/com/sun/star/lib/uno/Proxy \
|
||||
ridljar/com/sun/star/lib/uno/adapter/ByteArrayToXInputStreamAdapter \
|
||||
ridljar/com/sun/star/lib/uno/adapter/InputStreamToXInputStreamAdapter \
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.sun.star.lib.util.NativeLibraryLoader;
|
|||
import com.sun.star.loader.XImplementationLoader;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
@ -397,6 +398,68 @@ public class Bootstrap {
|
|||
return xContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstraps the component context from a websocket location.
|
||||
*
|
||||
* @param url
|
||||
* the ws:// or wss:// url of the websocket server
|
||||
*
|
||||
* @throws BootstrapException if things go awry.
|
||||
*
|
||||
* @return a bootstrapped component context.
|
||||
*
|
||||
* @since LibreOffice 24.2
|
||||
*/
|
||||
public static final XComponentContext bootstrapWebsocketConnection( String url )
|
||||
throws BootstrapException {
|
||||
|
||||
XComponentContext xContext = null;
|
||||
|
||||
try {
|
||||
// create default local component context
|
||||
XComponentContext xLocalContext =
|
||||
createInitialComponentContext( (Map<String, Object>) null );
|
||||
if ( xLocalContext == null )
|
||||
throw new BootstrapException( "no local component context!" );
|
||||
|
||||
// initial service manager
|
||||
XMultiComponentFactory xLocalServiceManager =
|
||||
xLocalContext.getServiceManager();
|
||||
if ( xLocalServiceManager == null )
|
||||
throw new BootstrapException( "no initial service manager!" );
|
||||
|
||||
// create a URL resolver
|
||||
XUnoUrlResolver xUrlResolver =
|
||||
UnoUrlResolver.create( xLocalContext );
|
||||
|
||||
// connection string
|
||||
String sConnect = "uno:websocket"
|
||||
+ ",url=" + url
|
||||
+ ";urp;StarOffice.ComponentContext";
|
||||
|
||||
try {
|
||||
// try to connect to office
|
||||
Object xOfficeServiceManager = xUrlResolver.resolve(sConnect);
|
||||
|
||||
xContext = UnoRuntime.queryInterface(XComponentContext.class, xOfficeServiceManager);
|
||||
|
||||
if ( xContext == null )
|
||||
throw new BootstrapException( "no component context!" );
|
||||
} catch ( com.sun.star.connection.NoConnectException ex ) {
|
||||
throw new BootstrapException(ex);
|
||||
}
|
||||
} catch ( BootstrapException e ) {
|
||||
throw e;
|
||||
} catch ( java.lang.RuntimeException e ) {
|
||||
throw e;
|
||||
} catch ( java.lang.Exception e ) {
|
||||
throw new BootstrapException( e );
|
||||
}
|
||||
|
||||
return xContext;
|
||||
}
|
||||
|
||||
|
||||
private static final Random randomPipeName = new Random();
|
||||
|
||||
private static void pipe(
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- 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.websocket;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Helper class for <code>websocketConnector</code>.
|
||||
*/
|
||||
final class ConnectionDescriptor {
|
||||
public ConnectionDescriptor(String description)
|
||||
throws com.sun.star.lang.IllegalArgumentException {
|
||||
Iterator<String> descriptionParts = Arrays.stream(description.split(",")).iterator();
|
||||
descriptionParts
|
||||
.next(); // skip over the first part as it's the protocol not a real parameter
|
||||
while (descriptionParts.hasNext())
|
||||
{
|
||||
String parameter = descriptionParts.next();
|
||||
String[] pair = parameter.split("=", 2);
|
||||
|
||||
if (pair.length != 2)
|
||||
{
|
||||
throw new com.sun.star.lang.IllegalArgumentException(
|
||||
String.format("parameter %s lacks '='", parameter));
|
||||
}
|
||||
|
||||
String key = pair[0];
|
||||
String value = pair[1];
|
||||
if (key.equalsIgnoreCase("url")) {
|
||||
url = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getURL() {
|
||||
return url;
|
||||
}
|
||||
|
||||
private String url = null;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -0,0 +1,335 @@
|
|||
/* -*- 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.websocket;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.swing.text.html.HTMLDocument.Iterator;
|
||||
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnectionBroadcaster;
|
||||
import com.sun.star.io.XStreamListener;
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
|
||||
/**
|
||||
* The WebsocketConnection implements the <code>XConnection</code> interface
|
||||
* and is uses by the <code>WebsocketConnector</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
|
||||
*/
|
||||
public class WebsocketConnection extends WebSocketClient implements XConnection, XConnectionBroadcaster {
|
||||
/**
|
||||
* When set to true, enables various debugging output.
|
||||
*/
|
||||
public static final boolean DEBUG = false;
|
||||
static final byte[] outgoingPrefix = { 'u', 'r', 'p', ' ' };
|
||||
|
||||
protected String _description;
|
||||
protected InputStream _inputStream;
|
||||
protected OutputStream _outputStream;
|
||||
|
||||
protected InputStream _outputStreamReader;
|
||||
protected OutputStream _inputStreamWriter;
|
||||
|
||||
protected ArrayList<XStreamListener> _listeners;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>WebsocketConnection</code>.
|
||||
*
|
||||
* @param description the description of the connection.
|
||||
* @param desc the websocket ConnectionDescriptor containing information such as the websocket URL
|
||||
*/
|
||||
public WebsocketConnection(String description, ConnectionDescriptor desc) throws IOException, URISyntaxException, InterruptedException {
|
||||
super(new URI(desc.getURL()));
|
||||
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated " + description + " " + desc);
|
||||
|
||||
_description = description;
|
||||
|
||||
PipedOutputStream inputStreamWriter = new PipedOutputStream();
|
||||
PipedInputStream inputPipe = new PipedInputStream(inputStreamWriter);
|
||||
PipedOutputStream outputPipe = new PipedOutputStream();
|
||||
PipedInputStream outputStreamReader = new PipedInputStream(outputPipe);
|
||||
|
||||
|
||||
_inputStream = new BufferedInputStream(inputPipe);
|
||||
_inputStreamWriter = inputStreamWriter;
|
||||
_outputStream = new BufferedOutputStream(outputPipe);
|
||||
_outputStreamReader = outputStreamReader;
|
||||
|
||||
_listeners = new ArrayList<XStreamListener>();
|
||||
|
||||
connectBlocking();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
String errMessage = null;
|
||||
|
||||
int read_bytes = 0;
|
||||
bytes[0] = new byte[nBytesToRead];
|
||||
|
||||
try {
|
||||
_inputStreamWriter.flush();
|
||||
|
||||
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(String.format("##### %s - read %s bytes of %s requested", getClass().getName(), Integer.toString(read_bytes), Integer.toString(nBytesToRead)));
|
||||
|
||||
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(String.format("##### %s - wrote %s bytes", getClass().getName(), Integer.toString(aData.length)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the data over the websocket to whatever is on the other side.
|
||||
*
|
||||
* **NOTE**: unlike with genuine streams, without flushing the data is
|
||||
* never sent
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#flush
|
||||
*/
|
||||
public void flush() throws com.sun.star.io.IOException,
|
||||
com.sun.star.uno.RuntimeException {
|
||||
try {
|
||||
_outputStream.flush();
|
||||
|
||||
Integer available = _outputStreamReader.available();
|
||||
|
||||
byte[] outputBytes = new byte[available + outgoingPrefix.length];
|
||||
System.arraycopy(outgoingPrefix, 0, outputBytes, 0, outgoingPrefix.length);
|
||||
|
||||
_outputStreamReader.read(outputBytes, outgoingPrefix.length, available);
|
||||
|
||||
send(outputBytes);
|
||||
} 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(String.format("##### %s - flushed", getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection.
|
||||
*
|
||||
* @see com.sun.star.connection.XConnection#close
|
||||
*/
|
||||
public void close() throws com.sun.star.uno.RuntimeException {
|
||||
if (DEBUG) System.err.println("##### " + getClass().getName() + " - socket closed");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
notifyListeners_open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote) {
|
||||
notifyListeners_close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
String[] messageParts = message.split(": ", 2);
|
||||
if (messageParts.length != 2)
|
||||
{
|
||||
notifyListeners_error(new com.sun.star.uno.Exception(new ProtocolException(String.format("Recieved URP/WS message (%s) without a type specifier. Messages must be proceeded by 'urp: '", message))));
|
||||
return;
|
||||
}
|
||||
|
||||
String messageType = messageParts[0];
|
||||
|
||||
if (!messageType.equals("urp"))
|
||||
{
|
||||
if (DEBUG) System.err.println(String.format("##### %s - received %s message but that is not URP", getClass().getName(), messageType));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] messageBytes = messageParts[1].getBytes();
|
||||
|
||||
try {
|
||||
_inputStreamWriter.write(messageBytes);
|
||||
} catch (IOException e) {
|
||||
notifyListeners_error(new com.sun.star.uno.Exception(e));
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) System.err.println(String.format("##### %s - recieved %s chars", getClass().getName(), Integer.toString(messageBytes.length)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(ByteBuffer message) {
|
||||
byte[] prefixedMessageBytes = message.array();
|
||||
|
||||
String messageType = "";
|
||||
boolean hasType = false;
|
||||
int i;
|
||||
for (i = 0; i < prefixedMessageBytes.length - 1; i++) {
|
||||
if (prefixedMessageBytes[i] == ':' && (prefixedMessageBytes[i+1] == ' ' || prefixedMessageBytes[i+1] == '\n')) {
|
||||
hasType = true;
|
||||
break; // The type ends with ": ", so if we find this sequence we found the end of our type
|
||||
}
|
||||
messageType += (char)prefixedMessageBytes[i];
|
||||
}
|
||||
|
||||
if(!hasType) {
|
||||
notifyListeners_error(new com.sun.star.uno.Exception(new ProtocolException(String.format("Recieved URP/WS message (%s) without a type specifier. Binary messages must be proceeded by 'urp: ' or 'urp:\\n'", message))));
|
||||
return;
|
||||
}
|
||||
|
||||
int messageStartIndex = i + 2;
|
||||
|
||||
if (!messageType.equals("urp")) {
|
||||
if (DEBUG) System.err.println(String.format("##### %s - recieved %s binary message but that is not URP", getClass().getName(), messageType));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] messageBytes = Arrays.copyOfRange(prefixedMessageBytes, messageStartIndex, prefixedMessageBytes.length);
|
||||
|
||||
try {
|
||||
_inputStreamWriter.write(messageBytes);
|
||||
} catch (IOException e) {
|
||||
notifyListeners_error(new com.sun.star.uno.Exception(e));
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) System.err.println(String.format("##### %s - recieved %s bytes", getClass().getName(), Integer.toString(prefixedMessageBytes.length)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
notifyListeners_error(new com.sun.star.uno.Exception(ex));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -0,0 +1,137 @@
|
|||
/* -*- 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.websocket;
|
||||
|
||||
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.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* A component that implements the <code>XConnector</code> interface.
|
||||
*
|
||||
* <p>The <code>websocketConnector</code> is a specialized component that uses
|
||||
* websockets for communication. The <code>websocketConnector</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
|
||||
*/
|
||||
public final class websocketConnector 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.websocketConnector";
|
||||
|
||||
/**
|
||||
* 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(websocketConnector.class.getName())
|
||||
? FactoryHelper.getServiceFactory(websocketConnector.class,
|
||||
__serviceName, multiFactory,
|
||||
regKey)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects via the described websocket 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>websocket</code>
|
||||
* (ignoring case). Supported keys (ignoring case) currently are</p>
|
||||
* <dl>
|
||||
* <dt><code>url</code>
|
||||
* <dd>The URL the websocket server is listening on, starting with
|
||||
* either ws:// or wss://
|
||||
* </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 to the socket");
|
||||
|
||||
ConnectionDescriptor desc;
|
||||
try {
|
||||
desc = new ConnectionDescriptor(connectionDescription);
|
||||
} catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
}
|
||||
|
||||
WebsocketConnection websocket = null;
|
||||
try {
|
||||
websocket = new WebsocketConnection(connectionDescription, desc);
|
||||
connected = websocket.isOpen();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ConnectionSetupException(e);
|
||||
}
|
||||
|
||||
if (websocket == null || !connected)
|
||||
throw new ConnectionSetupException("Could not connect to the server. Is it up?");
|
||||
|
||||
return websocket;
|
||||
}
|
||||
|
||||
private boolean connected = false;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -64,6 +64,7 @@ module org.libreoffice.uno
|
|||
exports com.sun.star.ldap;
|
||||
exports com.sun.star.lib.connections.pipe;
|
||||
exports com.sun.star.lib.connections.socket;
|
||||
exports com.sun.star.lib.connections.websocket;
|
||||
exports com.sun.star.lib.uno;
|
||||
exports com.sun.star.lib.uno.adapter;
|
||||
exports com.sun.star.lib.uno.bridges.java_remote;
|
||||
|
|
|
@ -24,6 +24,9 @@ Sealed: true
|
|||
Name: com/sun/star/lib/connections/socket/
|
||||
Sealed: true
|
||||
|
||||
Name: com/sun/star/lib/connections/websocket/
|
||||
Sealed: true
|
||||
|
||||
Name: com/sun/star/lib/uno/
|
||||
Sealed: true
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ ELF platforms (Linux, Solaris, *BSD):
|
|||
/opt/libreoffice/ure/lib/libstocserviceslo.so [private]
|
||||
/opt/libreoffice/ure/lib/libuuresolverlo.so [private]
|
||||
/opt/libreoffice/ure/share/java/java_uno.jar [private]
|
||||
/opt/libreoffice/ure/share/java/java_websocket.jar [private]
|
||||
/opt/libreoffice/ure/share/misc/javavendors.xml [private]
|
||||
|
||||
Windows:
|
||||
|
@ -132,6 +133,7 @@ Program Files\URE\bin\stocserviceslo.dll [private]
|
|||
Program Files\URE\bin\uuresolverlo.dll [private]
|
||||
Program Files\URE\bin\uwinapi.dll [private]
|
||||
Program Files\URE\java\java_uno.jar [private]
|
||||
Program Files\URE\java\java_websocket.jar [private]
|
||||
Program Files\URE\misc\javavendors.xml [private]
|
||||
|
||||
%windir%\assembly\cli_basetypes.dll [GAC]
|
||||
|
|
Loading…
Reference in a new issue