summaryrefslogtreecommitdiffstats
path: root/mcop
diff options
context:
space:
mode:
Diffstat (limited to 'mcop')
-rw-r--r--mcop/Makefile.am33
-rw-r--r--mcop/anyref.cc310
-rw-r--r--mcop/anyref.h146
-rw-r--r--mcop/arts_export.h.in53
-rw-r--r--mcop/asyncstream.cc46
-rw-r--r--mcop/asyncstream.h103
-rw-r--r--mcop/buffer.cc386
-rw-r--r--mcop/buffer.h104
-rw-r--r--mcop/common.h141
-rw-r--r--mcop/connect.cc149
-rw-r--r--mcop/connect.h55
-rw-r--r--mcop/connection.cc196
-rw-r--r--mcop/connection.h100
-rw-r--r--mcop/core.cc3191
-rw-r--r--mcop/core.h1561
-rw-r--r--mcop/core.idl715
-rw-r--r--mcop/datapacket.cc65
-rw-r--r--mcop/datapacket.h230
-rw-r--r--mcop/debug.cc821
-rw-r--r--mcop/debug.h138
-rw-r--r--mcop/delayedreturn.cc71
-rw-r--r--mcop/delayedreturn.h102
-rw-r--r--mcop/dispatcher.cc1090
-rw-r--r--mcop/dispatcher.h265
-rw-r--r--mcop/dynamicrequest.cc152
-rw-r--r--mcop/dynamicrequest.h133
-rw-r--r--mcop/dynamicskeleton.cc204
-rw-r--r--mcop/dynamicskeleton.h163
-rw-r--r--mcop/extensionloader.cc116
-rw-r--r--mcop/extensionloader.h59
-rw-r--r--mcop/factory.cc36
-rw-r--r--mcop/factory.h69
-rw-r--r--mcop/flowsystem.cc180
-rw-r--r--mcop/flowsystem.h147
-rw-r--r--mcop/idlfilereg.cc44
-rw-r--r--mcop/idlfilereg.h51
-rw-r--r--mcop/ifacerepo_impl.cc305
-rw-r--r--mcop/ifacerepo_impl.h98
-rw-r--r--mcop/iomanager.cc494
-rw-r--r--mcop/iomanager.h214
-rw-r--r--mcop/loopback.cc57
-rw-r--r--mcop/loopback.h51
-rw-r--r--mcop/mcopconfig.cc67
-rw-r--r--mcop/mcopconfig.h55
-rw-r--r--mcop/mcoputils.cc574
-rw-r--r--mcop/mcoputils.h97
-rw-r--r--mcop/md5.c197
-rw-r--r--mcop/md5.h45
-rw-r--r--mcop/md5auth.cc213
-rw-r--r--mcop/md5auth.h105
-rw-r--r--mcop/namedstore.h125
-rw-r--r--mcop/notification.cc101
-rw-r--r--mcop/notification.h87
-rw-r--r--mcop/object.cc1528
-rw-r--r--mcop/object.h390
-rw-r--r--mcop/objectmanager.cc289
-rw-r--r--mcop/objectmanager.h75
-rw-r--r--mcop/pool.h89
-rw-r--r--mcop/reference.cc32
-rw-r--r--mcop/reference.h349
-rw-r--r--mcop/referenceclean.cc87
-rw-r--r--mcop/referenceclean.h60
-rw-r--r--mcop/socketconnection.cc205
-rw-r--r--mcop/socketconnection.h64
-rw-r--r--mcop/startupmanager.cc150
-rw-r--r--mcop/startupmanager.h75
-rw-r--r--mcop/tcpconnection.cc152
-rw-r--r--mcop/tcpconnection.h43
-rw-r--r--mcop/tcpserver.cc193
-rw-r--r--mcop/tcpserver.h61
-rw-r--r--mcop/thread.cc169
-rw-r--r--mcop/thread.h375
-rw-r--r--mcop/tmpglobalcomm.cc82
-rw-r--r--mcop/trader_impl.cc345
-rw-r--r--mcop/type.cc31
-rw-r--r--mcop/type.h85
-rw-r--r--mcop/unixconnection.cc114
-rw-r--r--mcop/unixconnection.h43
-rw-r--r--mcop/unixserver.cc151
-rw-r--r--mcop/unixserver.h59
-rw-r--r--mcop/weakreference.h131
81 files changed, 19737 insertions, 0 deletions
diff --git a/mcop/Makefile.am b/mcop/Makefile.am
new file mode 100644
index 0000000..72fc23b
--- /dev/null
+++ b/mcop/Makefile.am
@@ -0,0 +1,33 @@
+
+AM_CPPFLAGS = -DEXTENSION_DIR='"$(libdir)"' -DTRADER_DIR='"$(libdir)/mcop"'
+##
+lib_LTLIBRARIES = libmcop.la
+#
+# Programs to compile, Manpages to install and Versions
+#
+INCLUDES = -I$(top_srcdir)/libltdl $(all_includes)
+libmcop_la_SOURCES = buffer.cc connection.cc core.cc debug.cc dispatcher.cc \
+ iomanager.cc object.cc socketconnection.cc tcpconnection.cc \
+ unixconnection.cc tcpserver.cc unixserver.cc objectmanager.cc \
+ factory.cc idlfilereg.cc ifacerepo_impl.cc mcoputils.cc \
+ startupmanager.cc md5.c md5auth.cc referenceclean.cc datapacket.cc \
+ asyncstream.cc notification.cc flowsystem.cc extensionloader.cc \
+ tmpglobalcomm.cc mcopconfig.cc connect.cc reference.cc type.cc \
+ trader_impl.cc dynamicrequest.cc anyref.cc loopback.cc \
+ delayedreturn.cc thread.cc dynamicskeleton.cc
+
+libmcop_la_LIBADD = $(LIBSOCKET) $(GLIB_LIBADD) $(top_builddir)/libltdl/libltdlc.la
+libmcop_la_LDFLAGS = -no-undefined -version-info 1:0 $(GLIB_LDFLAGS) $(all_libraries)
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = arts_export.h buffer.h common.h connection.h core.h dispatcher.h \
+ factory.h flowsystem.h idlfilereg.h ifacerepo_impl.h iomanager.h \
+ mcoputils.h object.h objectmanager.h pool.h socketconnection.h \
+ startupmanager.h tcpconnection.h tcpserver.h type.h unixconnection.h \
+ unixserver.h referenceclean.h datapacket.h asyncstream.h notification.h \
+ extensionloader.h mcopconfig.h connect.h reference.h weakreference.h \
+ dynamicrequest.h anyref.h debug.h delayedreturn.h dynamicskeleton.h thread.h \
+ core.idl
+
+core: $(srcdir)/core.idl $(MCOPIDL)
+ $(MCOPIDL) -e Arts::Object -I$(srcdir) $(srcdir)/core.idl
diff --git a/mcop/anyref.cc b/mcop/anyref.cc
new file mode 100644
index 0000000..9ea434b
--- /dev/null
+++ b/mcop/anyref.cc
@@ -0,0 +1,310 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "anyref.h"
+#include "common.h"
+#include "startupmanager.h"
+#include "debug.h"
+#include <assert.h>
+
+using namespace Arts;
+using namespace std;
+
+/*
+ * private utility class to deal with any types
+ */
+namespace Arts {
+ static class AnyRefHelper {
+ private:
+ Arts::InterfaceRepoV2 interfaceRepo;
+
+ public:
+ AnyRefHelper() {
+ interfaceRepo = DynamicCast(Dispatcher::the()->interfaceRepo());
+ }
+ void skipType(Buffer& buffer, const string& type);
+ } *anyRefHelper = 0;
+
+ static class AnyRefHelperStartup : public StartupClass {
+ void startup() {
+ assert(anyRefHelper == 0);
+ anyRefHelper = new AnyRefHelper();
+ }
+ void shutdown() {
+ delete anyRefHelper;
+ anyRefHelper = 0;
+ }
+ } The_AnyRefHelperStartup;
+}
+
+string AnyRefBase::type() const
+{
+/*
+ keep common types here, so that the string constructor doesn't need
+ to get called each and every time
+ */
+ static const string tVoid("void");
+ static const string tByte("byte");
+ static const string tsByte("*byte");
+ static const string tLong("long");
+ static const string tsLong("*long");
+ static const string tFloat("float");
+ static const string tsFloat("*float");
+ static const string tString("string");
+ static const string tsString("*string");
+ static const string tBool("bool");
+ static const string tsBool("*bool");
+
+ switch(rep)
+ {
+ case repVoid: return tVoid;
+
+ // primitive types
+ case repByte: return tByte;
+ case repInt:
+ case repLong: return tLong;
+ case repFloat:
+ case repDouble: return tFloat;
+ case repString:
+ case repCString: return tString;
+ case repBool: return tBool;
+
+ // sequences of primitive types
+ case repByteSeq: return tsByte;
+ case repLongSeq: return tsLong;
+ case repFloatSeq: return tsFloat;
+ case repStringSeq: return tsString;
+ case repBoolSeq: return tsBool;
+
+ case repAny: return ((Any *)data)->type;
+ }
+ assert(false);
+ return tVoid; // silence compiler
+}
+
+void AnyRefBase::_write(Buffer *b) const
+{
+ switch(rep)
+ {
+ case repVoid:
+ break;
+
+ // primitive types
+ case repByte: b->writeByte(*(mcopbyte *)data);
+ break;
+
+ case repInt: b->writeLong(*(int *)data);
+ break;
+
+ case repLong: b->writeLong(*(long *)data);
+ break;
+
+ case repFloat: b->writeFloat(*(float *)data);
+ break;
+
+ case repDouble: b->writeFloat(*(double *)data);
+ break;
+
+ case repString: b->writeString(*(string *)data);
+ break;
+
+ case repCString: b->writeString((const char *)data);
+ break;
+
+ case repBool: b->writeBool(*(bool *)data);
+ break;
+
+ // sequences of primitive types
+ case repByteSeq: b->writeByteSeq(*(vector<mcopbyte> *)data);
+ break;
+
+ case repLongSeq: b->writeLongSeq(*(vector<long> *)data);
+ break;
+
+ case repFloatSeq: b->writeFloatSeq(*(vector<float> *)data);
+ break;
+
+ case repStringSeq: b->writeStringSeq(*(vector<string> *)data);
+ break;
+
+ case repBoolSeq: b->writeBoolSeq(*(vector<bool> *)data);
+ break;
+
+ case repAny: b->write(((Any *)data)->value);
+ break;
+
+ default: assert(false);
+ }
+}
+
+void AnyRefBase::_read(Buffer *b) const
+{
+ switch(rep)
+ {
+ case repVoid:
+ break;
+
+ // primitive types
+ case repByte: *(mcopbyte *)data = b->readByte();
+ break;
+
+ case repInt: *(int *)data = b->readLong();
+ break;
+
+ case repLong: *(long *)data = b->readLong();
+ break;
+
+ case repFloat: *(float *)data = b->readFloat();
+ break;
+
+ case repDouble: *(double *)data = b->readFloat();
+ break;
+
+ case repString: b->readString(*(string *)data);
+ break;
+
+ case repBool: *(bool *)data = b->readBool();
+ break;
+
+ // sequences of primitive types
+ case repByteSeq: b->readByteSeq(*(vector<mcopbyte> *)data);
+ break;
+
+ case repLongSeq: b->readLongSeq(*(vector<long> *)data);
+ break;
+
+ case repFloatSeq: b->readFloatSeq(*(vector<float> *)data);
+ break;
+
+ case repStringSeq: b->readStringSeq(*(vector<string> *)data);
+ break;
+
+ case repBoolSeq: b->readBoolSeq(*(vector<bool> *)data);
+ break;
+
+ case repAny:
+ {
+ // find out the size by skipping over it for the first time
+ long startPos = b->size() - b->remaining();
+ anyRefHelper->skipType(*b, ((Any *)data)->type);
+
+ // if everything went well, read the raw value in one step
+ long size = (b->size() - b->remaining()) - startPos;
+ if(!b->readError())
+ {
+ b->rewind();
+ b->skip(startPos);
+ b->read(((Any *)data)->value, size);
+ }
+ }
+ break;
+
+ default: assert(false);
+ }
+}
+
+/**
+ * correct skipping of an arbitary type not known at compile-time (this is
+ * a problem, since the size of the type will vary, due to the sequence<...>s
+ * contained)
+ */
+void AnyRefHelper::skipType(Buffer& buffer, const string& type)
+{
+ /* sequences */
+ if(type[0] == '*')
+ {
+ long seqlen = buffer.readLong();
+ while(seqlen > 0 && !buffer.readError())
+ {
+ skipType(buffer, type.c_str()+1);
+ seqlen--;
+ }
+ }
+ else
+ {
+ TypeIdentification ti = interfaceRepo.identifyType(type);
+ switch(ti)
+ {
+ case tiString:
+ {
+ string s;
+ buffer.readString(s);
+ }
+ break;
+
+ case tiLong:
+ buffer.readLong();
+ break;
+
+ case tiFloat:
+ buffer.readFloat();
+ break;
+
+ case tiByte:
+ buffer.readByte();
+ break;
+
+ case tiBoolean:
+ buffer.readBool();
+ break;
+
+ case tiVoid:
+ /* nothing to do */
+ break;
+
+ case tiType:
+ {
+ Arts::TypeDef td = interfaceRepo.queryType(type);
+
+ if(td.name == type)
+ {
+ vector<TypeComponent>::iterator tci;
+ for(tci = td.contents.begin(); tci != td.contents.end();
+ tci++)
+ {
+ skipType(buffer,tci->type);
+ }
+ }
+ else
+ {
+ arts_warning("unknown type %s",type.c_str());
+ }
+ }
+ break;
+
+ case tiEnum:
+ buffer.readLong();
+ break;
+
+ case tiInterface:
+ {
+ ObjectReference oref;
+ oref.readType(buffer);
+ }
+ break;
+
+ default:
+ arts_warning("AnyRefHelper: can't read %s",type.c_str());
+ break;
+ }
+ }
+}
diff --git a/mcop/anyref.h b/mcop/anyref.h
new file mode 100644
index 0000000..688f9db
--- /dev/null
+++ b/mcop/anyref.h
@@ -0,0 +1,146 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef MCOP_ANYREF_H
+#define MCOP_ANYREF_H
+
+#include "buffer.h"
+#include <string>
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): AnyRefBase, AnyRef, AnyConstRef
+ *
+ * These classes will be kept binary compatibile. To change it, adding a new
+ * representation is necessary. No private d pointer for this reason.
+ */
+
+namespace Arts {
+
+class Any;
+class ARTS_EXPORT AnyRefBase {
+protected:
+ void *data;
+
+ /*
+ * This is used for specifying which is the content of a sequence or
+ * an enum or similar. For normal types, it remains unset, as their
+ * name can be generated from rep.
+ */
+ std::string _type;
+
+ /*
+ * What representation data is pointing to?
+ *
+ * repInt (int *), repDouble (double *) and repConstChar (const char *)
+ * are no native MCOP types, but alternative ways or representing the
+ * native "int", "float" and "const char *" types
+ */
+
+ // BC: adding new representations and types is possible, however, existing
+ // numbers may not be changed
+ enum Representation {
+ repVoid = 0,
+ repByte = 10,
+ repLong = 20, repInt = 21 /* treated as long */,
+ repFloat = 30, repDouble = 31 /* treated as float */,
+ repString = 40, repCString = 41 /* string */,
+ repBool = 50,
+ repByteSeq = 510,
+ repLongSeq = 520,
+ repFloatSeq = 530,
+ repStringSeq = 540,
+ repBoolSeq = 550,
+ repAny = 1000 /* may hold any type */
+ } rep;
+
+ void _write(Buffer *b) const;
+ void _read(Buffer *b) const;
+
+ AnyRefBase(const void *data, Representation rep)
+ : data(const_cast<void *>(data)), rep(rep) { };
+ AnyRefBase(const void *data, Representation rep, const char *type)
+ : data(const_cast<void *>(data)), _type(type), rep(rep) { };
+ AnyRefBase(const AnyRefBase &copy)
+ : data(copy.data), _type(copy._type), rep(copy.rep) { }
+public:
+ std::string type() const;
+};
+
+class ARTS_EXPORT AnyConstRef : public AnyRefBase {
+public:
+ AnyConstRef() : AnyRefBase(0,repVoid) { };
+ AnyConstRef(const mcopbyte& value) : AnyRefBase(&value,repByte) { };
+ AnyConstRef(const int& value) : AnyRefBase(&value,repInt) { };
+ AnyConstRef(const long& value) : AnyRefBase(&value,repLong) { };
+ AnyConstRef(const float& value) : AnyRefBase(&value,repFloat) { };
+ AnyConstRef(const double& value) : AnyRefBase(&value,repDouble) { };
+ AnyConstRef(const std::string& value) : AnyRefBase(&value,repString) { };
+ AnyConstRef(const char *value) : AnyRefBase(value,repCString) { };
+ AnyConstRef(const bool& value) : AnyRefBase(&value,repBool) { };
+
+ AnyConstRef(const std::vector<mcopbyte>& v)
+ : AnyRefBase(&v,repByteSeq) { };
+ AnyConstRef(const std::vector<long>& v)
+ : AnyRefBase(&v,repLongSeq) { };
+ AnyConstRef(const std::vector<float>& v)
+ : AnyRefBase(&v,repFloatSeq) { };
+ AnyConstRef(const std::vector<std::string>& v)
+ : AnyRefBase(&v,repStringSeq) { };
+ AnyConstRef(const std::vector<bool>& v)
+ : AnyRefBase(&v,repBoolSeq) { };
+
+ AnyConstRef(const Any& value) : AnyRefBase(&value,repAny) { };
+
+ AnyConstRef(const AnyConstRef& ref) : AnyRefBase(ref) { }
+ void write(Buffer *b) const { _write(b); }
+};
+
+class ARTS_EXPORT AnyRef : public AnyRefBase {
+public:
+ AnyRef() : AnyRefBase(0,repVoid) { };
+
+ // primitive types
+ AnyRef(mcopbyte& value) : AnyRefBase(&value,repByte) { };
+ AnyRef(int& value) : AnyRefBase(&value,repInt) { };
+ AnyRef(long& value) : AnyRefBase(&value,repLong) { };
+ AnyRef(float& value) : AnyRefBase(&value,repFloat) { };
+ AnyRef(double& value) : AnyRefBase(&value,repDouble) { };
+ AnyRef(std::string& value) : AnyRefBase(&value,repString) { };
+ AnyRef(bool& value) : AnyRefBase(&value,repBool) { };
+
+ // sequence of primitive types
+ AnyRef(std::vector<mcopbyte>& value) : AnyRefBase(&value,repByteSeq) { };
+ AnyRef(std::vector<long>& value) : AnyRefBase(&value,repLongSeq) { };
+ AnyRef(std::vector<float>& value) : AnyRefBase(&value,repFloatSeq) { };
+ AnyRef(std::vector<std::string>& value) : AnyRefBase(&value,repStringSeq){};
+ AnyRef(std::vector<bool>& value) : AnyRefBase(&value,repBoolSeq){};
+
+ AnyRef(Any& value) : AnyRefBase(&value,repAny) { };
+
+ AnyRef(const AnyRef& ref) : AnyRefBase(ref) { }
+
+ void read(Buffer *b) const { _read(b); }
+ void write(Buffer *b) const { _write(b); }
+};
+
+}
+#endif /* MCOP_ANYREF_H */
diff --git a/mcop/arts_export.h.in b/mcop/arts_export.h.in
new file mode 100644
index 0000000..4de637e
--- /dev/null
+++ b/mcop/arts_export.h.in
@@ -0,0 +1,53 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2002-2003 KDE Team
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ARTS_EXPORT_H
+#define ARTS_EXPORT_H
+
+#undef __KDE_HAVE_GCC_VISIBILITY
+
+/**
+ * The ARTS_NO_EXPORT macro marks the symbol of the given variable
+ * to be hidden. A hidden symbol is stripped during the linking step,
+ * so it can't be used from outside the resulting library, which is similar
+ * to static. However, static limits the visibility to the current
+ * compilation unit. hidden symbols can still be used in multiple compilation
+ * units.
+ *
+ * \code
+ * int ARTS_NO_EXPORT foo;
+ * int ARTS_EXPORT bar;
+ * \end
+ */
+
+#if defined(__KDE_HAVE_GCC_VISIBILITY)
+/* Visibility is available for GCC newer than 3.4.
+ * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9283
+ */
+#define ARTS_NO_EXPORT __attribute__ ((visibility("hidden")))
+#define ARTS_EXPORT __attribute__ ((visibility("default")))
+#elif defined(_WIN32)
+#define ARTS_NO_EXPORT
+#define ARTS_EXPORT __declspec(dllexport)
+#else
+#define ARTS_NO_EXPORT
+#define ARTS_EXPORT
+#endif
+
+#endif /* ARTS_EXPORTS */
diff --git a/mcop/asyncstream.cc b/mcop/asyncstream.cc
new file mode 100644
index 0000000..a623353
--- /dev/null
+++ b/mcop/asyncstream.cc
@@ -0,0 +1,46 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "asyncstream.h"
+#include "datapacket.h"
+
+using namespace Arts;
+
+DataPacket<float> *FloatAsyncStream::allocPacket(int capacity)
+{
+ return new FloatDataPacket(capacity,channel);
+}
+
+GenericAsyncStream *FloatAsyncStream::createNewStream()
+{
+ return new FloatAsyncStream();
+}
+
+DataPacket<mcopbyte> *ByteAsyncStream::allocPacket(int capacity)
+{
+ return new ByteDataPacket(capacity,channel);
+}
+
+GenericAsyncStream *ByteAsyncStream::createNewStream()
+{
+ return new ByteAsyncStream();
+}
diff --git a/mcop/asyncstream.h b/mcop/asyncstream.h
new file mode 100644
index 0000000..8d0a603
--- /dev/null
+++ b/mcop/asyncstream.h
@@ -0,0 +1,103 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ASYNCSTREAM_H
+#define ASYNCSTREAM_H
+
+#include "arts_export.h"
+#include "buffer.h"
+#include "datapacket.h"
+
+/*
+ * BC - Status (2002-03-08): GenericAsyncStream, AsyncStream,
+ * FloatAsyncStream/ByteAsyncStream
+ *
+ * These classes are to be treated with extreme care, as they are used in
+ * all kinds of relations with the flow system and the generated code. Do
+ * NOT touch unless you REALLY know what you are doing. For further
+ * extensibility, GenericAsyncStream features a private d pointer.
+ */
+
+namespace Arts {
+
+class GenericAsyncStreamPrivate;
+
+class ARTS_EXPORT GenericAsyncStream {
+private:
+ GenericAsyncStreamPrivate *d; // unused
+public:
+ /**
+ * interface to create packets and to get rid of them
+ */
+ virtual GenericDataPacket *createPacket(int capacity) = 0;
+ virtual void freePacket(GenericDataPacket *packet) = 0;
+
+ virtual GenericAsyncStream *createNewStream() = 0;
+
+ GenericDataChannel *channel;
+ int _notifyID;
+
+ inline int notifyID() { return _notifyID; }
+};
+
+template<class T>
+class AsyncStream : public GenericAsyncStream {
+protected:
+ GenericDataPacket *createPacket(int capacity)
+ {
+ return allocPacket(capacity);
+ }
+ void freePacket(GenericDataPacket *packet)
+ {
+ delete packet;
+ }
+public:
+ // for outgoing streams
+ virtual DataPacket<T> *allocPacket(int capacity) = 0;
+
+ inline void setPull(int packets, int capacity)
+ {
+ channel->setPull(packets,capacity);
+ }
+ inline void endPull()
+ {
+ channel->endPull();
+ }
+};
+
+class ARTS_EXPORT FloatAsyncStream : public AsyncStream<float>
+{
+public:
+ DataPacket<float> *allocPacket(int capacity);
+ GenericAsyncStream *createNewStream();
+};
+
+class ARTS_EXPORT ByteAsyncStream : public AsyncStream<mcopbyte>
+{
+public:
+ DataPacket<mcopbyte> *allocPacket(int capacity);
+ GenericAsyncStream *createNewStream();
+};
+
+}
+
+#endif /* ASYNCSTREAM_H */
diff --git a/mcop/buffer.cc b/mcop/buffer.cc
new file mode 100644
index 0000000..de21b3e
--- /dev/null
+++ b/mcop/buffer.cc
@@ -0,0 +1,386 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "buffer.h"
+#include <assert.h>
+#include <string.h>
+
+using namespace std;
+using namespace Arts;
+
+Buffer::Buffer() : rpos(0), _readError(false),d(0)
+{
+ contents.reserve(128);
+}
+
+Buffer::~Buffer()
+{
+}
+
+long Buffer::size()
+{
+ return contents.size();
+}
+
+long Buffer::remaining()
+{
+ return size()-rpos;
+}
+
+bool Buffer::readError() {
+ return _readError;
+}
+
+void Buffer::writeBool(bool b) {
+ contents.push_back(b?1:0);
+}
+
+void Buffer::writeByte(mcopbyte b) {
+ contents.push_back(b);
+}
+
+void Buffer::writeLong(long l) {
+ contents.push_back((l >> 24) & 0xff);
+ contents.push_back((l >> 16) & 0xff);
+ contents.push_back((l >> 8) & 0xff);
+ contents.push_back(l & 0xff);
+}
+
+void Buffer::writeBoolSeq(const vector<bool>& seq) {
+ writeLong(seq.size());
+
+ vector<bool>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeBool(*i);
+}
+
+void Buffer::writeByteSeq(const vector<mcopbyte>& seq) {
+ writeLong(seq.size()); // bytes are sent raw, so we can call read here
+ write(seq);
+}
+
+void Buffer::writeLongSeq(const vector<long>& seq) {
+ writeLong(seq.size());
+
+ vector<long>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeLong(*i);
+}
+
+void Buffer::writeFloat(float f) {
+ // FIXME: on some machines this may fail badly (there is explicit
+ // float marshalling and demarshalling code in mico/orb/util.cc)
+ union { float f; long l; } u = {f};
+ writeLong(u.l);
+}
+
+void Buffer::writeFloatSeq(const std::vector<float>& seq) {
+ writeLong(seq.size());
+
+ vector<float>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeFloat(*i);
+}
+
+void Buffer::writeString(const string& s) {
+ long len = s.size()+1;
+
+ writeLong(len);
+ contents.insert(contents.end(),reinterpret_cast<const unsigned char*>(s.c_str()),
+ reinterpret_cast<const unsigned char*>(s.c_str()+len));
+}
+
+void Buffer::writeStringSeq(const vector<string>& seq) {
+ writeLong(seq.size());
+
+ vector<string>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeString(*i);
+}
+
+void Buffer::write(void *data, long len) {
+ unsigned char *c = (unsigned char *)data;
+
+ contents.insert(contents.end(),c,c+len);
+}
+
+void Buffer::write(const vector<mcopbyte>& raw)
+{
+ contents.insert(contents.end(), raw.begin(), raw.end());
+}
+
+void Buffer::read(vector<mcopbyte>& raw, long l)
+{
+ if(l >= 0 && remaining() >= l) {
+ raw.clear();
+ raw.insert(raw.end(), contents.begin()+rpos, contents.begin()+rpos+l);
+ rpos += l;
+ } else {
+ _readError = true;
+ }
+}
+
+void *Buffer::read(long l) {
+ void *result = 0;
+
+ if(l >= 0 && remaining() >= l) {
+ result = &contents[rpos];
+ rpos += l;
+ } else {
+ _readError = true;
+ }
+ return result;
+}
+
+void *Buffer::peek(long l) {
+ assert(l >= 0 && remaining() >= l);
+ return &contents[rpos];
+}
+
+void Buffer::skip(long l) {
+ if(l >= 0 && remaining() >= l) {
+ rpos += l;
+ } else {
+ _readError = true;
+ }
+}
+
+void Buffer::rewind() {
+ rpos = 0;
+}
+
+bool Buffer::readBool()
+{
+ long result = false;
+ if(remaining() >= 1) {
+ if(contents[rpos] == 1)
+ result = true;
+ else
+ {
+ assert(contents[rpos] == 0);
+ }
+ rpos += 1;
+ } else {
+ _readError = true;
+ }
+ return result;
+}
+
+void Buffer::readBoolSeq(vector<bool>& result)
+{
+ // might be optimizable a bit
+ long i,seqlen = readLong();
+
+ result.clear();
+ if(seqlen >= 0 && remaining() >= seqlen)
+ {
+ for(i=0;i<seqlen;i++) result.push_back(readBool());
+ }
+ else
+ {
+ _readError = true;
+ }
+}
+
+
+mcopbyte Buffer::readByte()
+{
+ if(remaining() >= 1)
+ {
+ return contents[rpos++];
+ }
+ else
+ {
+ _readError = true;
+ return 0;
+ }
+}
+
+void Buffer::readByteSeq(vector<mcopbyte>& result)
+{
+ long seqlen = readLong(); // bytes are sent raw, so we can call read here
+ read(result, seqlen);
+}
+
+long Buffer::readLong()
+{
+ long result = 0;
+ if(remaining() >= 4) {
+ result = (contents[rpos] << 24)
+ + (contents[rpos+1] << 16)
+ + (contents[rpos+2] << 8)
+ + contents[rpos+3];
+ rpos += 4;
+ } else {
+ _readError = true;
+ }
+ return result;
+}
+
+void Buffer::readLongSeq(vector<long>& result)
+{
+ // might be optimizable a bit
+ long i,seqlen = readLong();
+
+ result.clear();
+ if(seqlen * 4 >= 0 && remaining() >= seqlen * 4)
+ {
+ for(i=0;i<seqlen;i++) result.push_back(readLong());
+ }
+ else
+ {
+ _readError = true;
+ }
+}
+
+float Buffer::readFloat()
+{
+ // FIXME: see writeFloat()
+ union {float f; long l; } u;
+ u.l = readLong();
+
+ if(!_readError) return u.f;
+ return 0.0;
+}
+
+void Buffer::readFloatSeq(vector<float>& result)
+{
+ // might be optimizable a bit
+ long i,seqlen = readLong();
+
+ result.clear();
+ if(seqlen * 4 >= 0 && remaining() >= seqlen * 4)
+ {
+ for(i=0;i<seqlen;i++) result.push_back(readFloat());
+ }
+ else
+ {
+ _readError = true;
+ }
+}
+
+void Buffer::readString(string& result)
+{
+ long len = readLong();
+ char *data = (char *)read(len);
+
+ if(data && len)
+ result.assign(data,len-1);
+ else
+ result = "";
+}
+
+void Buffer::readStringSeq(vector<string>& result)
+{
+ // might be optimizable a bit
+
+ long i,seqlen = readLong();
+
+ result.clear();
+ //result.reserve(seqlen);
+
+ for(i=0;i<seqlen;i++) {
+ string s;
+
+ readString(s);
+ if(_readError) return;
+
+ result.push_back(s);
+ }
+}
+
+
+void Buffer::patchLength()
+{
+ long len = size();
+ assert(len >= 8);
+
+ contents[4] = (len >> 24) & 0xff;
+ contents[5] = (len >> 16) & 0xff;
+ contents[6] = (len >> 8) & 0xff;
+ contents[7] = len & 0xff;
+}
+
+void Buffer::patchLong(long position, long value)
+{
+ long len = size();
+ assert(len >= position+4);
+
+ contents[position] = (value >> 24) & 0xff;
+ contents[position+1] = (value >> 16) & 0xff;
+ contents[position+2] = (value >> 8) & 0xff;
+ contents[position+3] = value & 0xff;
+}
+
+string Buffer::toString(const string& name)
+{
+ string result;
+ char hex[17] = "0123456789abcdef";
+
+ vector<unsigned char>::iterator ci;
+ for(ci = contents.begin(); ci != contents.end(); ci++)
+ {
+ result += hex[(*ci >> 4) & 0xf];
+ result += hex[*ci & 0xf];
+ }
+
+ if(name.empty()) return result;
+ return name + ":" + result;
+}
+
+unsigned char Buffer::fromHexNibble(char c)
+{
+ int uc = (unsigned char)c;
+
+ if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0';
+ if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a';
+ if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A';
+
+ return 16; // error
+}
+
+static int stringncmp(const string& s1, const string& s2, size_t n)
+{
+ // I don't know a way to implement that compliant to all STL string
+ // implementations (compare seems to work differently sometimes)
+ return strncmp(s1.c_str(),s2.c_str(),n);
+}
+
+bool Buffer::fromString(const string& data, const string& name)
+{
+ string start = name+":";
+ if(name.empty()) start = "";
+
+ if(stringncmp(data,start,start.size()) != 0) return false;
+ contents.clear();
+
+ string::const_iterator di = data.begin() + start.size();
+
+ while(di != data.end())
+ {
+ unsigned char h = fromHexNibble(*di++); // high nibble
+ if(di == data.end()) return false;
+
+ unsigned char l = fromHexNibble(*di++); // low nibble
+
+ if(h >= 16 || l >= 16) return false; // no proper hex digit
+ contents.push_back((h << 4) + l);
+ }
+ return true;
+}
+
diff --git a/mcop/buffer.h b/mcop/buffer.h
new file mode 100644
index 0000000..b361092
--- /dev/null
+++ b/mcop/buffer.h
@@ -0,0 +1,104 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include <string>
+#include <vector>
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): Buffer.
+ *
+ * Has to be kept binary compatible. As buffer is speed relevant, currently
+ * there are no private d ptrs, and the idea is to keep this as possible.
+ *
+ * If not, put additional stuff in the d ptr, but keep as much data as
+ * possible in the main items.
+ */
+
+namespace Arts {
+
+#ifndef MCOPBYTE_DEFINED
+#define MCOPBYTE_DEFINED
+typedef unsigned char mcopbyte;
+#endif
+
+class BufferPrivate;
+
+class ARTS_EXPORT Buffer {
+private:
+ long rpos;
+ bool _readError;
+ std::vector<unsigned char> contents;
+
+ BufferPrivate *d; // unused
+ unsigned char fromHexNibble(char c);
+
+public:
+ Buffer();
+ ~Buffer();
+
+ bool readError();
+ void writeBool(bool b);
+ void writeBoolSeq(const std::vector<bool>& seq);
+ void writeByte(mcopbyte b);
+ void writeByteSeq(const std::vector<mcopbyte>& seq);
+ void writeLong(long l);
+ void writeLongSeq(const std::vector<long>& seq);
+ void writeFloat(float f);
+ void writeFloatSeq(const std::vector<float>& seq);
+ void writeString(const std::string& s);
+ void writeStringSeq(const std::vector<std::string>& seq);
+
+ long size();
+ long remaining();
+ void *read(long l);
+ void read(std::vector<mcopbyte>& raw, long l);
+ void *peek(long l);
+ void skip(long l);
+ void rewind();
+
+ void write(void *data, long l);
+ void write(const std::vector<mcopbyte>& raw);
+
+ bool readBool();
+ void readBoolSeq(std::vector<bool>& result);
+ mcopbyte readByte();
+ void readByteSeq(std::vector<mcopbyte>& result);
+ long readLong();
+ void readLongSeq(std::vector<long>& result);
+ float readFloat();
+ void readFloatSeq(std::vector<float>& result);
+ void readString(std::string& result);
+ void readStringSeq(std::vector<std::string>& result);
+
+ void patchLength();
+ void patchLong(long position, long value);
+
+ std::string toString(const std::string& name);
+ bool fromString(const std::string& data, const std::string& name);
+};
+
+}
+
+#endif
diff --git a/mcop/common.h b/mcop/common.h
new file mode 100644
index 0000000..4021fb9
--- /dev/null
+++ b/mcop/common.h
@@ -0,0 +1,141 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "buffer.h"
+#include "type.h"
+#include "dispatcher.h"
+#include "object.h"
+#include "connection.h"
+#include "objectmanager.h"
+#include "idlfilereg.h"
+#include "asyncstream.h"
+#include "mcoputils.h"
+#include "anyref.h"
+#include "connect.h"
+
+/*
+ * BC - Status (2002-03-08): Read/WriteObject(Seq)
+ *
+ * Will be kept binary compatible by NOT TOUCHING AT ALL. Do not change this.
+ * (Interaction with generated code).
+ */
+
+/* define this to see what mcop transfers around */
+#undef DEBUG_IO
+
+/* define this to see what mcop messages are processed */
+#undef DEBUG_MESSAGES
+
+#include "core.h"
+
+namespace Arts {
+/* some marshalling helpers */
+
+template<class T>
+void readTypeSeq(Buffer& stream, std::vector<T>& sequence) {
+ sequence.clear();
+
+ unsigned long l = stream.readLong();
+ while(l--) sequence.push_back(T(stream));
+}
+
+template<class T>
+void writeTypeSeq(Buffer& stream, const std::vector<T>& sequence) {
+ stream.writeLong(sequence.size());
+ for(unsigned long l=0;l<sequence.size();l++)
+ sequence[l].writeType(stream);
+}
+
+template<class T>
+void writeObject(Buffer& stream, T* object) {
+ if(object)
+ {
+ /*
+ * perhaps reimplement directly (without conversion to/from string)
+ * for more speed
+ */
+
+ std::string s = object->_toString();
+
+ Buffer buffer;
+ buffer.fromString(s,"MCOP-Object");
+ ObjectReference reference(buffer);
+
+ object->_copyRemote(); // prevents that the object is freed for a while
+ reference.writeType(stream);
+ }
+ else
+ {
+ ObjectReference null_reference;
+
+ null_reference.serverID = "null";
+ null_reference.objectID = 0;
+ null_reference.writeType(stream);
+ }
+}
+
+template<class T>
+void readObject(Buffer& stream, T*& result) {
+ ObjectReference reference(stream);
+
+ if(reference.serverID == "null")
+ result = 0; // null reference?
+ else
+ result = T::_fromReference(reference,false);
+}
+
+template<class T>
+void readObjectSeq(Buffer& stream, std::vector<T>& sequence)
+{
+ sequence.clear();
+
+ unsigned long l = stream.readLong();
+ while(l--)
+ {
+ typename T::_base_class *temp;
+ readObject(stream, temp);
+ sequence.push_back(T::_from_base(temp));
+ }
+}
+
+template<class T>
+void writeObjectSeq(Buffer& stream, const std::vector<T>& sequence)
+{
+ stream.writeLong(sequence.size());
+
+ for(unsigned long l=0;l<sequence.size();l++)
+ {
+ T object = sequence[l];
+ writeObject(stream,object._base());
+ }
+}
+
+#ifndef MCOPBYTE_DEFINED
+#define MCOPBYTE_DEFINED
+typedef unsigned char mcopbyte;
+#endif
+
+}
+#endif
diff --git a/mcop/connect.cc b/mcop/connect.cc
new file mode 100644
index 0000000..88d5dff
--- /dev/null
+++ b/mcop/connect.cc
@@ -0,0 +1,149 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu
+ nicolas.brodu@free.fr
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "connect.h"
+#include "flowsystem.h"
+#include <assert.h>
+#include "debug.h"
+
+// NDEBUG is the symbol name that can remove the assertions
+#ifdef NDEBUG
+#define mywarning(a,b)
+#else
+#include <iostream>
+#define mywarning(a,b) if (!(a)) arts_warning("MCOP connection warning: %s",b)
+#endif
+
+using namespace std;
+
+namespace Arts {
+
+// Connect function overloaded for objects with default port
+void connect(const Object& src, const std::string& output, const Object& dest, const std::string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ node->connect(output, dest._node(), input);
+}
+
+void connect(const Object& src, const string& output, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsIn.size() == 1, "default input not found in void connect(const Object& src, const string& output, const Object& dest);");
+ node->connect(output, dest._node(), portsIn[0]);
+}
+
+void connect(const Object& src, const Object& dest, const string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ mywarning(portsOut.size() == 1, "default output not found in void connect(const Object& src, const Object& dest, const string& input);");
+ node->connect(portsOut[0], dest._node(), input);
+}
+
+void connect(const Object& src, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsOut.size() == portsIn.size(), "number of defaults for src and dest don't match in void connect(const Object& src, const Object& dest);");
+ mywarning(!portsOut.empty(), "no defaults for src and dest in void connect(const Object& src, const Object& dest);");
+ vector<std::string>::iterator ot = portsOut.begin();
+ vector<std::string>::iterator it = portsIn.begin();
+ for (; ot != portsOut.end(); it++, ot++) {
+ node->connect(*ot, dest._node(), *it);
+ }
+}
+
+void disconnect(const Object& src, const std::string& output, const Object& dest, const std::string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ node->disconnect(output, dest._node(), input);
+}
+
+void disconnect(const Object& src, const string& output, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsIn.size() == 1, "default input not found in void disconnect(const Object& src, const string& output, const Object& dest);");
+ node->disconnect(output, dest._node(), portsIn[0]);
+}
+
+void disconnect(const Object& src, const Object& dest, const string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ mywarning(portsOut.size() == 1, "default output not found in void disconnect(const Object& src, const Object& dest, const string& input);");
+ node->disconnect(portsOut[0], dest._node(), input);
+}
+
+void disconnect(const Object& src, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsOut.size() == portsIn.size(), "number of defaults for src and dest don't match in void disconnect(const Object& src, const Object& dest);");
+ mywarning(!portsOut.empty(), "no defaults for src and dest in void disconnect(const Object& src, const Object& dest);");
+ vector<std::string>::iterator ot = portsOut.begin();
+ vector<std::string>::iterator it = portsIn.begin();
+ for (; ot != portsOut.end(); it++, ot++) {
+ node->disconnect(*ot, dest._node(), *it);
+ }
+}
+
+// setValue function overloaded for objects with default port
+void setValue(const Object& c, const std::string& port, const float fvalue)
+{
+ ScheduleNode *node = c._node();
+ assert(node);
+ node->setFloatValue(port, fvalue);
+}
+
+void setValue(const Object& c, const float fvalue)
+{
+ ScheduleNode *node = c._node();
+ assert(node);
+ vector<std::string> portsIn = c._defaultPortsIn();
+ mywarning(!portsIn.empty(), "c has no default ports in void setValue(const Object& c, const float fvalue);");
+ vector<std::string>::iterator it = portsIn.begin();
+ for (; it != portsIn.end(); it++) {
+ node->setFloatValue(*it, fvalue);
+ }
+}
+
+/* String values???
+void setValue(Object& c, const string& port, const string& svalue)
+{
+}
+
+void setValue(Object& c, const string& svalue)
+{
+}
+*/
+
+}
diff --git a/mcop/connect.h b/mcop/connect.h
new file mode 100644
index 0000000..f9db8b5
--- /dev/null
+++ b/mcop/connect.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu
+ nicolas.brodu@free.fr
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef MCOP_CONNECT_H
+#define MCOP_CONNECT_H
+
+/*
+ * BC - Status (2002-03-08): connect / setValue functions
+ *
+ * Will be kept as they are (binary compatible).
+ */
+
+#include <string>
+#include "arts_export.h"
+
+namespace Arts {
+class Object;
+
+// Connect function overloaded for components with default port
+void ARTS_EXPORT connect(const Object& src, const std::string& output, const Object& dest, const std::string& input);
+void ARTS_EXPORT connect(const Object& src, const std::string& output, const Object& dest);
+void ARTS_EXPORT connect(const Object& src, const Object& dest, const std::string& input);
+void ARTS_EXPORT connect(const Object& src, const Object& dest);
+// Same for disconnect function
+void ARTS_EXPORT disconnect(const Object& src, const std::string& output, const Object& dest, const std::string& input);
+void ARTS_EXPORT disconnect(const Object& src, const std::string& output, const Object& dest);
+void ARTS_EXPORT disconnect(const Object& src, const Object& dest, const std::string& input);
+void ARTS_EXPORT disconnect(const Object& src, const Object& dest);
+
+// setValue function overloaded for components with default port
+void ARTS_EXPORT setValue(const Object& c, const std::string& port, const float fvalue);
+void ARTS_EXPORT setValue(const Object& c, const float fvalue);
+//void setValue(const Object& c, const std::string& port, const std::string& svalue);
+//void setValue(const Object& c, const std::string& svalue);
+
+}
+
+#endif
diff --git a/mcop/connection.cc b/mcop/connection.cc
new file mode 100644
index 0000000..49221f9
--- /dev/null
+++ b/mcop/connection.cc
@@ -0,0 +1,196 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "connection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include <stdio.h>
+#include <string.h> // for Solaris
+#include <queue>
+#include <algorithm>
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+class ConnectionPrivate {
+public:
+ struct Data {
+ Data() : data(0), len(0) { }
+ Data(unsigned char *data, long len) : data(data), len(len) { }
+ Data(const Data& d) : data(d.data), len(d.len) { }
+ unsigned char *data;
+ long len;
+ };
+
+ queue<Data> incoming;
+ map<string,string> hints;
+};
+}
+
+Connection::Connection() :d(new ConnectionPrivate), _refCnt(1)
+{
+ _connState = unknown;
+}
+
+Connection::~Connection()
+{
+ assert(d->incoming.empty());
+ assert(_refCnt == 0);
+
+ delete d;
+}
+
+void Connection::_copy()
+{
+ assert(_refCnt > 0);
+ _refCnt++;
+}
+
+void Connection::_release()
+{
+ assert(_refCnt > 0);
+ _refCnt--;
+ if(_refCnt == 0)
+ delete this;
+}
+
+void Connection::initReceive()
+{
+ rcbuf = 0;
+ receiveHeader = true;
+ remaining = 12;
+}
+
+void Connection::receive(unsigned char *newdata, long newlen)
+{
+ /*
+ * protect against being freed while receive is running, as there are a
+ * few points where reentrant event loops may happen (Dispatcher::handle)
+ */
+ _copy();
+
+ d->incoming.push(ConnectionPrivate::Data(newdata,newlen));
+
+ do
+ {
+ ConnectionPrivate::Data &data = d->incoming.front();
+
+ // get a buffer for the incoming message
+ if(!rcbuf) rcbuf = new Buffer;
+
+ // put a suitable amount of input data into the receive buffer
+ long len = min(remaining, data.len);
+
+ remaining -= len;
+ rcbuf->write(data.data,len);
+
+ data.len -= len;
+ data.data += len;
+
+ if(data.len == 0)
+ d->incoming.pop();
+
+ // look if it was enough to do something useful with it
+ if(remaining == 0)
+ {
+ if(receiveHeader)
+ {
+ long mcopMagic;
+
+ mcopMagic = rcbuf->readLong();
+ remaining = rcbuf->readLong() - 12;
+ messageType = rcbuf->readLong();
+
+ if(_connState != Connection::established
+ && (remaining >= 4096 || remaining < 0))
+ {
+ /*
+ * don't accept large amounts of data on unauthenticated
+ * connections
+ */
+ remaining = 0;
+ }
+
+ if(mcopMagic == MCOP_MAGIC)
+ {
+ // do we need to receive more data (message body?)
+ if(remaining)
+ {
+ receiveHeader = false;
+ }
+ else
+ {
+ Buffer *received = rcbuf;
+ initReceive();
+ Dispatcher::the()->handle(this,received,messageType);
+ }
+ }
+ else
+ {
+ initReceive();
+ Dispatcher::the()->handleCorrupt(this);
+ }
+ }
+ else
+ {
+ Buffer *received = rcbuf;
+
+ /*
+ * it's important to prepare to receive new messages *before*
+ * calling Dispatcher::the()->handle(...), as handle may
+ * get into an I/O situation (e.g. when doing an invocation
+ * itself), and we may receive more messages while handle is
+ * running
+ */
+ initReceive();
+
+ // rcbuf is consumed by the dispatcher
+ Dispatcher::the()->handle(this,received,messageType);
+ }
+ }
+ } while(!d->incoming.empty());
+
+ _release();
+}
+
+void Connection::setHints(const vector<string>& hints)
+{
+ vector<string>::const_iterator i;
+
+ for(i = hints.begin(); i != hints.end(); i++)
+ {
+ string key;
+ vector<string> values;
+
+ if(MCOPUtils::tokenize(*i, key, values))
+ {
+ if(values.size() == 1)
+ d->hints[key] = values[0];
+ }
+ }
+}
+
+string Connection::findHint(const string& hint)
+{
+ return d->hints[hint];
+}
diff --git a/mcop/connection.h b/mcop/connection.h
new file mode 100644
index 0000000..db7edf0
--- /dev/null
+++ b/mcop/connection.h
@@ -0,0 +1,100 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+#include "arts_export.h"
+#include "buffer.h"
+
+/*
+ * BC - Status (2002-03-08): Connection.
+ *
+ * None of these classes is considered part of the public API. However, they
+ * NEED to be kept binary compatible as the DO interact with generated code.
+ *
+ * Especially virtual functions and stuff can't be added, if you need to,
+ * you need to add classes parallel to the Connection hierarchy.
+ */
+
+namespace Arts {
+
+class ConnectionPrivate;
+
+class ARTS_EXPORT Connection {
+private:
+ ConnectionPrivate *d; // unused
+public:
+ enum ConnectionState {
+ unknown = 0,
+ expectServerHello = 1,
+ expectClientHello = 2,
+ expectAuthAccept = 3,
+ established = 4
+ };
+protected:
+ Buffer *rcbuf;
+ bool receiveHeader;
+ long remaining;
+ long messageType;
+ ConnectionState _connState;
+ std::string serverID;
+ std::string _cookie;
+
+ long _refCnt;
+
+ /**
+ * If you don't want to handle message fragmentation yourself:
+ *
+ * Call initReceive in your derived Connection constructor, ald
+ * receive as soon as you receive some data - the connection object
+ * will handle the rest (put the messages into buffers and send them
+ * to the dispatcher)
+ */
+ void initReceive();
+ void receive(unsigned char *data, long len);
+
+ virtual ~Connection();
+public:
+ Connection();
+
+ inline void setServerID(const std::string& _serverID) { serverID = _serverID; }
+ inline bool isConnected(const std::string& s) { return (serverID == s); }
+ inline void setConnState(ConnectionState cs) { _connState = cs; };
+
+ inline std::string cookie() { return _cookie; }
+ void setCookie(const std::string& c) { _cookie = c; }
+ void setHints(const std::vector<std::string>& hints);
+ std::string findHint(const std::string& name);
+
+ inline ConnectionState connState() { return _connState; };
+ virtual void drop() = 0;
+ virtual bool broken() = 0;
+ virtual void qSendBuffer(Buffer *buffer) = 0;
+
+ void _release();
+ void _copy();
+};
+
+}
+
+#endif
diff --git a/mcop/core.cc b/mcop/core.cc
new file mode 100644
index 0000000..b0d48eb
--- /dev/null
+++ b/mcop/core.cc
@@ -0,0 +1,3191 @@
+/* this file was generated by the MCOP idl compiler - DO NOT EDIT */
+
+#include "common.h"
+
+// Implementation
+Arts::Header::Header()
+{
+}
+
+Arts::Header::Header(Arts::HeaderMagic _a_magic, long _a_messageLength, Arts::MessageType _a_messageType)
+{
+ this->magic = _a_magic;
+ this->messageLength = _a_messageLength;
+ this->messageType = _a_messageType;
+}
+
+Arts::Header::Header(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::Header::Header(const Arts::Header& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::Header& Arts::Header::operator=(const Arts::Header& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::Header::readType(Arts::Buffer& stream)
+{
+ magic = (Arts::HeaderMagic)stream.readLong();
+ messageLength = stream.readLong();
+ messageType = (Arts::MessageType)stream.readLong();
+}
+
+void Arts::Header::writeType(Arts::Buffer& stream) const
+{
+ stream.writeLong(magic);
+ stream.writeLong(messageLength);
+ stream.writeLong(messageType);
+}
+
+std::string Arts::Header::_typeName() const
+{
+ return "Arts::Header";
+}
+
+Arts::Invocation::Invocation()
+{
+}
+
+Arts::Invocation::Invocation(long _a_objectID, long _a_methodID, long _a_requestID)
+{
+ this->objectID = _a_objectID;
+ this->methodID = _a_methodID;
+ this->requestID = _a_requestID;
+}
+
+Arts::Invocation::Invocation(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::Invocation::Invocation(const Arts::Invocation& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::Invocation& Arts::Invocation::operator=(const Arts::Invocation& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::Invocation::readType(Arts::Buffer& stream)
+{
+ objectID = stream.readLong();
+ methodID = stream.readLong();
+ requestID = stream.readLong();
+}
+
+void Arts::Invocation::writeType(Arts::Buffer& stream) const
+{
+ stream.writeLong(objectID);
+ stream.writeLong(methodID);
+ stream.writeLong(requestID);
+}
+
+std::string Arts::Invocation::_typeName() const
+{
+ return "Arts::Invocation";
+}
+
+Arts::OnewayInvocation::OnewayInvocation()
+{
+}
+
+Arts::OnewayInvocation::OnewayInvocation(long _a_objectID, long _a_methodID)
+{
+ this->objectID = _a_objectID;
+ this->methodID = _a_methodID;
+}
+
+Arts::OnewayInvocation::OnewayInvocation(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::OnewayInvocation::OnewayInvocation(const Arts::OnewayInvocation& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::OnewayInvocation& Arts::OnewayInvocation::operator=(const Arts::OnewayInvocation& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::OnewayInvocation::readType(Arts::Buffer& stream)
+{
+ objectID = stream.readLong();
+ methodID = stream.readLong();
+}
+
+void Arts::OnewayInvocation::writeType(Arts::Buffer& stream) const
+{
+ stream.writeLong(objectID);
+ stream.writeLong(methodID);
+}
+
+std::string Arts::OnewayInvocation::_typeName() const
+{
+ return "Arts::OnewayInvocation";
+}
+
+Arts::ServerHello::ServerHello()
+{
+}
+
+Arts::ServerHello::ServerHello(const std::string& _a_mcopVersion, const std::string& _a_serverID, const std::vector<std::string>& _a_authProtocols, const std::string& _a_authSeed)
+{
+ this->mcopVersion = _a_mcopVersion;
+ this->serverID = _a_serverID;
+ this->authProtocols = _a_authProtocols;
+ this->authSeed = _a_authSeed;
+}
+
+Arts::ServerHello::ServerHello(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ServerHello::ServerHello(const Arts::ServerHello& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ServerHello& Arts::ServerHello::operator=(const Arts::ServerHello& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ServerHello::readType(Arts::Buffer& stream)
+{
+ stream.readString(mcopVersion);
+ stream.readString(serverID);
+ stream.readStringSeq(authProtocols);
+ stream.readString(authSeed);
+}
+
+void Arts::ServerHello::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(mcopVersion);
+ stream.writeString(serverID);
+ stream.writeStringSeq(authProtocols);
+ stream.writeString(authSeed);
+}
+
+std::string Arts::ServerHello::_typeName() const
+{
+ return "Arts::ServerHello";
+}
+
+Arts::ClientHello::ClientHello()
+{
+}
+
+Arts::ClientHello::ClientHello(const std::string& _a_serverID, const std::string& _a_authProtocol, const std::string& _a_authData)
+{
+ this->serverID = _a_serverID;
+ this->authProtocol = _a_authProtocol;
+ this->authData = _a_authData;
+}
+
+Arts::ClientHello::ClientHello(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ClientHello::ClientHello(const Arts::ClientHello& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ClientHello& Arts::ClientHello::operator=(const Arts::ClientHello& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ClientHello::readType(Arts::Buffer& stream)
+{
+ stream.readString(serverID);
+ stream.readString(authProtocol);
+ stream.readString(authData);
+}
+
+void Arts::ClientHello::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(serverID);
+ stream.writeString(authProtocol);
+ stream.writeString(authData);
+}
+
+std::string Arts::ClientHello::_typeName() const
+{
+ return "Arts::ClientHello";
+}
+
+Arts::AuthAccept::AuthAccept()
+{
+}
+
+Arts::AuthAccept::AuthAccept(const std::vector<std::string>& _a_hints)
+{
+ this->hints = _a_hints;
+}
+
+Arts::AuthAccept::AuthAccept(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::AuthAccept::AuthAccept(const Arts::AuthAccept& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::AuthAccept& Arts::AuthAccept::operator=(const Arts::AuthAccept& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::AuthAccept::readType(Arts::Buffer& stream)
+{
+ stream.readStringSeq(hints);
+}
+
+void Arts::AuthAccept::writeType(Arts::Buffer& stream) const
+{
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::AuthAccept::_typeName() const
+{
+ return "Arts::AuthAccept";
+}
+
+Arts::ObjectReference::ObjectReference()
+{
+}
+
+Arts::ObjectReference::ObjectReference(const std::string& _a_serverID, long _a_objectID, const std::vector<std::string>& _a_urls)
+{
+ this->serverID = _a_serverID;
+ this->objectID = _a_objectID;
+ this->urls = _a_urls;
+}
+
+Arts::ObjectReference::ObjectReference(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ObjectReference::ObjectReference(const Arts::ObjectReference& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ObjectReference& Arts::ObjectReference::operator=(const Arts::ObjectReference& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ObjectReference::readType(Arts::Buffer& stream)
+{
+ stream.readString(serverID);
+ objectID = stream.readLong();
+ stream.readStringSeq(urls);
+}
+
+void Arts::ObjectReference::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(serverID);
+ stream.writeLong(objectID);
+ stream.writeStringSeq(urls);
+}
+
+std::string Arts::ObjectReference::_typeName() const
+{
+ return "Arts::ObjectReference";
+}
+
+Arts::ParamDef::ParamDef()
+{
+}
+
+Arts::ParamDef::ParamDef(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints)
+{
+ this->type = _a_type;
+ this->name = _a_name;
+ this->hints = _a_hints;
+}
+
+Arts::ParamDef::ParamDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ParamDef::ParamDef(const Arts::ParamDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ParamDef& Arts::ParamDef::operator=(const Arts::ParamDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ParamDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(type);
+ stream.readString(name);
+ stream.readStringSeq(hints);
+}
+
+void Arts::ParamDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(type);
+ stream.writeString(name);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::ParamDef::_typeName() const
+{
+ return "Arts::ParamDef";
+}
+
+Arts::MethodDef::MethodDef()
+{
+}
+
+Arts::MethodDef::MethodDef(const std::string& _a_name, const std::string& _a_type, Arts::MethodType _a_flags, const std::vector<Arts::ParamDef>& _a_signature, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->type = _a_type;
+ this->flags = _a_flags;
+ this->signature = _a_signature;
+ this->hints = _a_hints;
+}
+
+Arts::MethodDef::MethodDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::MethodDef::MethodDef(const Arts::MethodDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::MethodDef& Arts::MethodDef::operator=(const Arts::MethodDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::MethodDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ stream.readString(type);
+ flags = (Arts::MethodType)stream.readLong();
+ Arts::readTypeSeq(stream,signature);
+ stream.readStringSeq(hints);
+}
+
+void Arts::MethodDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeString(type);
+ stream.writeLong(flags);
+ Arts::writeTypeSeq(stream,signature);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::MethodDef::_typeName() const
+{
+ return "Arts::MethodDef";
+}
+
+Arts::AttributeDef::AttributeDef()
+{
+}
+
+Arts::AttributeDef::AttributeDef(const std::string& _a_name, const std::string& _a_type, Arts::AttributeType _a_flags, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->type = _a_type;
+ this->flags = _a_flags;
+ this->hints = _a_hints;
+}
+
+Arts::AttributeDef::AttributeDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::AttributeDef::AttributeDef(const Arts::AttributeDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::AttributeDef& Arts::AttributeDef::operator=(const Arts::AttributeDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::AttributeDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ stream.readString(type);
+ flags = (Arts::AttributeType)stream.readLong();
+ stream.readStringSeq(hints);
+}
+
+void Arts::AttributeDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeString(type);
+ stream.writeLong(flags);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::AttributeDef::_typeName() const
+{
+ return "Arts::AttributeDef";
+}
+
+Arts::InterfaceDef::InterfaceDef()
+{
+}
+
+Arts::InterfaceDef::InterfaceDef(const std::string& _a_name, const std::vector<std::string>& _a_inheritedInterfaces, const std::vector<Arts::MethodDef>& _a_methods, const std::vector<Arts::AttributeDef>& _a_attributes, const std::vector<std::string>& _a_defaultPorts, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->inheritedInterfaces = _a_inheritedInterfaces;
+ this->methods = _a_methods;
+ this->attributes = _a_attributes;
+ this->defaultPorts = _a_defaultPorts;
+ this->hints = _a_hints;
+}
+
+Arts::InterfaceDef::InterfaceDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::InterfaceDef::InterfaceDef(const Arts::InterfaceDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::InterfaceDef& Arts::InterfaceDef::operator=(const Arts::InterfaceDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::InterfaceDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ stream.readStringSeq(inheritedInterfaces);
+ Arts::readTypeSeq(stream,methods);
+ Arts::readTypeSeq(stream,attributes);
+ stream.readStringSeq(defaultPorts);
+ stream.readStringSeq(hints);
+}
+
+void Arts::InterfaceDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeStringSeq(inheritedInterfaces);
+ Arts::writeTypeSeq(stream,methods);
+ Arts::writeTypeSeq(stream,attributes);
+ stream.writeStringSeq(defaultPorts);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::InterfaceDef::_typeName() const
+{
+ return "Arts::InterfaceDef";
+}
+
+Arts::TypeComponent::TypeComponent()
+{
+}
+
+Arts::TypeComponent::TypeComponent(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints)
+{
+ this->type = _a_type;
+ this->name = _a_name;
+ this->hints = _a_hints;
+}
+
+Arts::TypeComponent::TypeComponent(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::TypeComponent::TypeComponent(const Arts::TypeComponent& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::TypeComponent& Arts::TypeComponent::operator=(const Arts::TypeComponent& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::TypeComponent::readType(Arts::Buffer& stream)
+{
+ stream.readString(type);
+ stream.readString(name);
+ stream.readStringSeq(hints);
+}
+
+void Arts::TypeComponent::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(type);
+ stream.writeString(name);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::TypeComponent::_typeName() const
+{
+ return "Arts::TypeComponent";
+}
+
+Arts::TypeDef::TypeDef()
+{
+}
+
+Arts::TypeDef::TypeDef(const std::string& _a_name, const std::vector<Arts::TypeComponent>& _a_contents, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->contents = _a_contents;
+ this->hints = _a_hints;
+}
+
+Arts::TypeDef::TypeDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::TypeDef::TypeDef(const Arts::TypeDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::TypeDef& Arts::TypeDef::operator=(const Arts::TypeDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::TypeDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ Arts::readTypeSeq(stream,contents);
+ stream.readStringSeq(hints);
+}
+
+void Arts::TypeDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ Arts::writeTypeSeq(stream,contents);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::TypeDef::_typeName() const
+{
+ return "Arts::TypeDef";
+}
+
+Arts::EnumComponent::EnumComponent()
+{
+}
+
+Arts::EnumComponent::EnumComponent(const std::string& _a_name, long _a_value, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->value = _a_value;
+ this->hints = _a_hints;
+}
+
+Arts::EnumComponent::EnumComponent(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::EnumComponent::EnumComponent(const Arts::EnumComponent& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::EnumComponent& Arts::EnumComponent::operator=(const Arts::EnumComponent& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::EnumComponent::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ value = stream.readLong();
+ stream.readStringSeq(hints);
+}
+
+void Arts::EnumComponent::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeLong(value);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::EnumComponent::_typeName() const
+{
+ return "Arts::EnumComponent";
+}
+
+Arts::EnumDef::EnumDef()
+{
+}
+
+Arts::EnumDef::EnumDef(const std::string& _a_name, const std::vector<Arts::EnumComponent>& _a_contents, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->contents = _a_contents;
+ this->hints = _a_hints;
+}
+
+Arts::EnumDef::EnumDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::EnumDef::EnumDef(const Arts::EnumDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::EnumDef& Arts::EnumDef::operator=(const Arts::EnumDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::EnumDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ Arts::readTypeSeq(stream,contents);
+ stream.readStringSeq(hints);
+}
+
+void Arts::EnumDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ Arts::writeTypeSeq(stream,contents);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::EnumDef::_typeName() const
+{
+ return "Arts::EnumDef";
+}
+
+Arts::ModuleDef::ModuleDef()
+{
+}
+
+Arts::ModuleDef::ModuleDef(const std::string& _a_moduleName, const std::vector<Arts::EnumDef>& _a_enums, const std::vector<Arts::TypeDef>& _a_types, const std::vector<Arts::InterfaceDef>& _a_interfaces, const std::vector<std::string>& _a_hints)
+{
+ this->moduleName = _a_moduleName;
+ this->enums = _a_enums;
+ this->types = _a_types;
+ this->interfaces = _a_interfaces;
+ this->hints = _a_hints;
+}
+
+Arts::ModuleDef::ModuleDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ModuleDef::ModuleDef(const Arts::ModuleDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ModuleDef& Arts::ModuleDef::operator=(const Arts::ModuleDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ModuleDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(moduleName);
+ Arts::readTypeSeq(stream,enums);
+ Arts::readTypeSeq(stream,types);
+ Arts::readTypeSeq(stream,interfaces);
+ stream.readStringSeq(hints);
+}
+
+void Arts::ModuleDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(moduleName);
+ Arts::writeTypeSeq(stream,enums);
+ Arts::writeTypeSeq(stream,types);
+ Arts::writeTypeSeq(stream,interfaces);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::ModuleDef::_typeName() const
+{
+ return "Arts::ModuleDef";
+}
+
+Arts::Any::Any()
+{
+}
+
+Arts::Any::Any(const std::string& _a_type, const std::vector<Arts::mcopbyte>& _a_value)
+{
+ this->type = _a_type;
+ this->value = _a_value;
+}
+
+Arts::Any::Any(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::Any::Any(const Arts::Any& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::Any& Arts::Any::operator=(const Arts::Any& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::Any::readType(Arts::Buffer& stream)
+{
+ stream.readString(type);
+ stream.readByteSeq(value);
+}
+
+void Arts::Any::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(type);
+ stream.writeByteSeq(value);
+}
+
+std::string Arts::Any::_typeName() const
+{
+ return "Arts::Any";
+}
+
+Arts::TraderEntry::TraderEntry()
+{
+}
+
+Arts::TraderEntry::TraderEntry(const std::string& _a_interfaceName, const std::vector<std::string>& _a_lines)
+{
+ this->interfaceName = _a_interfaceName;
+ this->lines = _a_lines;
+}
+
+Arts::TraderEntry::TraderEntry(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::TraderEntry::TraderEntry(const Arts::TraderEntry& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::TraderEntry& Arts::TraderEntry::operator=(const Arts::TraderEntry& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::TraderEntry::readType(Arts::Buffer& stream)
+{
+ stream.readString(interfaceName);
+ stream.readStringSeq(lines);
+}
+
+void Arts::TraderEntry::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(interfaceName);
+ stream.writeStringSeq(lines);
+}
+
+std::string Arts::TraderEntry::_typeName() const
+{
+ return "Arts::TraderEntry";
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::InterfaceRepo_base *castedObject = (Arts::InterfaceRepo_base *)skel->_cast(Arts::InterfaceRepo_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::InterfaceRepo_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::InterfaceRepo_base *castedObject = (Arts::InterfaceRepo_base *)object._base()->_cast(Arts::InterfaceRepo_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::InterfaceRepo_base *result;
+ result = (Arts::InterfaceRepo_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::InterfaceRepo");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::InterfaceRepo_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::InterfaceRepo")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::InterfaceRepo_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::InterfaceRepo_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::InterfaceRepo_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::InterfaceRepo_base::_IID) return (Arts::InterfaceRepo_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::InterfaceRepo_stub::InterfaceRepo_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::InterfaceRepo_stub::InterfaceRepo_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+long Arts::InterfaceRepo_stub::insertModule(const Arts::ModuleDef& newModule)
+{
+ long methodID = _lookupMethodFast("method:0000000d696e736572744d6f64756c6500000000056c6f6e6700000000020000000100000010417274733a3a4d6f64756c65446566000000000a6e65774d6f64756c65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ newModule.writeType(*request);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return 0; // error occurred
+ long returnCode = result->readLong();
+ delete result;
+ return returnCode;
+}
+
+void Arts::InterfaceRepo_stub::removeModule(long moduleID)
+{
+ long methodID = _lookupMethodFast("method:0000000d72656d6f76654d6f64756c650000000005766f6964000000000200000001000000056c6f6e6700000000096d6f64756c654944000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeLong(moduleID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+Arts::InterfaceDef Arts::InterfaceRepo_stub::queryInterface(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000f7175657279496e746572666163650000000013417274733a3a496e7465726661636544656600000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return Arts::InterfaceDef(); // error occurred
+ Arts::InterfaceDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+Arts::TypeDef Arts::InterfaceRepo_stub::queryType(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a717565727954797065000000000e417274733a3a5479706544656600000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return Arts::TypeDef(); // error occurred
+ Arts::TypeDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+Arts::EnumDef Arts::InterfaceRepo_stub::queryEnum(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a7175657279456e756d000000000e417274733a3a456e756d44656600000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return Arts::EnumDef(); // error occurred
+ Arts::EnumDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryChildren(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000e71756572794368696c6472656e00000000082a737472696e6700000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryInterfaces()
+{
+ long methodID = _lookupMethodFast("method:000000107175657279496e746572666163657300000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryTypes()
+{
+ long methodID = _lookupMethodFast("method:0000000b7175657279547970657300000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryEnums()
+{
+ long methodID = _lookupMethodFast("method:0000000b7175657279456e756d7300000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::InterfaceRepo_skel::_interfaceName()
+{
+ return "Arts::InterfaceRepo";
+}
+
+bool Arts::InterfaceRepo_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::InterfaceRepo") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::InterfaceRepo_skel::_interfaceNameSkel()
+{
+ return "Arts::InterfaceRepo";
+}
+
+// insertModule
+static void _dispatch_Arts_InterfaceRepo_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::ModuleDef newModule(*request);
+ result->writeLong(((Arts::InterfaceRepo_skel *)object)->insertModule(newModule));
+}
+
+// removeModule
+static void _dispatch_Arts_InterfaceRepo_01(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ long moduleID = request->readLong();
+ ((Arts::InterfaceRepo_skel *)object)->removeModule(moduleID);
+}
+
+// queryInterface
+static void _dispatch_Arts_InterfaceRepo_02(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::InterfaceDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryInterface(name);
+ _returnCode.writeType(*result);
+}
+
+// queryType
+static void _dispatch_Arts_InterfaceRepo_03(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::TypeDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryType(name);
+ _returnCode.writeType(*result);
+}
+
+// queryEnum
+static void _dispatch_Arts_InterfaceRepo_04(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::EnumDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryEnum(name);
+ _returnCode.writeType(*result);
+}
+
+// queryChildren
+static void _dispatch_Arts_InterfaceRepo_05(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryChildren(name);
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// queryInterfaces
+static void _dispatch_Arts_InterfaceRepo_06(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryInterfaces();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// queryTypes
+static void _dispatch_Arts_InterfaceRepo_07(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryTypes();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// queryEnums
+static void _dispatch_Arts_InterfaceRepo_08(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryEnums();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+void Arts::InterfaceRepo_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000d696e736572744d6f64756c6500000000056c6f6e670000"
+ "0000020000000100000010417274733a3a4d6f64756c65446566000000000a6e65"
+ "774d6f64756c650000000000000000000000000d72656d6f76654d6f64756c6500"
+ "00000005766f6964000000000200000001000000056c6f6e6700000000096d6f64"
+ "756c6549440000000000000000000000000f7175657279496e7465726661636500"
+ "00000013417274733a3a496e746572666163654465660000000002000000010000"
+ "0007737472696e6700000000056e616d650000000000000000000000000a717565"
+ "727954797065000000000e417274733a3a54797065446566000000000200000001"
+ "00000007737472696e6700000000056e616d650000000000000000000000000a71"
+ "75657279456e756d000000000e417274733a3a456e756d44656600000000020000"
+ "000100000007737472696e6700000000056e616d65000000000000000000000000"
+ "0e71756572794368696c6472656e00000000082a737472696e6700000000020000"
+ "000100000007737472696e6700000000056e616d65000000000000000000000000"
+ "107175657279496e746572666163657300000000082a737472696e670000000002"
+ "00000000000000000000000b7175657279547970657300000000082a737472696e"
+ "67000000000200000000000000000000000b7175657279456e756d730000000008"
+ "2a737472696e6700000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_InterfaceRepo_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_03,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_04,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_05,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_06,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_07,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_08,this,Arts::MethodDef(m));
+}
+
+Arts::InterfaceRepo_skel::InterfaceRepo_skel()
+{
+}
+
+Arts::Object_base* Arts::InterfaceRepo::_Creator() {
+ return Arts::InterfaceRepo_base::_create();
+}
+
+unsigned long Arts::InterfaceRepo_base::_IID = Arts::MCOPUtils::makeIID("Arts::InterfaceRepo");
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::InterfaceRepoV2_base *castedObject = (Arts::InterfaceRepoV2_base *)skel->_cast(Arts::InterfaceRepoV2_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::InterfaceRepoV2_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::InterfaceRepoV2_base *castedObject = (Arts::InterfaceRepoV2_base *)object._base()->_cast(Arts::InterfaceRepoV2_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::InterfaceRepoV2_base *result;
+ result = (Arts::InterfaceRepoV2_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::InterfaceRepoV2");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::InterfaceRepoV2_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::InterfaceRepoV2")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::InterfaceRepoV2_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::InterfaceRepoV2_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::InterfaceRepoV2_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::InterfaceRepoV2_base::_IID) return (Arts::InterfaceRepoV2_base *)this;
+ if(iid == Arts::InterfaceRepo_base::_IID) return (Arts::InterfaceRepo_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::InterfaceRepoV2_stub::InterfaceRepoV2_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::InterfaceRepoV2_stub::InterfaceRepoV2_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+Arts::TypeIdentification Arts::InterfaceRepoV2_stub::identifyType(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000d6964656e74696679547970650000000019417274733a3a547970654964656e74696669636174696f6e00000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return (Arts::TypeIdentification)0; // error occurred
+ Arts::TypeIdentification returnCode = (Arts::TypeIdentification)result->readLong();
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::InterfaceRepoV2_skel::_interfaceName()
+{
+ return "Arts::InterfaceRepoV2";
+}
+
+bool Arts::InterfaceRepoV2_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::InterfaceRepoV2") return true;
+ if (interfacename == "Arts::InterfaceRepo") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::InterfaceRepoV2_skel::_interfaceNameSkel()
+{
+ return "Arts::InterfaceRepoV2";
+}
+
+// identifyType
+static void _dispatch_Arts_InterfaceRepoV2_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ result->writeLong(((Arts::InterfaceRepoV2_skel *)object)->identifyType(name));
+}
+
+void Arts::InterfaceRepoV2_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000d6964656e74696679547970650000000019417274733a3a"
+ "547970654964656e74696669636174696f6e000000000200000001000000077374"
+ "72696e6700000000056e616d65000000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_InterfaceRepoV2_00,this,Arts::MethodDef(m));
+ Arts::InterfaceRepo_skel::_buildMethodTable();
+}
+
+Arts::InterfaceRepoV2_skel::InterfaceRepoV2_skel()
+{
+}
+
+Arts::Object_base* Arts::InterfaceRepoV2::_Creator() {
+ return Arts::InterfaceRepoV2_base::_create();
+}
+
+unsigned long Arts::InterfaceRepoV2_base::_IID = Arts::MCOPUtils::makeIID("Arts::InterfaceRepoV2");
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::FlowSystemSender_base *castedObject = (Arts::FlowSystemSender_base *)skel->_cast(Arts::FlowSystemSender_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::FlowSystemSender_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::FlowSystemSender_base *castedObject = (Arts::FlowSystemSender_base *)object._base()->_cast(Arts::FlowSystemSender_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::FlowSystemSender_base *result;
+ result = (Arts::FlowSystemSender_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystemSender");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::FlowSystemSender_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::FlowSystemSender")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::FlowSystemSender_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::FlowSystemSender_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::FlowSystemSender_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::FlowSystemSender_base::_IID) return (Arts::FlowSystemSender_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::FlowSystemSender_stub::FlowSystemSender_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::FlowSystemSender_stub::FlowSystemSender_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::FlowSystemSender_stub::processed()
+{
+ long methodID = _lookupMethodFast("method:0000000a70726f6365737365640000000005766f696400000000010000000000000000");
+ Arts::Buffer *request = Arts::Dispatcher::the()->createOnewayRequest(_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+}
+
+void Arts::FlowSystemSender_stub::disconnect()
+{
+ long methodID = _lookupMethodFast("method:0000000b646973636f6e6e6563740000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::string Arts::FlowSystemSender_skel::_interfaceName()
+{
+ return "Arts::FlowSystemSender";
+}
+
+bool Arts::FlowSystemSender_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::FlowSystemSender") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::FlowSystemSender_skel::_interfaceNameSkel()
+{
+ return "Arts::FlowSystemSender";
+}
+
+// processed
+static void _dispatch_Arts_FlowSystemSender_00(void *object, Arts::Buffer *)
+{
+ ((Arts::FlowSystemSender_skel *)object)->processed();
+}
+
+// disconnect
+static void _dispatch_Arts_FlowSystemSender_01(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::FlowSystemSender_skel *)object)->disconnect();
+}
+
+void Arts::FlowSystemSender_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000a70726f6365737365640000000005766f69640000000001"
+ "00000000000000000000000b646973636f6e6e6563740000000005766f69640000"
+ "0000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_FlowSystemSender_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystemSender_01,this,Arts::MethodDef(m));
+}
+
+Arts::FlowSystemSender_skel::FlowSystemSender_skel()
+{
+}
+
+Arts::Object_base* Arts::FlowSystemSender::_Creator() {
+ return Arts::FlowSystemSender_base::_create();
+}
+
+unsigned long Arts::FlowSystemSender_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystemSender");
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::FlowSystemReceiver_base *castedObject = (Arts::FlowSystemReceiver_base *)skel->_cast(Arts::FlowSystemReceiver_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::FlowSystemReceiver_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::FlowSystemReceiver_base *castedObject = (Arts::FlowSystemReceiver_base *)object._base()->_cast(Arts::FlowSystemReceiver_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::FlowSystemReceiver_base *result;
+ result = (Arts::FlowSystemReceiver_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystemReceiver");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::FlowSystemReceiver_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::FlowSystemReceiver")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::FlowSystemReceiver_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::FlowSystemReceiver_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::FlowSystemReceiver_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::FlowSystemReceiver_base::_IID) return (Arts::FlowSystemReceiver_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::FlowSystemReceiver_stub::FlowSystemReceiver_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::FlowSystemReceiver_stub::FlowSystemReceiver_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::FlowSystemReceiver_stub::disconnect()
+{
+ long methodID = _lookupMethodFast("method:0000000b646973636f6e6e6563740000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+long Arts::FlowSystemReceiver_stub::receiveHandlerID()
+{
+ long methodID = _lookupMethodFast("method:000000165f6765745f7265636569766548616e646c6572494400000000056c6f6e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return 0; // error occurred
+ long returnCode = result->readLong();
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::FlowSystemReceiver_skel::_interfaceName()
+{
+ return "Arts::FlowSystemReceiver";
+}
+
+bool Arts::FlowSystemReceiver_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::FlowSystemReceiver") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::FlowSystemReceiver_skel::_interfaceNameSkel()
+{
+ return "Arts::FlowSystemReceiver";
+}
+
+// disconnect
+static void _dispatch_Arts_FlowSystemReceiver_00(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::FlowSystemReceiver_skel *)object)->disconnect();
+}
+
+// _get_receiveHandlerID
+static void _dispatch_Arts_FlowSystemReceiver_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeLong(((Arts::FlowSystemReceiver_skel *)object)->receiveHandlerID());
+}
+
+void Arts::FlowSystemReceiver_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000b646973636f6e6e6563740000000005766f696400000000"
+ "020000000000000000000000165f6765745f7265636569766548616e646c657249"
+ "4400000000056c6f6e6700000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_FlowSystemReceiver_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystemReceiver_01,this,Arts::MethodDef(m));
+}
+
+Arts::FlowSystemReceiver_skel::FlowSystemReceiver_skel()
+{
+}
+
+Arts::Object_base* Arts::FlowSystemReceiver::_Creator() {
+ return Arts::FlowSystemReceiver_base::_create();
+}
+
+unsigned long Arts::FlowSystemReceiver_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystemReceiver");
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::FlowSystem_base *castedObject = (Arts::FlowSystem_base *)skel->_cast(Arts::FlowSystem_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::FlowSystem_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::FlowSystem_base *castedObject = (Arts::FlowSystem_base *)object._base()->_cast(Arts::FlowSystem_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::FlowSystem_base *result;
+ result = (Arts::FlowSystem_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystem");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::FlowSystem_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::FlowSystem")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::FlowSystem_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::FlowSystem_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::FlowSystem_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::FlowSystem_base::_IID) return (Arts::FlowSystem_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::FlowSystem_stub::FlowSystem_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::FlowSystem_stub::FlowSystem_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::FlowSystem_stub::startObject(Arts::Object node)
+{
+ long methodID = _lookupMethodFast("method:0000000c73746172744f626a6563740000000005766f6964000000000200000001000000076f626a65637400000000056e6f6465000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::FlowSystem_stub::stopObject(Arts::Object node)
+{
+ long methodID = _lookupMethodFast("method:0000000b73746f704f626a6563740000000005766f6964000000000200000001000000076f626a65637400000000056e6f6465000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::FlowSystem_stub::connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ long methodID = _lookupMethodFast("method:0000000e636f6e6e6563744f626a6563740000000005766f6964000000000200000004000000076f626a656374000000000d736f757263654f626a656374000000000000000007737472696e67000000000b736f75726365506f72740000000000000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,sourceObject._base());
+ request->writeString(sourcePort);
+ Arts::writeObject(*request,destObject._base());
+ request->writeString(destPort);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::FlowSystem_stub::disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ long methodID = _lookupMethodFast("method:00000011646973636f6e6e6563744f626a6563740000000005766f6964000000000200000004000000076f626a656374000000000d736f757263654f626a656374000000000000000007737472696e67000000000b736f75726365506f72740000000000000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,sourceObject._base());
+ request->writeString(sourcePort);
+ Arts::writeObject(*request,destObject._base());
+ request->writeString(destPort);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+Arts::AttributeType Arts::FlowSystem_stub::queryFlags(Arts::Object node, const std::string& port)
+{
+ long methodID = _lookupMethodFast("method:0000000b7175657279466c6167730000000014417274733a3a41747472696275746554797065000000000200000002000000076f626a65637400000000056e6f6465000000000000000007737472696e670000000005706f7274000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->writeString(port);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return (Arts::AttributeType)0; // error occurred
+ Arts::AttributeType returnCode = (Arts::AttributeType)result->readLong();
+ delete result;
+ return returnCode;
+}
+
+void Arts::FlowSystem_stub::setFloatValue(Arts::Object node, const std::string& port, float value)
+{
+ long methodID = _lookupMethodFast("method:0000000e736574466c6f617456616c75650000000005766f6964000000000200000003000000076f626a65637400000000056e6f6465000000000000000007737472696e670000000005706f7274000000000000000006666c6f6174000000000676616c7565000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->writeString(port);
+ request->writeFloat(value);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+Arts::FlowSystemReceiver Arts::FlowSystem_stub::createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender)
+{
+ long methodID = _lookupMethodFast("method:0000000f63726561746552656365697665720000000019417274733a3a466c6f7753797374656d5265636569766572000000000200000003000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000017417274733a3a466c6f7753797374656d53656e646572000000000773656e646572000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,destObject._base());
+ request->writeString(destPort);
+ Arts::writeObject(*request,sender._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::FlowSystemReceiver::null();
+ Arts::FlowSystemReceiver_base* returnCode;
+ Arts::readObject(*result,returnCode);
+ delete result;
+ return Arts::FlowSystemReceiver::_from_base(returnCode);
+}
+
+std::string Arts::FlowSystem_skel::_interfaceName()
+{
+ return "Arts::FlowSystem";
+}
+
+bool Arts::FlowSystem_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::FlowSystem") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::FlowSystem_skel::_interfaceNameSkel()
+{
+ return "Arts::FlowSystem";
+}
+
+// startObject
+static void _dispatch_Arts_FlowSystem_00(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ ((Arts::FlowSystem_skel *)object)->startObject(node);
+}
+
+// stopObject
+static void _dispatch_Arts_FlowSystem_01(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ ((Arts::FlowSystem_skel *)object)->stopObject(node);
+}
+
+// connectObject
+static void _dispatch_Arts_FlowSystem_02(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_sourceObject;
+ Arts::readObject(*request,_temp_sourceObject);
+ Arts::Object sourceObject = Arts::Object::_from_base(_temp_sourceObject);
+ std::string sourcePort;
+ request->readString(sourcePort);
+ Arts::Object_base* _temp_destObject;
+ Arts::readObject(*request,_temp_destObject);
+ Arts::Object destObject = Arts::Object::_from_base(_temp_destObject);
+ std::string destPort;
+ request->readString(destPort);
+ ((Arts::FlowSystem_skel *)object)->connectObject(sourceObject,sourcePort,destObject,destPort);
+}
+
+// disconnectObject
+static void _dispatch_Arts_FlowSystem_03(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_sourceObject;
+ Arts::readObject(*request,_temp_sourceObject);
+ Arts::Object sourceObject = Arts::Object::_from_base(_temp_sourceObject);
+ std::string sourcePort;
+ request->readString(sourcePort);
+ Arts::Object_base* _temp_destObject;
+ Arts::readObject(*request,_temp_destObject);
+ Arts::Object destObject = Arts::Object::_from_base(_temp_destObject);
+ std::string destPort;
+ request->readString(destPort);
+ ((Arts::FlowSystem_skel *)object)->disconnectObject(sourceObject,sourcePort,destObject,destPort);
+}
+
+// queryFlags
+static void _dispatch_Arts_FlowSystem_04(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ std::string port;
+ request->readString(port);
+ result->writeLong(((Arts::FlowSystem_skel *)object)->queryFlags(node,port));
+}
+
+// setFloatValue
+static void _dispatch_Arts_FlowSystem_05(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ std::string port;
+ request->readString(port);
+ float value = request->readFloat();
+ ((Arts::FlowSystem_skel *)object)->setFloatValue(node,port,value);
+}
+
+// createReceiver
+static void _dispatch_Arts_FlowSystem_06(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::Object_base* _temp_destObject;
+ Arts::readObject(*request,_temp_destObject);
+ Arts::Object destObject = Arts::Object::_from_base(_temp_destObject);
+ std::string destPort;
+ request->readString(destPort);
+ Arts::FlowSystemSender_base* _temp_sender;
+ Arts::readObject(*request,_temp_sender);
+ Arts::FlowSystemSender sender = Arts::FlowSystemSender::_from_base(_temp_sender);
+ Arts::FlowSystemReceiver returnCode = ((Arts::FlowSystem_skel *)object)->createReceiver(destObject,destPort,sender);
+ Arts::writeObject(*result,returnCode._base());
+}
+
+void Arts::FlowSystem_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000c73746172744f626a6563740000000005766f6964000000"
+ "000200000001000000076f626a65637400000000056e6f64650000000000000000"
+ "000000000b73746f704f626a6563740000000005766f6964000000000200000001"
+ "000000076f626a65637400000000056e6f64650000000000000000000000000e63"
+ "6f6e6e6563744f626a6563740000000005766f6964000000000200000004000000"
+ "076f626a656374000000000d736f757263654f626a656374000000000000000007"
+ "737472696e67000000000b736f75726365506f72740000000000000000076f626a"
+ "656374000000000b646573744f626a656374000000000000000007737472696e67"
+ "000000000964657374506f727400000000000000000000000011646973636f6e6e"
+ "6563744f626a6563740000000005766f6964000000000200000004000000076f62"
+ "6a656374000000000d736f757263654f626a656374000000000000000007737472"
+ "696e67000000000b736f75726365506f72740000000000000000076f626a656374"
+ "000000000b646573744f626a656374000000000000000007737472696e67000000"
+ "000964657374506f72740000000000000000000000000b7175657279466c616773"
+ "0000000014417274733a3a41747472696275746554797065000000000200000002"
+ "000000076f626a65637400000000056e6f6465000000000000000007737472696e"
+ "670000000005706f72740000000000000000000000000e736574466c6f61745661"
+ "6c75650000000005766f6964000000000200000003000000076f626a6563740000"
+ "0000056e6f6465000000000000000007737472696e670000000005706f72740000"
+ "00000000000006666c6f6174000000000676616c75650000000000000000000000"
+ "000f63726561746552656365697665720000000019417274733a3a466c6f775379"
+ "7374656d5265636569766572000000000200000003000000076f626a6563740000"
+ "00000b646573744f626a656374000000000000000007737472696e670000000009"
+ "64657374506f7274000000000000000017417274733a3a466c6f7753797374656d"
+ "53656e646572000000000773656e646572000000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_FlowSystem_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_03,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_04,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_05,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_06,this,Arts::MethodDef(m));
+}
+
+Arts::FlowSystem_skel::FlowSystem_skel()
+{
+}
+
+Arts::Object_base* Arts::FlowSystem::_Creator() {
+ return Arts::FlowSystem_base::_create();
+}
+
+unsigned long Arts::FlowSystem_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystem");
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::GlobalComm_base *castedObject = (Arts::GlobalComm_base *)skel->_cast(Arts::GlobalComm_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::GlobalComm_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::GlobalComm_base *castedObject = (Arts::GlobalComm_base *)object._base()->_cast(Arts::GlobalComm_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::GlobalComm_base *result;
+ result = (Arts::GlobalComm_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::GlobalComm");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::GlobalComm_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::GlobalComm")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::GlobalComm_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::GlobalComm_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::GlobalComm_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::GlobalComm_base::_IID) return (Arts::GlobalComm_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::GlobalComm_stub::GlobalComm_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::GlobalComm_stub::GlobalComm_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+bool Arts::GlobalComm_stub::put(const std::string& variable, const std::string& value)
+{
+ long methodID = _lookupMethodFast("method:000000047075740000000008626f6f6c65616e00000000020000000200000007737472696e6700000000097661726961626c65000000000000000007737472696e67000000000676616c7565000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(variable);
+ request->writeString(value);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return false; // error occurred
+ bool returnCode = result->readBool();
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::GlobalComm_stub::get(const std::string& variable)
+{
+ long methodID = _lookupMethodFast("method:000000046765740000000007737472696e6700000000020000000100000007737472696e6700000000097661726961626c65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(variable);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+void Arts::GlobalComm_stub::erase(const std::string& variable)
+{
+ long methodID = _lookupMethodFast("method:0000000665726173650000000005766f696400000000020000000100000007737472696e6700000000097661726961626c65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(variable);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::string Arts::GlobalComm_skel::_interfaceName()
+{
+ return "Arts::GlobalComm";
+}
+
+bool Arts::GlobalComm_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::GlobalComm") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::GlobalComm_skel::_interfaceNameSkel()
+{
+ return "Arts::GlobalComm";
+}
+
+// put
+static void _dispatch_Arts_GlobalComm_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string variable;
+ request->readString(variable);
+ std::string value;
+ request->readString(value);
+ result->writeBool(((Arts::GlobalComm_skel *)object)->put(variable,value));
+}
+
+// get
+static void _dispatch_Arts_GlobalComm_01(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string variable;
+ request->readString(variable);
+ result->writeString(((Arts::GlobalComm_skel *)object)->get(variable));
+}
+
+// erase
+static void _dispatch_Arts_GlobalComm_02(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ std::string variable;
+ request->readString(variable);
+ ((Arts::GlobalComm_skel *)object)->erase(variable);
+}
+
+void Arts::GlobalComm_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:000000047075740000000008626f6f6c65616e0000000002000000"
+ "0200000007737472696e6700000000097661726961626c65000000000000000007"
+ "737472696e67000000000676616c75650000000000000000000000000467657400"
+ "00000007737472696e6700000000020000000100000007737472696e6700000000"
+ "097661726961626c65000000000000000000000000066572617365000000000576"
+ "6f696400000000020000000100000007737472696e670000000009766172696162"
+ "6c65000000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_GlobalComm_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_GlobalComm_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_GlobalComm_02,this,Arts::MethodDef(m));
+}
+
+Arts::GlobalComm_skel::GlobalComm_skel()
+{
+}
+
+Arts::Object_base* Arts::GlobalComm::_Creator() {
+ return Arts::GlobalComm_base::_create();
+}
+
+unsigned long Arts::GlobalComm_base::_IID = Arts::MCOPUtils::makeIID("Arts::GlobalComm");
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::TmpGlobalComm_base *castedObject = (Arts::TmpGlobalComm_base *)skel->_cast(Arts::TmpGlobalComm_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::TmpGlobalComm_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::TmpGlobalComm_base *castedObject = (Arts::TmpGlobalComm_base *)object._base()->_cast(Arts::TmpGlobalComm_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::TmpGlobalComm_base *result;
+ result = (Arts::TmpGlobalComm_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TmpGlobalComm");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::TmpGlobalComm_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::TmpGlobalComm")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::TmpGlobalComm_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::TmpGlobalComm_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::TmpGlobalComm_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::TmpGlobalComm_base::_IID) return (Arts::TmpGlobalComm_base *)this;
+ if(iid == Arts::GlobalComm_base::_IID) return (Arts::GlobalComm_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::TmpGlobalComm_stub::TmpGlobalComm_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::TmpGlobalComm_stub::TmpGlobalComm_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+std::string Arts::TmpGlobalComm_skel::_interfaceName()
+{
+ return "Arts::TmpGlobalComm";
+}
+
+bool Arts::TmpGlobalComm_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::TmpGlobalComm") return true;
+ if (interfacename == "Arts::GlobalComm") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::TmpGlobalComm_skel::_interfaceNameSkel()
+{
+ return "Arts::TmpGlobalComm";
+}
+
+void Arts::TmpGlobalComm_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:",
+ "MethodTable"
+ );
+ Arts::GlobalComm_skel::_buildMethodTable();
+}
+
+Arts::TmpGlobalComm_skel::TmpGlobalComm_skel()
+{
+}
+
+Arts::Object_base* Arts::TmpGlobalComm::_Creator() {
+ return Arts::TmpGlobalComm_base::_create();
+}
+
+unsigned long Arts::TmpGlobalComm_base::_IID = Arts::MCOPUtils::makeIID("Arts::TmpGlobalComm");
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::TraderOffer_base *castedObject = (Arts::TraderOffer_base *)skel->_cast(Arts::TraderOffer_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::TraderOffer_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::TraderOffer_base *castedObject = (Arts::TraderOffer_base *)object._base()->_cast(Arts::TraderOffer_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::TraderOffer_base *result;
+ result = (Arts::TraderOffer_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TraderOffer");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::TraderOffer_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::TraderOffer")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::TraderOffer_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::TraderOffer_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::TraderOffer_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::TraderOffer_base::_IID) return (Arts::TraderOffer_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::TraderOffer_stub::TraderOffer_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::TraderOffer_stub::TraderOffer_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+std::vector<std::string> * Arts::TraderOffer_stub::getProperty(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000c67657450726f706572747900000000082a737472696e6700000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::TraderOffer_stub::interfaceName()
+{
+ long methodID = _lookupMethodFast("method:000000135f6765745f696e746572666163654e616d650000000007737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::TraderOffer_skel::_interfaceName()
+{
+ return "Arts::TraderOffer";
+}
+
+bool Arts::TraderOffer_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::TraderOffer") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::TraderOffer_skel::_interfaceNameSkel()
+{
+ return "Arts::TraderOffer";
+}
+
+// getProperty
+static void _dispatch_Arts_TraderOffer_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ std::vector<std::string> *_returnCode = ((Arts::TraderOffer_skel *)object)->getProperty(name);
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// _get_interfaceName
+static void _dispatch_Arts_TraderOffer_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::TraderOffer_skel *)object)->interfaceName());
+}
+
+void Arts::TraderOffer_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000c67657450726f706572747900000000082a737472696e67"
+ "00000000020000000100000007737472696e6700000000056e616d650000000000"
+ "00000000000000135f6765745f696e746572666163654e616d6500000000077374"
+ "72696e6700000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_TraderOffer_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_TraderOffer_01,this,Arts::MethodDef(m));
+}
+
+Arts::TraderOffer_skel::TraderOffer_skel()
+{
+}
+
+Arts::Object_base* Arts::TraderOffer::_Creator() {
+ return Arts::TraderOffer_base::_create();
+}
+
+unsigned long Arts::TraderOffer_base::_IID = Arts::MCOPUtils::makeIID("Arts::TraderOffer");
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::TraderQuery_base *castedObject = (Arts::TraderQuery_base *)skel->_cast(Arts::TraderQuery_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::TraderQuery_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::TraderQuery_base *castedObject = (Arts::TraderQuery_base *)object._base()->_cast(Arts::TraderQuery_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::TraderQuery_base *result;
+ result = (Arts::TraderQuery_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TraderQuery");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::TraderQuery_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::TraderQuery")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::TraderQuery_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::TraderQuery_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::TraderQuery_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::TraderQuery_base::_IID) return (Arts::TraderQuery_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::TraderQuery_stub::TraderQuery_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::TraderQuery_stub::TraderQuery_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::TraderQuery_stub::supports(const std::string& property, const std::string& value)
+{
+ long methodID = _lookupMethodFast("method:00000009737570706f7274730000000005766f696400000000020000000200000007737472696e67000000000970726f7065727479000000000000000007737472696e67000000000676616c7565000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(property);
+ request->writeString(value);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::vector<Arts::TraderOffer> * Arts::TraderQuery_stub::query()
+{
+ long methodID = _lookupMethodFast("method:00000006717565727900000000132a417274733a3a5472616465724f6666657200000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<Arts::TraderOffer> *_returnCode = new std::vector<Arts::TraderOffer>;
+ if(!result) return _returnCode; // error occurred
+ Arts::readObjectSeq(*result,*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::TraderQuery_skel::_interfaceName()
+{
+ return "Arts::TraderQuery";
+}
+
+bool Arts::TraderQuery_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::TraderQuery") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::TraderQuery_skel::_interfaceNameSkel()
+{
+ return "Arts::TraderQuery";
+}
+
+// supports
+static void _dispatch_Arts_TraderQuery_00(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ std::string property;
+ request->readString(property);
+ std::string value;
+ request->readString(value);
+ ((Arts::TraderQuery_skel *)object)->supports(property,value);
+}
+
+// query
+static void _dispatch_Arts_TraderQuery_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<Arts::TraderOffer> *_returnCode = ((Arts::TraderQuery_skel *)object)->query();
+ Arts::writeObjectSeq(*result,*_returnCode);
+ delete _returnCode;
+}
+
+void Arts::TraderQuery_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:00000009737570706f7274730000000005766f6964000000000200"
+ "00000200000007737472696e67000000000970726f706572747900000000000000"
+ "0007737472696e67000000000676616c7565000000000000000000000000067175"
+ "65727900000000132a417274733a3a5472616465724f6666657200000000020000"
+ "000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_TraderQuery_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_TraderQuery_01,this,Arts::MethodDef(m));
+}
+
+Arts::TraderQuery_skel::TraderQuery_skel()
+{
+}
+
+Arts::Object_base* Arts::TraderQuery::_Creator() {
+ return Arts::TraderQuery_base::_create();
+}
+
+unsigned long Arts::TraderQuery_base::_IID = Arts::MCOPUtils::makeIID("Arts::TraderQuery");
+
+Arts::Loader_base *Arts::Loader_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::Loader_base *castedObject = (Arts::Loader_base *)skel->_cast(Arts::Loader_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::Loader_base *Arts::Loader_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::Loader_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::Loader_base *Arts::Loader_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::Loader_base *castedObject = (Arts::Loader_base *)object._base()->_cast(Arts::Loader_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::Loader_base *Arts::Loader_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::Loader_base *result;
+ result = (Arts::Loader_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::Loader");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::Loader_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::Loader")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::Loader_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::Loader_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::Loader_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::Loader_base::_IID) return (Arts::Loader_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::Loader_stub::Loader_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::Loader_stub::Loader_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+Arts::Object Arts::Loader_stub::loadObject(Arts::TraderOffer offer)
+{
+ long methodID = _lookupMethodFast("method:0000000b6c6f61644f626a65637400000000076f626a65637400000000020000000100000012417274733a3a5472616465724f6666657200000000066f66666572000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,offer._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::Object::null();
+ Arts::Object_base* returnCode;
+ Arts::readObject(*result,returnCode);
+ delete result;
+ return Arts::Object::_from_base(returnCode);
+}
+
+std::string Arts::Loader_stub::dataVersion()
+{
+ long methodID = _lookupMethodFast("method:000000115f6765745f6461746156657273696f6e0000000007737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+std::vector<Arts::TraderEntry> * Arts::Loader_stub::traderEntries()
+{
+ long methodID = _lookupMethodFast("method:000000135f6765745f747261646572456e747269657300000000132a417274733a3a547261646572456e74727900000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<Arts::TraderEntry> *_returnCode = new std::vector<Arts::TraderEntry>;
+ if(!result) return _returnCode; // error occurred
+ Arts::readTypeSeq(*result,*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<Arts::ModuleDef> * Arts::Loader_stub::modules()
+{
+ long methodID = _lookupMethodFast("method:0000000d5f6765745f6d6f64756c657300000000112a417274733a3a4d6f64756c6544656600000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<Arts::ModuleDef> *_returnCode = new std::vector<Arts::ModuleDef>;
+ if(!result) return _returnCode; // error occurred
+ Arts::readTypeSeq(*result,*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::Loader_skel::_interfaceName()
+{
+ return "Arts::Loader";
+}
+
+bool Arts::Loader_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::Loader") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::Loader_skel::_interfaceNameSkel()
+{
+ return "Arts::Loader";
+}
+
+// loadObject
+static void _dispatch_Arts_Loader_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::TraderOffer_base* _temp_offer;
+ Arts::readObject(*request,_temp_offer);
+ Arts::TraderOffer offer = Arts::TraderOffer::_from_base(_temp_offer);
+ Arts::Object returnCode = ((Arts::Loader_skel *)object)->loadObject(offer);
+ Arts::writeObject(*result,returnCode._base());
+}
+
+// _get_dataVersion
+static void _dispatch_Arts_Loader_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::Loader_skel *)object)->dataVersion());
+}
+
+// _get_traderEntries
+static void _dispatch_Arts_Loader_02(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<Arts::TraderEntry> *_returnCode = ((Arts::Loader_skel *)object)->traderEntries();
+ Arts::writeTypeSeq(*result,*_returnCode);
+ delete _returnCode;
+}
+
+// _get_modules
+static void _dispatch_Arts_Loader_03(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<Arts::ModuleDef> *_returnCode = ((Arts::Loader_skel *)object)->modules();
+ Arts::writeTypeSeq(*result,*_returnCode);
+ delete _returnCode;
+}
+
+void Arts::Loader_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000b6c6f61644f626a65637400000000076f626a6563740000"
+ "0000020000000100000012417274733a3a5472616465724f666665720000000006"
+ "6f66666572000000000000000000000000115f6765745f6461746156657273696f"
+ "6e0000000007737472696e6700000000020000000000000000000000135f676574"
+ "5f747261646572456e747269657300000000132a417274733a3a54726164657245"
+ "6e747279000000000200000000000000000000000d5f6765745f6d6f64756c6573"
+ "00000000112a417274733a3a4d6f64756c65446566000000000200000000000000"
+ "00",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_Loader_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Loader_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Loader_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Loader_03,this,Arts::MethodDef(m));
+}
+
+Arts::Loader_skel::Loader_skel()
+{
+}
+
+Arts::Object_base* Arts::Loader::_Creator() {
+ return Arts::Loader_base::_create();
+}
+
+unsigned long Arts::Loader_base::_IID = Arts::MCOPUtils::makeIID("Arts::Loader");
+
+static Arts::IDLFileReg IDLFileReg_core("core",
+ "IDLFile:00000001000000000500000012417274733a3a4865616465724d6167696300"
+ "000000010000000b4d434f505f4d41474943004d434f50000000000000000000000012"
+ "417274733a3a4d657373616765547970650000000007000000136d636f704d65737361"
+ "6765496e76616c6964000000000000000000000000106d636f7053657276657248656c"
+ "6c6f000000000100000000000000106d636f70436c69656e7448656c6c6f0000000002"
+ "000000000000000f6d636f70417574684163636570740000000003000000000000000f"
+ "6d636f70496e766f636174696f6e0000000004000000000000000b6d636f7052657475"
+ "726e000000000500000000000000156d636f704f6e65776179496e766f636174696f6e"
+ "0000000006000000000000000000000011417274733a3a4d6574686f64547970650000"
+ "0000020000000d6d6574686f644f6e657761790000000001000000000000000d6d6574"
+ "686f6454776f7761790000000002000000000000000000000014417274733a3a417474"
+ "7269627574655479706500000000070000000973747265616d496e0000000001000000"
+ "000000000a73747265616d4f75740000000002000000000000000c73747265616d4d75"
+ "6c74690000000004000000000000001061747472696275746553747265616d00000000"
+ "0800000000000000136174747269627574654174747269627574650000000010000000"
+ "000000000c73747265616d4173796e630000000020000000000000000e73747265616d"
+ "44656661756c740000000040000000000000000000000019417274733a3a5479706549"
+ "64656e74696669636174696f6e000000000a0000000a7469556e6b6e6f776e00000000"
+ "0000000000000000077469566f69640000000001000000000000000774694c6f6e6700"
+ "0000000200000000000000077469427974650000000003000000000000000974695374"
+ "72696e670000000004000000000000000a7469426f6f6c65616e000000000500000000"
+ "000000087469466c6f6174000000000600000000000000077469456e756d0000000080"
+ "00000000000000077469547970650000000081000000000000000c7469496e74657266"
+ "61636500000000820000000000000000000000120000000d417274733a3a4865616465"
+ "72000000000300000012417274733a3a4865616465724d6167696300000000066d6167"
+ "69630000000000000000056c6f6e67000000000e6d6573736167654c656e6774680000"
+ "00000000000012417274733a3a4d65737361676554797065000000000c6d6573736167"
+ "655479706500000000000000000000000011417274733a3a496e766f636174696f6e00"
+ "00000003000000056c6f6e6700000000096f626a65637449440000000000000000056c"
+ "6f6e6700000000096d6574686f6449440000000000000000056c6f6e67000000000a72"
+ "657175657374494400000000000000000000000017417274733a3a4f6e65776179496e"
+ "766f636174696f6e0000000002000000056c6f6e6700000000096f626a656374494400"
+ "00000000000000056c6f6e6700000000096d6574686f64494400000000000000000000"
+ "000012417274733a3a53657276657248656c6c6f000000000400000007737472696e67"
+ "000000000c6d636f7056657273696f6e000000000000000007737472696e6700000000"
+ "0973657276657249440000000000000000082a737472696e67000000000e6175746850"
+ "726f746f636f6c73000000000000000007737472696e67000000000961757468536565"
+ "6400000000000000000000000012417274733a3a436c69656e7448656c6c6f00000000"
+ "0300000007737472696e67000000000973657276657249440000000000000000077374"
+ "72696e67000000000d6175746850726f746f636f6c000000000000000007737472696e"
+ "670000000009617574684461746100000000000000000000000011417274733a3a4175"
+ "74684163636570740000000001000000082a737472696e67000000000668696e747300"
+ "000000000000000000000016417274733a3a4f626a6563745265666572656e63650000"
+ "00000300000007737472696e6700000000097365727665724944000000000000000005"
+ "6c6f6e6700000000096f626a65637449440000000000000000082a737472696e670000"
+ "00000575726c730000000000000000000000000f417274733a3a506172616d44656600"
+ "0000000300000007737472696e67000000000574797065000000000000000007737472"
+ "696e6700000000056e616d650000000000000000082a737472696e6700000000066869"
+ "6e747300000000000000000000000010417274733a3a4d6574686f6444656600000000"
+ "0500000007737472696e6700000000056e616d65000000000000000007737472696e67"
+ "000000000574797065000000000000000011417274733a3a4d6574686f645479706500"
+ "00000006666c6167730000000000000000102a417274733a3a506172616d4465660000"
+ "00000a7369676e61747572650000000000000000082a737472696e6700000000066869"
+ "6e747300000000000000000000000013417274733a3a41747472696275746544656600"
+ "0000000400000007737472696e6700000000056e616d65000000000000000007737472"
+ "696e67000000000574797065000000000000000014417274733a3a4174747269627574"
+ "65547970650000000006666c6167730000000000000000082a737472696e6700000000"
+ "0668696e747300000000000000000000000013417274733a3a496e7465726661636544"
+ "6566000000000600000007737472696e6700000000056e616d65000000000000000008"
+ "2a737472696e670000000014696e68657269746564496e746572666163657300000000"
+ "00000000112a417274733a3a4d6574686f6444656600000000086d6574686f64730000"
+ "000000000000142a417274733a3a417474726962757465446566000000000b61747472"
+ "6962757465730000000000000000082a737472696e67000000000d64656661756c7450"
+ "6f7274730000000000000000082a737472696e67000000000668696e74730000000000"
+ "0000000000000014417274733a3a54797065436f6d706f6e656e740000000003000000"
+ "07737472696e67000000000574797065000000000000000007737472696e6700000000"
+ "056e616d650000000000000000082a737472696e67000000000668696e747300000000"
+ "00000000000000000e417274733a3a5479706544656600000000030000000773747269"
+ "6e6700000000056e616d650000000000000000152a417274733a3a54797065436f6d70"
+ "6f6e656e740000000009636f6e74656e74730000000000000000082a737472696e6700"
+ "0000000668696e747300000000000000000000000014417274733a3a456e756d436f6d"
+ "706f6e656e74000000000300000007737472696e6700000000056e616d650000000000"
+ "000000056c6f6e67000000000676616c75650000000000000000082a737472696e6700"
+ "0000000668696e74730000000000000000000000000e417274733a3a456e756d446566"
+ "000000000300000007737472696e6700000000056e616d650000000000000000152a41"
+ "7274733a3a456e756d436f6d706f6e656e740000000009636f6e74656e747300000000"
+ "00000000082a737472696e67000000000668696e747300000000000000000000000010"
+ "417274733a3a4d6f64756c65446566000000000500000007737472696e67000000000b"
+ "6d6f64756c654e616d6500000000000000000f2a417274733a3a456e756d4465660000"
+ "000006656e756d7300000000000000000f2a417274733a3a5479706544656600000000"
+ "0674797065730000000000000000142a417274733a3a496e7465726661636544656600"
+ "0000000b696e74657266616365730000000000000000082a737472696e670000000006"
+ "68696e74730000000000000000000000000a417274733a3a416e790000000002000000"
+ "07737472696e670000000005747970650000000000000000062a627974650000000006"
+ "76616c756500000000000000000000000012417274733a3a547261646572456e747279"
+ "000000000200000007737472696e67000000000e696e746572666163654e616d650000"
+ "000000000000082a737472696e6700000000066c696e65730000000000000000000000"
+ "000b00000014417274733a3a496e746572666163655265706f00000000000000000900"
+ "00000d696e736572744d6f64756c6500000000056c6f6e670000000002000000010000"
+ "0010417274733a3a4d6f64756c65446566000000000a6e65774d6f64756c6500000000"
+ "00000000000000000d72656d6f76654d6f64756c650000000005766f69640000000002"
+ "00000001000000056c6f6e6700000000096d6f64756c65494400000000000000000000"
+ "00000f7175657279496e746572666163650000000013417274733a3a496e7465726661"
+ "636544656600000000020000000100000007737472696e6700000000056e616d650000"
+ "000000000000000000000a717565727954797065000000000e417274733a3a54797065"
+ "44656600000000020000000100000007737472696e6700000000056e616d6500000000"
+ "00000000000000000a7175657279456e756d000000000e417274733a3a456e756d4465"
+ "6600000000020000000100000007737472696e6700000000056e616d65000000000000"
+ "0000000000000e71756572794368696c6472656e00000000082a737472696e67000000"
+ "00020000000100000007737472696e6700000000056e616d6500000000000000000000"
+ "0000107175657279496e746572666163657300000000082a737472696e670000000002"
+ "00000000000000000000000b7175657279547970657300000000082a737472696e6700"
+ "0000000200000000000000000000000b7175657279456e756d7300000000082a737472"
+ "696e670000000002000000000000000000000000000000000000000000000016417274"
+ "733a3a496e746572666163655265706f5632000000000100000014417274733a3a496e"
+ "746572666163655265706f00000000010000000d6964656e7469667954797065000000"
+ "0019417274733a3a547970654964656e74696669636174696f6e000000000200000001"
+ "00000007737472696e6700000000056e616d6500000000000000000000000000000000"
+ "000000000000000017417274733a3a466c6f7753797374656d53656e64657200000000"
+ "00000000020000000a70726f6365737365640000000005766f69640000000001000000"
+ "00000000000000000b646973636f6e6e6563740000000005766f696400000000020000"
+ "00000000000000000000000000000000000000000019417274733a3a466c6f77537973"
+ "74656d52656365697665720000000000000000010000000b646973636f6e6e65637400"
+ "00000005766f6964000000000200000000000000000000000100000011726563656976"
+ "6548616e646c6572494400000000056c6f6e6700000000120000000000000000000000"
+ "0000000011417274733a3a466c6f7753797374656d0000000000000000070000000c73"
+ "746172744f626a6563740000000005766f6964000000000200000001000000076f626a"
+ "65637400000000056e6f64650000000000000000000000000b73746f704f626a656374"
+ "0000000005766f6964000000000200000001000000076f626a65637400000000056e6f"
+ "64650000000000000000000000000e636f6e6e6563744f626a6563740000000005766f"
+ "6964000000000200000004000000076f626a656374000000000d736f757263654f626a"
+ "656374000000000000000007737472696e67000000000b736f75726365506f72740000"
+ "000000000000076f626a656374000000000b646573744f626a65637400000000000000"
+ "0007737472696e67000000000964657374506f72740000000000000000000000001164"
+ "6973636f6e6e6563744f626a6563740000000005766f69640000000002000000040000"
+ "00076f626a656374000000000d736f757263654f626a65637400000000000000000773"
+ "7472696e67000000000b736f75726365506f72740000000000000000076f626a656374"
+ "000000000b646573744f626a656374000000000000000007737472696e670000000009"
+ "64657374506f72740000000000000000000000000b7175657279466c61677300000000"
+ "14417274733a3a41747472696275746554797065000000000200000002000000076f62"
+ "6a65637400000000056e6f6465000000000000000007737472696e670000000005706f"
+ "72740000000000000000000000000e736574466c6f617456616c75650000000005766f"
+ "6964000000000200000003000000076f626a65637400000000056e6f64650000000000"
+ "00000007737472696e670000000005706f7274000000000000000006666c6f61740000"
+ "00000676616c75650000000000000000000000000f6372656174655265636569766572"
+ "0000000019417274733a3a466c6f7753797374656d5265636569766572000000000200"
+ "000003000000076f626a656374000000000b646573744f626a65637400000000000000"
+ "0007737472696e67000000000964657374506f7274000000000000000017417274733a"
+ "3a466c6f7753797374656d53656e646572000000000773656e64657200000000000000"
+ "000000000000000000000000000000000011417274733a3a476c6f62616c436f6d6d00"
+ "0000000000000003000000047075740000000008626f6f6c65616e0000000002000000"
+ "0200000007737472696e6700000000097661726961626c650000000000000000077374"
+ "72696e67000000000676616c7565000000000000000000000000046765740000000007"
+ "737472696e6700000000020000000100000007737472696e6700000000097661726961"
+ "626c650000000000000000000000000665726173650000000005766f69640000000002"
+ "0000000100000007737472696e6700000000097661726961626c650000000000000000"
+ "0000000000000000000000000000000014417274733a3a546d70476c6f62616c436f6d"
+ "6d000000000100000011417274733a3a476c6f62616c436f6d6d000000000000000000"
+ "000000000000000000000012417274733a3a5472616465724f66666572000000000000"
+ "0000010000000c67657450726f706572747900000000082a737472696e670000000002"
+ "0000000100000007737472696e6700000000056e616d65000000000000000000000000"
+ "010000000e696e746572666163654e616d650000000007737472696e67000000001200"
+ "000000000000000000000000000012417274733a3a5472616465725175657279000000"
+ "00000000000200000009737570706f7274730000000005766f69640000000002000000"
+ "0200000007737472696e67000000000970726f70657274790000000000000000077374"
+ "72696e67000000000676616c7565000000000000000000000000067175657279000000"
+ "00132a417274733a3a5472616465724f66666572000000000200000000000000000000"
+ "000000000000000000000000000d417274733a3a4f626a65637400000000000000000e"
+ "0000000e5f6c6f6f6b75704d6574686f6400000000056c6f6e67000000000200000001"
+ "00000010417274733a3a4d6574686f64446566000000000a6d6574686f644465660000"
+ "000000000000000000000f5f696e746572666163654e616d650000000007737472696e"
+ "6700000000020000000000000000000000105f7175657279496e746572666163650000"
+ "000013417274733a3a496e746572666163654465660000000002000000010000000773"
+ "7472696e6700000000056e616d650000000000000000000000000b5f71756572795479"
+ "7065000000000e417274733a3a54797065446566000000000200000001000000077374"
+ "72696e6700000000056e616d650000000000000000000000000b5f7175657279456e75"
+ "6d000000000e417274733a3a456e756d44656600000000020000000100000007737472"
+ "696e6700000000056e616d650000000000000000000000000a5f746f537472696e6700"
+ "00000007737472696e6700000000020000000000000000000000125f6973436f6d7061"
+ "7469626c65576974680000000008626f6f6c65616e0000000002000000010000000773"
+ "7472696e67000000000e696e746572666163656e616d65000000000000000000000000"
+ "0c5f636f707952656d6f74650000000005766f69640000000002000000000000000000"
+ "00000b5f75736552656d6f74650000000005766f696400000000020000000000000000"
+ "0000000f5f72656c6561736552656d6f74650000000005766f69640000000002000000"
+ "00000000000000000a5f6164644368696c640000000007737472696e67000000000200"
+ "000002000000076f626a65637400000000066368696c64000000000000000007737472"
+ "696e6700000000056e616d650000000000000000000000000d5f72656d6f7665436869"
+ "6c640000000008626f6f6c65616e00000000020000000100000007737472696e670000"
+ "0000056e616d650000000000000000000000000a5f6765744368696c6400000000076f"
+ "626a65637400000000020000000100000007737472696e6700000000056e616d650000"
+ "000000000000000000000f5f71756572794368696c6472656e00000000082a73747269"
+ "6e6700000000020000000000000000000000010000000c5f666c6f7753797374656d00"
+ "00000011417274733a3a466c6f7753797374656d000000001200000000000000000000"
+ "00000000000d417274733a3a4c6f616465720000000000000000010000000b6c6f6164"
+ "4f626a65637400000000076f626a65637400000000020000000100000012417274733a"
+ "3a5472616465724f6666657200000000066f6666657200000000000000000000000003"
+ "0000000c6461746156657273696f6e0000000007737472696e67000000001200000000"
+ "0000000e747261646572456e747269657300000000132a417274733a3a547261646572"
+ "456e747279000000001200000000000000086d6f64756c657300000000112a41727473"
+ "3a3a4d6f64756c65446566000000001200000000000000000000000000000000"
+);
diff --git a/mcop/core.h b/mcop/core.h
new file mode 100644
index 0000000..5ab73e1
--- /dev/null
+++ b/mcop/core.h
@@ -0,0 +1,1561 @@
+/* this file was generated by the MCOP idl compiler - DO NOT EDIT */
+
+#ifndef CORE_H
+#define CORE_H
+
+#include "common.h"
+#include "arts_export.h"
+
+namespace Arts {
+enum HeaderMagic {MCOP_MAGIC = 1296256848};
+enum MessageType {mcopMessageInvalid = 0, mcopServerHello = 1, mcopClientHello = 2, mcopAuthAccept = 3, mcopInvocation = 4, mcopReturn = 5, mcopOnewayInvocation = 6};
+enum MethodType {methodOneway = 1, methodTwoway = 2, methodMax = 0xffffffff};
+enum AttributeType {streamIn = 1, streamOut = 2, streamMulti = 4, attributeStream = 8, attributeAttribute = 16, streamAsync = 32, streamDefault = 64};
+enum TypeIdentification {tiUnknown = 0, tiVoid = 1, tiLong = 2, tiByte = 3, tiString = 4, tiBoolean = 5, tiFloat = 6, tiEnum = 128, tiType = 129, tiInterface = 130};
+}
+namespace Arts {
+class ARTS_EXPORT Header : public Arts::Type {
+public:
+ Header();
+ Header(Arts::HeaderMagic _a_magic, long _a_messageLength, Arts::MessageType _a_messageType);
+ Header(Arts::Buffer& stream);
+ Header(const Header& copyType);
+ Header& operator=(const Header& assignType);
+ Arts::HeaderMagic magic;
+ long messageLength;
+ Arts::MessageType messageType;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT Invocation : public Arts::Type {
+public:
+ Invocation();
+ Invocation(long _a_objectID, long _a_methodID, long _a_requestID);
+ Invocation(Arts::Buffer& stream);
+ Invocation(const Invocation& copyType);
+ Invocation& operator=(const Invocation& assignType);
+ long objectID;
+ long methodID;
+ long requestID;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT OnewayInvocation : public Arts::Type {
+public:
+ OnewayInvocation();
+ OnewayInvocation(long _a_objectID, long _a_methodID);
+ OnewayInvocation(Arts::Buffer& stream);
+ OnewayInvocation(const OnewayInvocation& copyType);
+ OnewayInvocation& operator=(const OnewayInvocation& assignType);
+ long objectID;
+ long methodID;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ServerHello : public Arts::Type {
+public:
+ ServerHello();
+ ServerHello(const std::string& _a_mcopVersion, const std::string& _a_serverID, const std::vector<std::string>& _a_authProtocols, const std::string& _a_authSeed);
+ ServerHello(Arts::Buffer& stream);
+ ServerHello(const ServerHello& copyType);
+ ServerHello& operator=(const ServerHello& assignType);
+ std::string mcopVersion;
+ std::string serverID;
+ std::vector<std::string> authProtocols;
+ std::string authSeed;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ClientHello : public Arts::Type {
+public:
+ ClientHello();
+ ClientHello(const std::string& _a_serverID, const std::string& _a_authProtocol, const std::string& _a_authData);
+ ClientHello(Arts::Buffer& stream);
+ ClientHello(const ClientHello& copyType);
+ ClientHello& operator=(const ClientHello& assignType);
+ std::string serverID;
+ std::string authProtocol;
+ std::string authData;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT AuthAccept : public Arts::Type {
+public:
+ AuthAccept();
+ AuthAccept(const std::vector<std::string>& _a_hints);
+ AuthAccept(Arts::Buffer& stream);
+ AuthAccept(const AuthAccept& copyType);
+ AuthAccept& operator=(const AuthAccept& assignType);
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ObjectReference : public Arts::Type {
+public:
+ ObjectReference();
+ ObjectReference(const std::string& _a_serverID, long _a_objectID, const std::vector<std::string>& _a_urls);
+ ObjectReference(Arts::Buffer& stream);
+ ObjectReference(const ObjectReference& copyType);
+ ObjectReference& operator=(const ObjectReference& assignType);
+ std::string serverID;
+ long objectID;
+ std::vector<std::string> urls;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ParamDef : public Arts::Type {
+public:
+ ParamDef();
+ ParamDef(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints);
+ ParamDef(Arts::Buffer& stream);
+ ParamDef(const ParamDef& copyType);
+ ParamDef& operator=(const ParamDef& assignType);
+ std::string type;
+ std::string name;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT MethodDef : public Arts::Type {
+public:
+ MethodDef();
+ MethodDef(const std::string& _a_name, const std::string& _a_type, Arts::MethodType _a_flags, const std::vector<Arts::ParamDef>& _a_signature, const std::vector<std::string>& _a_hints);
+ MethodDef(Arts::Buffer& stream);
+ MethodDef(const MethodDef& copyType);
+ MethodDef& operator=(const MethodDef& assignType);
+ std::string name;
+ std::string type;
+ Arts::MethodType flags;
+ std::vector<Arts::ParamDef> signature;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT AttributeDef : public Arts::Type {
+public:
+ AttributeDef();
+ AttributeDef(const std::string& _a_name, const std::string& _a_type, Arts::AttributeType _a_flags, const std::vector<std::string>& _a_hints);
+ AttributeDef(Arts::Buffer& stream);
+ AttributeDef(const AttributeDef& copyType);
+ AttributeDef& operator=(const AttributeDef& assignType);
+ std::string name;
+ std::string type;
+ Arts::AttributeType flags;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT InterfaceDef : public Arts::Type {
+public:
+ InterfaceDef();
+ InterfaceDef(const std::string& _a_name, const std::vector<std::string>& _a_inheritedInterfaces, const std::vector<Arts::MethodDef>& _a_methods, const std::vector<Arts::AttributeDef>& _a_attributes, const std::vector<std::string>& _a_defaultPorts, const std::vector<std::string>& _a_hints);
+ InterfaceDef(Arts::Buffer& stream);
+ InterfaceDef(const InterfaceDef& copyType);
+ InterfaceDef& operator=(const InterfaceDef& assignType);
+ std::string name;
+ std::vector<std::string> inheritedInterfaces;
+ std::vector<Arts::MethodDef> methods;
+ std::vector<Arts::AttributeDef> attributes;
+ std::vector<std::string> defaultPorts;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT TypeComponent : public Arts::Type {
+public:
+ TypeComponent();
+ TypeComponent(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints);
+ TypeComponent(Arts::Buffer& stream);
+ TypeComponent(const TypeComponent& copyType);
+ TypeComponent& operator=(const TypeComponent& assignType);
+ std::string type;
+ std::string name;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT TypeDef : public Arts::Type {
+public:
+ TypeDef();
+ TypeDef(const std::string& _a_name, const std::vector<Arts::TypeComponent>& _a_contents, const std::vector<std::string>& _a_hints);
+ TypeDef(Arts::Buffer& stream);
+ TypeDef(const TypeDef& copyType);
+ TypeDef& operator=(const TypeDef& assignType);
+ std::string name;
+ std::vector<Arts::TypeComponent> contents;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT EnumComponent : public Arts::Type {
+public:
+ EnumComponent();
+ EnumComponent(const std::string& _a_name, long _a_value, const std::vector<std::string>& _a_hints);
+ EnumComponent(Arts::Buffer& stream);
+ EnumComponent(const EnumComponent& copyType);
+ EnumComponent& operator=(const EnumComponent& assignType);
+ std::string name;
+ long value;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT EnumDef : public Arts::Type {
+public:
+ EnumDef();
+ EnumDef(const std::string& _a_name, const std::vector<Arts::EnumComponent>& _a_contents, const std::vector<std::string>& _a_hints);
+ EnumDef(Arts::Buffer& stream);
+ EnumDef(const EnumDef& copyType);
+ EnumDef& operator=(const EnumDef& assignType);
+ std::string name;
+ std::vector<Arts::EnumComponent> contents;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ModuleDef : public Arts::Type {
+public:
+ ModuleDef();
+ ModuleDef(const std::string& _a_moduleName, const std::vector<Arts::EnumDef>& _a_enums, const std::vector<Arts::TypeDef>& _a_types, const std::vector<Arts::InterfaceDef>& _a_interfaces, const std::vector<std::string>& _a_hints);
+ ModuleDef(Arts::Buffer& stream);
+ ModuleDef(const ModuleDef& copyType);
+ ModuleDef& operator=(const ModuleDef& assignType);
+ std::string moduleName;
+ std::vector<Arts::EnumDef> enums;
+ std::vector<Arts::TypeDef> types;
+ std::vector<Arts::InterfaceDef> interfaces;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT Any : public Arts::Type {
+public:
+ Any();
+ Any(const std::string& _a_type, const std::vector<Arts::mcopbyte>& _a_value);
+ Any(Arts::Buffer& stream);
+ Any(const Any& copyType);
+ Any& operator=(const Any& assignType);
+ std::string type;
+ std::vector<Arts::mcopbyte> value;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT TraderEntry : public Arts::Type {
+public:
+ TraderEntry();
+ TraderEntry(const std::string& _a_interfaceName, const std::vector<std::string>& _a_lines);
+ TraderEntry(Arts::Buffer& stream);
+ TraderEntry(const TraderEntry& copyType);
+ TraderEntry& operator=(const TraderEntry& assignType);
+ std::string interfaceName;
+ std::vector<std::string> lines;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+}
+namespace Arts {
+class InterfaceRepo;
+class InterfaceRepoV2;
+class FlowSystemSender;
+class FlowSystemReceiver;
+class FlowSystem;
+class GlobalComm;
+class TmpGlobalComm;
+class TraderOffer;
+class TraderQuery;
+class Loader;
+
+class ARTS_EXPORT InterfaceRepo_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static InterfaceRepo_base *_create(const std::string& subClass = "Arts::InterfaceRepo");
+ static InterfaceRepo_base *_fromString(std::string objectref);
+ static InterfaceRepo_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static InterfaceRepo_base *_fromDynamicCast(const Arts::Object& object);
+ inline InterfaceRepo_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual long insertModule(const Arts::ModuleDef& newModule) = 0;
+ virtual void removeModule(long moduleID) = 0;
+ virtual Arts::InterfaceDef queryInterface(const std::string& name) = 0;
+ virtual Arts::TypeDef queryType(const std::string& name) = 0;
+ virtual Arts::EnumDef queryEnum(const std::string& name) = 0;
+ virtual std::vector<std::string> * queryChildren(const std::string& name) = 0;
+ virtual std::vector<std::string> * queryInterfaces() = 0;
+ virtual std::vector<std::string> * queryTypes() = 0;
+ virtual std::vector<std::string> * queryEnums() = 0;
+};
+
+class ARTS_EXPORT InterfaceRepo_stub : virtual public InterfaceRepo_base, virtual public Arts::Object_stub {
+protected:
+ InterfaceRepo_stub();
+
+public:
+ InterfaceRepo_stub(Arts::Connection *connection, long objectID);
+
+ long insertModule(const Arts::ModuleDef& newModule);
+ void removeModule(long moduleID);
+ Arts::InterfaceDef queryInterface(const std::string& name);
+ Arts::TypeDef queryType(const std::string& name);
+ Arts::EnumDef queryEnum(const std::string& name);
+ std::vector<std::string> * queryChildren(const std::string& name);
+ std::vector<std::string> * queryInterfaces();
+ std::vector<std::string> * queryTypes();
+ std::vector<std::string> * queryEnums();
+};
+
+class ARTS_EXPORT InterfaceRepo_skel : virtual public InterfaceRepo_base, virtual public Arts::Object_skel {
+public:
+ InterfaceRepo_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT InterfaceRepo : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ InterfaceRepo_base *_cache;
+ inline InterfaceRepo_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(InterfaceRepo_base *)_pool->base->_cast(InterfaceRepo_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline InterfaceRepo(InterfaceRepo_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef InterfaceRepo_base _base_class;
+
+ inline InterfaceRepo() : Arts::Object(_Creator), _cache(0) {}
+ inline InterfaceRepo(const Arts::SubClass& s) :
+ Arts::Object(InterfaceRepo_base::_create(s.string())), _cache(0) {}
+ inline InterfaceRepo(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(InterfaceRepo_base::_fromString(r.string())):(InterfaceRepo_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline InterfaceRepo(const Arts::DynamicCast& c) : Arts::Object(InterfaceRepo_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline InterfaceRepo(const InterfaceRepo& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline InterfaceRepo(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static InterfaceRepo null() {return InterfaceRepo((InterfaceRepo_base*)0);}
+ inline static InterfaceRepo _from_base(InterfaceRepo_base* b) {return InterfaceRepo(b);}
+ inline InterfaceRepo& operator=(const InterfaceRepo& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline InterfaceRepo_base* _base() {return _cache?_cache:_method_call();}
+
+ inline long insertModule(const Arts::ModuleDef& newModule);
+ inline void removeModule(long moduleID);
+ inline Arts::InterfaceDef queryInterface(const std::string& name);
+ inline Arts::TypeDef queryType(const std::string& name);
+ inline Arts::EnumDef queryEnum(const std::string& name);
+ inline std::vector<std::string> * queryChildren(const std::string& name);
+ inline std::vector<std::string> * queryInterfaces();
+ inline std::vector<std::string> * queryTypes();
+ inline std::vector<std::string> * queryEnums();
+};
+
+class ARTS_EXPORT InterfaceRepoV2_base : virtual public Arts::InterfaceRepo_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static InterfaceRepoV2_base *_create(const std::string& subClass = "Arts::InterfaceRepoV2");
+ static InterfaceRepoV2_base *_fromString(std::string objectref);
+ static InterfaceRepoV2_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static InterfaceRepoV2_base *_fromDynamicCast(const Arts::Object& object);
+ inline InterfaceRepoV2_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual Arts::TypeIdentification identifyType(const std::string& name) = 0;
+};
+
+class ARTS_EXPORT InterfaceRepoV2_stub : virtual public InterfaceRepoV2_base, virtual public Arts::InterfaceRepo_stub {
+protected:
+ InterfaceRepoV2_stub();
+
+public:
+ InterfaceRepoV2_stub(Arts::Connection *connection, long objectID);
+
+ Arts::TypeIdentification identifyType(const std::string& name);
+};
+
+class ARTS_EXPORT InterfaceRepoV2_skel : virtual public InterfaceRepoV2_base, virtual public Arts::InterfaceRepo_skel {
+public:
+ InterfaceRepoV2_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT InterfaceRepoV2 : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ InterfaceRepoV2_base *_cache;
+ inline InterfaceRepoV2_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(InterfaceRepoV2_base *)_pool->base->_cast(InterfaceRepoV2_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline InterfaceRepoV2(InterfaceRepoV2_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef InterfaceRepoV2_base _base_class;
+
+ inline InterfaceRepoV2() : Arts::Object(_Creator), _cache(0) {}
+ inline InterfaceRepoV2(const Arts::SubClass& s) :
+ Arts::Object(InterfaceRepoV2_base::_create(s.string())), _cache(0) {}
+ inline InterfaceRepoV2(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(InterfaceRepoV2_base::_fromString(r.string())):(InterfaceRepoV2_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline InterfaceRepoV2(const Arts::DynamicCast& c) : Arts::Object(InterfaceRepoV2_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline InterfaceRepoV2(const InterfaceRepoV2& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline InterfaceRepoV2(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static InterfaceRepoV2 null() {return InterfaceRepoV2((InterfaceRepoV2_base*)0);}
+ inline static InterfaceRepoV2 _from_base(InterfaceRepoV2_base* b) {return InterfaceRepoV2(b);}
+ inline InterfaceRepoV2& operator=(const InterfaceRepoV2& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline operator Arts::InterfaceRepo() const { return Arts::InterfaceRepo(*_pool); }
+ inline InterfaceRepoV2_base* _base() {return _cache?_cache:_method_call();}
+
+ inline long insertModule(const Arts::ModuleDef& newModule);
+ inline void removeModule(long moduleID);
+ inline Arts::InterfaceDef queryInterface(const std::string& name);
+ inline Arts::TypeDef queryType(const std::string& name);
+ inline Arts::EnumDef queryEnum(const std::string& name);
+ inline std::vector<std::string> * queryChildren(const std::string& name);
+ inline std::vector<std::string> * queryInterfaces();
+ inline std::vector<std::string> * queryTypes();
+ inline std::vector<std::string> * queryEnums();
+ inline Arts::TypeIdentification identifyType(const std::string& name);
+};
+
+class ARTS_EXPORT FlowSystemSender_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static FlowSystemSender_base *_create(const std::string& subClass = "Arts::FlowSystemSender");
+ static FlowSystemSender_base *_fromString(std::string objectref);
+ static FlowSystemSender_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static FlowSystemSender_base *_fromDynamicCast(const Arts::Object& object);
+ inline FlowSystemSender_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual void processed() = 0;
+ virtual void disconnect() = 0;
+};
+
+class ARTS_EXPORT FlowSystemSender_stub : virtual public FlowSystemSender_base, virtual public Arts::Object_stub {
+protected:
+ FlowSystemSender_stub();
+
+public:
+ FlowSystemSender_stub(Arts::Connection *connection, long objectID);
+
+ void processed();
+ void disconnect();
+};
+
+class ARTS_EXPORT FlowSystemSender_skel : virtual public FlowSystemSender_base, virtual public Arts::Object_skel {
+public:
+ FlowSystemSender_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT FlowSystemSender : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ FlowSystemSender_base *_cache;
+ inline FlowSystemSender_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(FlowSystemSender_base *)_pool->base->_cast(FlowSystemSender_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline FlowSystemSender(FlowSystemSender_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef FlowSystemSender_base _base_class;
+
+ inline FlowSystemSender() : Arts::Object(_Creator), _cache(0) {}
+ inline FlowSystemSender(const Arts::SubClass& s) :
+ Arts::Object(FlowSystemSender_base::_create(s.string())), _cache(0) {}
+ inline FlowSystemSender(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(FlowSystemSender_base::_fromString(r.string())):(FlowSystemSender_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline FlowSystemSender(const Arts::DynamicCast& c) : Arts::Object(FlowSystemSender_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline FlowSystemSender(const FlowSystemSender& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline FlowSystemSender(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static FlowSystemSender null() {return FlowSystemSender((FlowSystemSender_base*)0);}
+ inline static FlowSystemSender _from_base(FlowSystemSender_base* b) {return FlowSystemSender(b);}
+ inline FlowSystemSender& operator=(const FlowSystemSender& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline FlowSystemSender_base* _base() {return _cache?_cache:_method_call();}
+
+ inline void processed();
+ inline void disconnect();
+};
+
+class ARTS_EXPORT FlowSystemReceiver_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static FlowSystemReceiver_base *_create(const std::string& subClass = "Arts::FlowSystemReceiver");
+ static FlowSystemReceiver_base *_fromString(std::string objectref);
+ static FlowSystemReceiver_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static FlowSystemReceiver_base *_fromDynamicCast(const Arts::Object& object);
+ inline FlowSystemReceiver_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual long receiveHandlerID() = 0;
+ virtual void disconnect() = 0;
+};
+
+class ARTS_EXPORT FlowSystemReceiver_stub : virtual public FlowSystemReceiver_base, virtual public Arts::Object_stub {
+protected:
+ FlowSystemReceiver_stub();
+
+public:
+ FlowSystemReceiver_stub(Arts::Connection *connection, long objectID);
+
+ long receiveHandlerID();
+ void disconnect();
+};
+
+class ARTS_EXPORT FlowSystemReceiver_skel : virtual public FlowSystemReceiver_base, virtual public Arts::Object_skel {
+protected:
+ // emitters for change notifications
+ inline void receiveHandlerID_changed(long newValue) {
+ _emit_changed("receiveHandlerID_changed",newValue);
+ }
+
+public:
+ FlowSystemReceiver_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT FlowSystemReceiver : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ FlowSystemReceiver_base *_cache;
+ inline FlowSystemReceiver_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(FlowSystemReceiver_base *)_pool->base->_cast(FlowSystemReceiver_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline FlowSystemReceiver(FlowSystemReceiver_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef FlowSystemReceiver_base _base_class;
+
+ inline FlowSystemReceiver() : Arts::Object(_Creator), _cache(0) {}
+ inline FlowSystemReceiver(const Arts::SubClass& s) :
+ Arts::Object(FlowSystemReceiver_base::_create(s.string())), _cache(0) {}
+ inline FlowSystemReceiver(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(FlowSystemReceiver_base::_fromString(r.string())):(FlowSystemReceiver_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline FlowSystemReceiver(const Arts::DynamicCast& c) : Arts::Object(FlowSystemReceiver_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline FlowSystemReceiver(const FlowSystemReceiver& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline FlowSystemReceiver(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static FlowSystemReceiver null() {return FlowSystemReceiver((FlowSystemReceiver_base*)0);}
+ inline static FlowSystemReceiver _from_base(FlowSystemReceiver_base* b) {return FlowSystemReceiver(b);}
+ inline FlowSystemReceiver& operator=(const FlowSystemReceiver& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline FlowSystemReceiver_base* _base() {return _cache?_cache:_method_call();}
+
+ inline long receiveHandlerID();
+ inline void disconnect();
+};
+
+class ARTS_EXPORT FlowSystem_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static FlowSystem_base *_create(const std::string& subClass = "Arts::FlowSystem");
+ static FlowSystem_base *_fromString(std::string objectref);
+ static FlowSystem_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static FlowSystem_base *_fromDynamicCast(const Arts::Object& object);
+ inline FlowSystem_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual void startObject(Arts::Object node) = 0;
+ virtual void stopObject(Arts::Object node) = 0;
+ virtual void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) = 0;
+ virtual void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) = 0;
+ virtual Arts::AttributeType queryFlags(Arts::Object node, const std::string& port) = 0;
+ virtual void setFloatValue(Arts::Object node, const std::string& port, float value) = 0;
+ virtual Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender) = 0;
+};
+
+class ARTS_EXPORT FlowSystem_stub : virtual public FlowSystem_base, virtual public Arts::Object_stub {
+protected:
+ FlowSystem_stub();
+
+public:
+ FlowSystem_stub(Arts::Connection *connection, long objectID);
+
+ void startObject(Arts::Object node);
+ void stopObject(Arts::Object node);
+ void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ Arts::AttributeType queryFlags(Arts::Object node, const std::string& port);
+ void setFloatValue(Arts::Object node, const std::string& port, float value);
+ Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender);
+};
+
+class ARTS_EXPORT FlowSystem_skel : virtual public FlowSystem_base, virtual public Arts::Object_skel {
+public:
+ FlowSystem_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT FlowSystem : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ FlowSystem_base *_cache;
+ inline FlowSystem_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(FlowSystem_base *)_pool->base->_cast(FlowSystem_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline FlowSystem(FlowSystem_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef FlowSystem_base _base_class;
+
+ inline FlowSystem() : Arts::Object(_Creator), _cache(0) {}
+ inline FlowSystem(const Arts::SubClass& s) :
+ Arts::Object(FlowSystem_base::_create(s.string())), _cache(0) {}
+ inline FlowSystem(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(FlowSystem_base::_fromString(r.string())):(FlowSystem_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline FlowSystem(const Arts::DynamicCast& c) : Arts::Object(FlowSystem_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline FlowSystem(const FlowSystem& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline FlowSystem(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static FlowSystem null() {return FlowSystem((FlowSystem_base*)0);}
+ inline static FlowSystem _from_base(FlowSystem_base* b) {return FlowSystem(b);}
+ inline FlowSystem& operator=(const FlowSystem& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline FlowSystem_base* _base() {return _cache?_cache:_method_call();}
+
+ inline void startObject(Arts::Object node);
+ inline void stopObject(Arts::Object node);
+ inline void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ inline void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ inline Arts::AttributeType queryFlags(Arts::Object node, const std::string& port);
+ inline void setFloatValue(Arts::Object node, const std::string& port, float value);
+ inline Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender);
+};
+
+class ARTS_EXPORT GlobalComm_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static GlobalComm_base *_create(const std::string& subClass = "Arts::GlobalComm");
+ static GlobalComm_base *_fromString(std::string objectref);
+ static GlobalComm_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static GlobalComm_base *_fromDynamicCast(const Arts::Object& object);
+ inline GlobalComm_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual bool put(const std::string& variable, const std::string& value) = 0;
+ virtual std::string get(const std::string& variable) = 0;
+ virtual void erase(const std::string& variable) = 0;
+};
+
+class ARTS_EXPORT GlobalComm_stub : virtual public GlobalComm_base, virtual public Arts::Object_stub {
+protected:
+ GlobalComm_stub();
+
+public:
+ GlobalComm_stub(Arts::Connection *connection, long objectID);
+
+ bool put(const std::string& variable, const std::string& value);
+ std::string get(const std::string& variable);
+ void erase(const std::string& variable);
+};
+
+class ARTS_EXPORT GlobalComm_skel : virtual public GlobalComm_base, virtual public Arts::Object_skel {
+public:
+ GlobalComm_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT GlobalComm : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ GlobalComm_base *_cache;
+ inline GlobalComm_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(GlobalComm_base *)_pool->base->_cast(GlobalComm_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline GlobalComm(GlobalComm_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef GlobalComm_base _base_class;
+
+ inline GlobalComm() : Arts::Object(_Creator), _cache(0) {}
+ inline GlobalComm(const Arts::SubClass& s) :
+ Arts::Object(GlobalComm_base::_create(s.string())), _cache(0) {}
+ inline GlobalComm(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(GlobalComm_base::_fromString(r.string())):(GlobalComm_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline GlobalComm(const Arts::DynamicCast& c) : Arts::Object(GlobalComm_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline GlobalComm(const GlobalComm& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline GlobalComm(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static GlobalComm null() {return GlobalComm((GlobalComm_base*)0);}
+ inline static GlobalComm _from_base(GlobalComm_base* b) {return GlobalComm(b);}
+ inline GlobalComm& operator=(const GlobalComm& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline GlobalComm_base* _base() {return _cache?_cache:_method_call();}
+
+ inline bool put(const std::string& variable, const std::string& value);
+ inline std::string get(const std::string& variable);
+ inline void erase(const std::string& variable);
+};
+
+class ARTS_EXPORT TmpGlobalComm_base : virtual public Arts::GlobalComm_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static TmpGlobalComm_base *_create(const std::string& subClass = "Arts::TmpGlobalComm");
+ static TmpGlobalComm_base *_fromString(std::string objectref);
+ static TmpGlobalComm_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static TmpGlobalComm_base *_fromDynamicCast(const Arts::Object& object);
+ inline TmpGlobalComm_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+};
+
+class ARTS_EXPORT TmpGlobalComm_stub : virtual public TmpGlobalComm_base, virtual public Arts::GlobalComm_stub {
+protected:
+ TmpGlobalComm_stub();
+
+public:
+ TmpGlobalComm_stub(Arts::Connection *connection, long objectID);
+
+};
+
+class ARTS_EXPORT TmpGlobalComm_skel : virtual public TmpGlobalComm_base, virtual public Arts::GlobalComm_skel {
+public:
+ TmpGlobalComm_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT TmpGlobalComm : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ TmpGlobalComm_base *_cache;
+ inline TmpGlobalComm_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(TmpGlobalComm_base *)_pool->base->_cast(TmpGlobalComm_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline TmpGlobalComm(TmpGlobalComm_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef TmpGlobalComm_base _base_class;
+
+ inline TmpGlobalComm() : Arts::Object(_Creator), _cache(0) {}
+ inline TmpGlobalComm(const Arts::SubClass& s) :
+ Arts::Object(TmpGlobalComm_base::_create(s.string())), _cache(0) {}
+ inline TmpGlobalComm(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(TmpGlobalComm_base::_fromString(r.string())):(TmpGlobalComm_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline TmpGlobalComm(const Arts::DynamicCast& c) : Arts::Object(TmpGlobalComm_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline TmpGlobalComm(const TmpGlobalComm& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline TmpGlobalComm(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static TmpGlobalComm null() {return TmpGlobalComm((TmpGlobalComm_base*)0);}
+ inline static TmpGlobalComm _from_base(TmpGlobalComm_base* b) {return TmpGlobalComm(b);}
+ inline TmpGlobalComm& operator=(const TmpGlobalComm& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline operator Arts::GlobalComm() const { return Arts::GlobalComm(*_pool); }
+ inline TmpGlobalComm_base* _base() {return _cache?_cache:_method_call();}
+
+ inline bool put(const std::string& variable, const std::string& value);
+ inline std::string get(const std::string& variable);
+ inline void erase(const std::string& variable);
+};
+
+class ARTS_EXPORT TraderOffer_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static TraderOffer_base *_create(const std::string& subClass = "Arts::TraderOffer");
+ static TraderOffer_base *_fromString(std::string objectref);
+ static TraderOffer_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static TraderOffer_base *_fromDynamicCast(const Arts::Object& object);
+ inline TraderOffer_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual std::string interfaceName() = 0;
+ virtual std::vector<std::string> * getProperty(const std::string& name) = 0;
+};
+
+class ARTS_EXPORT TraderOffer_stub : virtual public TraderOffer_base, virtual public Arts::Object_stub {
+protected:
+ TraderOffer_stub();
+
+public:
+ TraderOffer_stub(Arts::Connection *connection, long objectID);
+
+ std::string interfaceName();
+ std::vector<std::string> * getProperty(const std::string& name);
+};
+
+class ARTS_EXPORT TraderOffer_skel : virtual public TraderOffer_base, virtual public Arts::Object_skel {
+protected:
+ // emitters for change notifications
+ inline void interfaceName_changed(const std::string& newValue) {
+ _emit_changed("interfaceName_changed",newValue);
+ }
+
+public:
+ TraderOffer_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT TraderOffer : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ TraderOffer_base *_cache;
+ inline TraderOffer_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(TraderOffer_base *)_pool->base->_cast(TraderOffer_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline TraderOffer(TraderOffer_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef TraderOffer_base _base_class;
+
+ inline TraderOffer() : Arts::Object(_Creator), _cache(0) {}
+ inline TraderOffer(const Arts::SubClass& s) :
+ Arts::Object(TraderOffer_base::_create(s.string())), _cache(0) {}
+ inline TraderOffer(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(TraderOffer_base::_fromString(r.string())):(TraderOffer_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline TraderOffer(const Arts::DynamicCast& c) : Arts::Object(TraderOffer_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline TraderOffer(const TraderOffer& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline TraderOffer(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static TraderOffer null() {return TraderOffer((TraderOffer_base*)0);}
+ inline static TraderOffer _from_base(TraderOffer_base* b) {return TraderOffer(b);}
+ inline TraderOffer& operator=(const TraderOffer& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline TraderOffer_base* _base() {return _cache?_cache:_method_call();}
+
+ inline std::string interfaceName();
+ inline std::vector<std::string> * getProperty(const std::string& name);
+};
+
+class ARTS_EXPORT TraderQuery_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static TraderQuery_base *_create(const std::string& subClass = "Arts::TraderQuery");
+ static TraderQuery_base *_fromString(std::string objectref);
+ static TraderQuery_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static TraderQuery_base *_fromDynamicCast(const Arts::Object& object);
+ inline TraderQuery_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual void supports(const std::string& property, const std::string& value) = 0;
+ virtual std::vector<Arts::TraderOffer> * query() = 0;
+};
+
+class ARTS_EXPORT TraderQuery_stub : virtual public TraderQuery_base, virtual public Arts::Object_stub {
+protected:
+ TraderQuery_stub();
+
+public:
+ TraderQuery_stub(Arts::Connection *connection, long objectID);
+
+ void supports(const std::string& property, const std::string& value);
+ std::vector<Arts::TraderOffer> * query();
+};
+
+class ARTS_EXPORT TraderQuery_skel : virtual public TraderQuery_base, virtual public Arts::Object_skel {
+public:
+ TraderQuery_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT TraderQuery : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ TraderQuery_base *_cache;
+ inline TraderQuery_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(TraderQuery_base *)_pool->base->_cast(TraderQuery_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline TraderQuery(TraderQuery_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef TraderQuery_base _base_class;
+
+ inline TraderQuery() : Arts::Object(_Creator), _cache(0) {}
+ inline TraderQuery(const Arts::SubClass& s) :
+ Arts::Object(TraderQuery_base::_create(s.string())), _cache(0) {}
+ inline TraderQuery(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(TraderQuery_base::_fromString(r.string())):(TraderQuery_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline TraderQuery(const Arts::DynamicCast& c) : Arts::Object(TraderQuery_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline TraderQuery(const TraderQuery& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline TraderQuery(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static TraderQuery null() {return TraderQuery((TraderQuery_base*)0);}
+ inline static TraderQuery _from_base(TraderQuery_base* b) {return TraderQuery(b);}
+ inline TraderQuery& operator=(const TraderQuery& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline TraderQuery_base* _base() {return _cache?_cache:_method_call();}
+
+ inline void supports(const std::string& property, const std::string& value);
+ inline std::vector<Arts::TraderOffer> * query();
+};
+
+class ARTS_EXPORT Loader_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static Loader_base *_create(const std::string& subClass = "Arts::Loader");
+ static Loader_base *_fromString(std::string objectref);
+ static Loader_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static Loader_base *_fromDynamicCast(const Arts::Object& object);
+ inline Loader_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual std::string dataVersion() = 0;
+ virtual std::vector<Arts::TraderEntry> * traderEntries() = 0;
+ virtual std::vector<Arts::ModuleDef> * modules() = 0;
+ virtual Arts::Object loadObject(Arts::TraderOffer offer) = 0;
+};
+
+class ARTS_EXPORT Loader_stub : virtual public Loader_base, virtual public Arts::Object_stub {
+protected:
+ Loader_stub();
+
+public:
+ Loader_stub(Arts::Connection *connection, long objectID);
+
+ std::string dataVersion();
+ std::vector<Arts::TraderEntry> * traderEntries();
+ std::vector<Arts::ModuleDef> * modules();
+ Arts::Object loadObject(Arts::TraderOffer offer);
+};
+
+class ARTS_EXPORT Loader_skel : virtual public Loader_base, virtual public Arts::Object_skel {
+protected:
+ // emitters for change notifications
+ inline void dataVersion_changed(const std::string& newValue) {
+ _emit_changed("dataVersion_changed",newValue);
+ }
+
+public:
+ Loader_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT Loader : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ Loader_base *_cache;
+ inline Loader_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(Loader_base *)_pool->base->_cast(Loader_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline Loader(Loader_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef Loader_base _base_class;
+
+ inline Loader() : Arts::Object(_Creator), _cache(0) {}
+ inline Loader(const Arts::SubClass& s) :
+ Arts::Object(Loader_base::_create(s.string())), _cache(0) {}
+ inline Loader(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(Loader_base::_fromString(r.string())):(Loader_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline Loader(const Arts::DynamicCast& c) : Arts::Object(Loader_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline Loader(const Loader& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline Loader(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static Loader null() {return Loader((Loader_base*)0);}
+ inline static Loader _from_base(Loader_base* b) {return Loader(b);}
+ inline Loader& operator=(const Loader& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline Loader_base* _base() {return _cache?_cache:_method_call();}
+
+ inline std::string dataVersion();
+ inline std::vector<Arts::TraderEntry> * traderEntries();
+ inline std::vector<Arts::ModuleDef> * modules();
+ inline Arts::Object loadObject(Arts::TraderOffer offer);
+};
+
+}
+// Forward wrapper calls to _base classes:
+
+inline long Arts::InterfaceRepo::insertModule(const Arts::ModuleDef& newModule)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->insertModule(newModule):static_cast<Arts::InterfaceRepo_base*>(_method_call())->insertModule(newModule);
+}
+
+inline void Arts::InterfaceRepo::removeModule(long moduleID)
+{
+ _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->removeModule(moduleID):static_cast<Arts::InterfaceRepo_base*>(_method_call())->removeModule(moduleID);
+}
+
+inline Arts::InterfaceDef Arts::InterfaceRepo::queryInterface(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterface(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterface(name);
+}
+
+inline Arts::TypeDef Arts::InterfaceRepo::queryType(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryType(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryType(name);
+}
+
+inline Arts::EnumDef Arts::InterfaceRepo::queryEnum(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnum(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnum(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryChildren(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryChildren(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryChildren(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryInterfaces()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterfaces():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterfaces();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryTypes()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryTypes():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryTypes();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryEnums()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnums():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnums();
+}
+
+inline long Arts::InterfaceRepoV2::insertModule(const Arts::ModuleDef& newModule)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->insertModule(newModule):static_cast<Arts::InterfaceRepo_base*>(_method_call())->insertModule(newModule);
+}
+
+inline void Arts::InterfaceRepoV2::removeModule(long moduleID)
+{
+ _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->removeModule(moduleID):static_cast<Arts::InterfaceRepo_base*>(_method_call())->removeModule(moduleID);
+}
+
+inline Arts::InterfaceDef Arts::InterfaceRepoV2::queryInterface(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterface(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterface(name);
+}
+
+inline Arts::TypeDef Arts::InterfaceRepoV2::queryType(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryType(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryType(name);
+}
+
+inline Arts::EnumDef Arts::InterfaceRepoV2::queryEnum(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnum(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnum(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryChildren(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryChildren(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryChildren(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryInterfaces()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterfaces():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterfaces();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryTypes()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryTypes():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryTypes();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryEnums()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnums():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnums();
+}
+
+inline Arts::TypeIdentification Arts::InterfaceRepoV2::identifyType(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepoV2_base*>(_cache)->identifyType(name):static_cast<Arts::InterfaceRepoV2_base*>(_method_call())->identifyType(name);
+}
+
+inline void Arts::FlowSystemSender::processed()
+{
+ _cache?static_cast<Arts::FlowSystemSender_base*>(_cache)->processed():static_cast<Arts::FlowSystemSender_base*>(_method_call())->processed();
+}
+
+inline void Arts::FlowSystemSender::disconnect()
+{
+ _cache?static_cast<Arts::FlowSystemSender_base*>(_cache)->disconnect():static_cast<Arts::FlowSystemSender_base*>(_method_call())->disconnect();
+}
+
+inline long Arts::FlowSystemReceiver::receiveHandlerID()
+{
+ return _cache?static_cast<Arts::FlowSystemReceiver_base*>(_cache)->receiveHandlerID():static_cast<Arts::FlowSystemReceiver_base*>(_method_call())->receiveHandlerID();
+}
+
+inline void Arts::FlowSystemReceiver::disconnect()
+{
+ _cache?static_cast<Arts::FlowSystemReceiver_base*>(_cache)->disconnect():static_cast<Arts::FlowSystemReceiver_base*>(_method_call())->disconnect();
+}
+
+inline void Arts::FlowSystem::startObject(Arts::Object node)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->startObject(node):static_cast<Arts::FlowSystem_base*>(_method_call())->startObject(node);
+}
+
+inline void Arts::FlowSystem::stopObject(Arts::Object node)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->stopObject(node):static_cast<Arts::FlowSystem_base*>(_method_call())->stopObject(node);
+}
+
+inline void Arts::FlowSystem::connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->connectObject(sourceObject, sourcePort, destObject, destPort):static_cast<Arts::FlowSystem_base*>(_method_call())->connectObject(sourceObject, sourcePort, destObject, destPort);
+}
+
+inline void Arts::FlowSystem::disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->disconnectObject(sourceObject, sourcePort, destObject, destPort):static_cast<Arts::FlowSystem_base*>(_method_call())->disconnectObject(sourceObject, sourcePort, destObject, destPort);
+}
+
+inline Arts::AttributeType Arts::FlowSystem::queryFlags(Arts::Object node, const std::string& port)
+{
+ return _cache?static_cast<Arts::FlowSystem_base*>(_cache)->queryFlags(node, port):static_cast<Arts::FlowSystem_base*>(_method_call())->queryFlags(node, port);
+}
+
+inline void Arts::FlowSystem::setFloatValue(Arts::Object node, const std::string& port, float value)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->setFloatValue(node, port, value):static_cast<Arts::FlowSystem_base*>(_method_call())->setFloatValue(node, port, value);
+}
+
+inline Arts::FlowSystemReceiver Arts::FlowSystem::createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender)
+{
+ return _cache?static_cast<Arts::FlowSystem_base*>(_cache)->createReceiver(destObject, destPort, sender):static_cast<Arts::FlowSystem_base*>(_method_call())->createReceiver(destObject, destPort, sender);
+}
+
+inline bool Arts::GlobalComm::put(const std::string& variable, const std::string& value)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->put(variable, value):static_cast<Arts::GlobalComm_base*>(_method_call())->put(variable, value);
+}
+
+inline std::string Arts::GlobalComm::get(const std::string& variable)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->get(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->get(variable);
+}
+
+inline void Arts::GlobalComm::erase(const std::string& variable)
+{
+ _cache?static_cast<Arts::GlobalComm_base*>(_cache)->erase(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->erase(variable);
+}
+
+inline bool Arts::TmpGlobalComm::put(const std::string& variable, const std::string& value)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->put(variable, value):static_cast<Arts::GlobalComm_base*>(_method_call())->put(variable, value);
+}
+
+inline std::string Arts::TmpGlobalComm::get(const std::string& variable)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->get(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->get(variable);
+}
+
+inline void Arts::TmpGlobalComm::erase(const std::string& variable)
+{
+ _cache?static_cast<Arts::GlobalComm_base*>(_cache)->erase(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->erase(variable);
+}
+
+inline std::string Arts::TraderOffer::interfaceName()
+{
+ return _cache?static_cast<Arts::TraderOffer_base*>(_cache)->interfaceName():static_cast<Arts::TraderOffer_base*>(_method_call())->interfaceName();
+}
+
+inline std::vector<std::string> * Arts::TraderOffer::getProperty(const std::string& name)
+{
+ return _cache?static_cast<Arts::TraderOffer_base*>(_cache)->getProperty(name):static_cast<Arts::TraderOffer_base*>(_method_call())->getProperty(name);
+}
+
+inline void Arts::TraderQuery::supports(const std::string& property, const std::string& value)
+{
+ _cache?static_cast<Arts::TraderQuery_base*>(_cache)->supports(property, value):static_cast<Arts::TraderQuery_base*>(_method_call())->supports(property, value);
+}
+
+inline std::vector<Arts::TraderOffer> * Arts::TraderQuery::query()
+{
+ return _cache?static_cast<Arts::TraderQuery_base*>(_cache)->query():static_cast<Arts::TraderQuery_base*>(_method_call())->query();
+}
+
+inline std::string Arts::Loader::dataVersion()
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->dataVersion():static_cast<Arts::Loader_base*>(_method_call())->dataVersion();
+}
+
+inline std::vector<Arts::TraderEntry> * Arts::Loader::traderEntries()
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->traderEntries():static_cast<Arts::Loader_base*>(_method_call())->traderEntries();
+}
+
+inline std::vector<Arts::ModuleDef> * Arts::Loader::modules()
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->modules():static_cast<Arts::Loader_base*>(_method_call())->modules();
+}
+
+inline Arts::Object Arts::Loader::loadObject(Arts::TraderOffer offer)
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->loadObject(offer):static_cast<Arts::Loader_base*>(_method_call())->loadObject(offer);
+}
+
+#endif /* CORE_H */
diff --git a/mcop/core.idl b/mcop/core.idl
new file mode 100644
index 0000000..33081e7
--- /dev/null
+++ b/mcop/core.idl
@@ -0,0 +1,715 @@
+/*
+
+ Copyright (C) 1999-2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+module Arts {
+// MCOP protocol
+
+enum HeaderMagic { MCOP_MAGIC = 0x4d434f50 }; /* gets marshalled as "MCOP" */
+ /* decimal 1296256848 */
+enum MessageType {
+ mcopMessageInvalid = 0, /* never send this */
+ mcopServerHello = 1,
+ mcopClientHello = 2,
+ mcopAuthAccept = 3,
+ mcopInvocation = 4,
+ mcopReturn = 5,
+ mcopOnewayInvocation = 6
+};
+
+/**
+ * This type is sent as header of each MCOP message.
+ */
+struct Header {
+ /**
+ * the value 0x504f434d, which is marshalled as MCOP
+ */
+ HeaderMagic magic;
+ long messageLength;
+ MessageType messageType;
+};
+
+/**
+ * This is sent as start of each normal (twoway) invocation
+ */
+struct Invocation {
+ /**
+ * The ID of the object receiving the request
+ */
+ long objectID;
+ /**
+ * The ID of the method that is to be invoked
+ */
+ long methodID;
+ /**
+ * A unique number of the request (needed to send the return code back)
+ */
+ long requestID;
+};
+
+/**
+ * This is sent as start of each oneway invocation
+ */
+struct OnewayInvocation {
+ /**
+ * The ID of the object receiving the request
+ */
+ long objectID;
+ /**
+ * The ID of the method that is to be invoked
+ */
+ long methodID;
+};
+
+/**
+ * Body of the mcopServerHello MCOP message
+ */
+struct ServerHello {
+ string mcopVersion;
+ string serverID;
+ sequence<string> authProtocols;
+ string authSeed;
+};
+
+/**
+ * Body of the mcopClientHello MCOP message
+ */
+struct ClientHello {
+ string serverID;
+ string authProtocol;
+ string authData;
+};
+
+/**
+ * The message you get when you connect a MCOP server. The MCOP server can
+ * send you some useful information here. Usually, it will send you
+ *
+ * GlobalComm=<object reference of a global comm interface>
+ * InterfaceRepo=<object reference of an interface repository>
+ *
+ * But as this is called "hints" it doesn't necessarily need to happen.
+ */
+struct AuthAccept {
+ sequence<string> hints;
+};
+
+/**
+ * An object reference
+ */
+struct ObjectReference {
+ /**
+ * A unique ID for the server the object is located on, (a server ID may
+ * i.e. be composed of start time, hostname, and pid)
+ */
+ string serverID;
+
+ /**
+ * The number of the object under that server
+ */
+ long objectID;
+
+ /**
+ * where the server holding object can be reached
+ */
+ sequence<string> urls;
+};
+
+// Interface definitions
+
+/**
+ * The definition of a parameter of a method
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct ParamDef {
+ string type;
+ string name;
+ sequence<string> hints;
+};
+
+/**
+ * Twoway methods are such where the calling process does a call and is
+ * suspended until some result (maybe even a void result) gets back.
+ *
+ * Oneway methods are one shot and forget methods: you send the invocation,
+ * and continue. Maybe it will be received, maybe executed later. You will
+ * never hear the result.
+ */
+enum MethodType {
+ methodOneway = 1,
+ methodTwoway = 2
+};
+
+/**
+ * The definition of a method.
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct MethodDef {
+ string name;
+ string type;
+ MethodType flags;
+
+ sequence<ParamDef> signature;
+ sequence<string> hints;
+};
+
+/**
+ * an attribute
+ *
+ * flags should contain things like
+ *
+ * @li attribute is readonly/writeonly/readwrite
+ * @li attribute is incoming/outgoing stream
+ * @li if it's a stream, it also should contain the information whether it is
+ * asynchronous or synchronous
+ * @li NB20000320: see InterfaceDef for the meaning of streamDefault
+ */
+enum AttributeType {
+ streamIn = 1,
+ streamOut = 2,
+ streamMulti = 4,
+ attributeStream = 8,
+ attributeAttribute = 16,
+ streamAsync = 32,
+ streamDefault = 64
+};
+
+/**
+ * The definition of an attribute and/or stream
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct AttributeDef {
+ string name;
+ string type;
+ AttributeType flags;
+ sequence<string> hints;
+};
+
+/**
+ * InterfaceDef - interface definition structure
+ *
+ * defines what methods/attributes a particular interface supports: these
+ * do not contain the methods/attributes of inherited interfaces.
+ *
+ * inheritedInterfaces only contains the names of Interfaces that this one
+ * inherits in exactly one step. So to see if interface XYZ is inherited
+ * from ABC, you need to check the "inheritedInterfaces" of XYZ, and their
+ * "inheritedInterfaces" and their "inheritedInterfaces" and so on.
+ *
+ * - NB20000320: defaultPorts allows to connect to those port by default if
+ * connection is made in the corresponding direction.
+ * It cannot be just an attribute flag because of the syntax
+ * on a separate line.
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+
+struct InterfaceDef {
+ string name;
+
+ sequence<string> inheritedInterfaces;
+ sequence<MethodDef> methods;
+ sequence<AttributeDef> attributes;
+
+ sequence<string> defaultPorts;
+ sequence<string> hints;
+};
+
+// Type definitions (struct's and such)
+
+/**
+ * One component of a struct
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct TypeComponent {
+ string type;
+ string name;
+ sequence<string> hints;
+};
+
+/**
+ * The definition of a struct
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct TypeDef {
+ string name;
+
+ sequence<TypeComponent> contents;
+ sequence<string> hints;
+};
+
+/**
+ * One item of an enum value
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct EnumComponent {
+ string name;
+
+ long value;
+ sequence<string> hints;
+};
+
+/**
+ * The definition of an enum
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct EnumDef {
+ /**
+ * name if the enum, "_anonymous_" for anonymous enum - of course, when
+ * using namespaces, this can also lead to things like "Arts::_anonymous_",
+ * which would mean an anonymous enum in the Arts namespace
+ */
+ string name;
+
+ sequence<EnumComponent> contents;
+ sequence<string> hints;
+};
+
+/**
+ * The contents of an idl file
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct ModuleDef {
+ string moduleName;
+
+ sequence<EnumDef> enums;
+ sequence<TypeDef> types;
+ sequence<InterfaceDef> interfaces;
+ sequence<string> hints;
+};
+
+/**
+ * The interface repository
+ */
+interface InterfaceRepo {
+ /**
+ * inserts the contents of a module into the interface repository
+ *
+ * @returns an ID which can be used to remove the entry again
+ */
+ long insertModule(ModuleDef newModule);
+
+ /**
+ * removes the contents of a module from the interface repository
+ */
+ void removeModule(long moduleID);
+
+ /**
+ * queries the definition of an interface
+ */
+ InterfaceDef queryInterface(string name);
+
+ /**
+ * queries the definition of a type
+ */
+ TypeDef queryType(string name);
+
+ /**
+ * queries the definition of an enum value
+ */
+ EnumDef queryEnum(string name);
+
+ /**
+ * queries all interfaces that inherit a given interface
+ */
+ sequence<string> queryChildren(string name);
+
+ /**
+ * queries all interfaces
+ */
+ sequence<string> queryInterfaces();
+
+ /**
+ * queries all types
+ */
+ sequence<string> queryTypes();
+
+ /**
+ * queries all enums
+ */
+ sequence<string> queryEnums();
+};
+
+enum TypeIdentification {
+ tiUnknown = 0,
+ tiVoid = 1,
+ tiLong = 2,
+ tiByte = 3,
+ tiString = 4,
+ tiBoolean = 5,
+ tiFloat = 6,
+ tiEnum = 128,
+ tiType = 129,
+ tiInterface = 130
+};
+
+interface InterfaceRepoV2 : InterfaceRepo {
+ /**
+ * identifies whether a type is a primitive, enum, type or interface,
+ * or not known at all
+ */
+ TypeIdentification identifyType(string name);
+};
+
+/**
+ * Flow System interface
+ */
+
+/**
+ * Internal use: implement distributed asynchronous streams.
+ *
+ * The FlowSystemSender object transmits the packets that should be sent
+ * over the stream via _allocCustomMessage (Object_base).
+ */
+interface FlowSystemSender {
+ /**
+ * This method is invoked whenever the receiver has finished processing
+ * a packet of the stream
+ */
+ oneway void processed();
+
+ /**
+ * This method is for telling the local FlowSystemSender to break the
+ * connection to the remote Receiver (it's not intended to be called
+ * remotely)
+ */
+ void disconnect();
+};
+
+/**
+ * Internal use: implement distributed asynchronous streams.
+ *
+ * The FlowSystemReceiver object receives and extracts the packets sent by
+ * the sender object and injects them in the notification system again.
+ */
+interface FlowSystemReceiver {
+ /**
+ * The custom message ID which should be used to send the stream packets
+ */
+ readonly attribute long receiveHandlerID;
+
+ /**
+ * This method is for telling the local FlowSystemReceiver to break the
+ * connection to the remote Sender (it's not intended to be called
+ * remotely)
+ */
+ void disconnect();
+};
+
+/**
+ * A flow system.
+ *
+ * Flow systems handle the streaming between MCOP objects. As this streaming
+ * is network transparent (at least for asynchronous streams) they have this
+ * remote interface.
+ */
+interface FlowSystem {
+ /**
+ * This starts a scheduling node
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void startObject(object node);
+
+ /**
+ * This stops a scheduling node
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void stopObject(object node);
+
+ /**
+ * This connects two objects, maybe even remote
+ *
+ * it is important that
+ * - sourceObject/sourcePort points to the node the signal flow is
+ * coming from
+ * - destObject/destPort points to the node/port the signal flow is
+ * going to
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void connectObject(object sourceObject, string sourcePort,
+ object destObject, string destPort);
+
+ /**
+ * This disconnects two objects, maybe even remote
+ *
+ * it is important that
+ * @li sourceObject/sourcePort points to the node the signal flow is
+ * coming from
+ * @li destObject/destPort points to the node/port the signal flow is
+ * going to
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void disconnectObject(object sourceObject, string sourcePort,
+ object destObject, string destPort);
+
+ /**
+ * queries the stream flags - returns 0 when such a stream isn't
+ * present
+ */
+ AttributeType queryFlags(object node, string port);
+
+ /**
+ * directly sets an audio port to a fixed value
+ */
+ void setFloatValue(object node, string port, float value);
+
+ /**
+ * network transparent connections
+ */
+ FlowSystemReceiver createReceiver(object destObject, string destPort,
+ FlowSystemSender sender);
+};
+
+/**
+ * A global communication space used to obtain initial object references
+ *
+ * MCOP needs a way to connect to initial (global) object references. This
+ * is done by these global communication spaces.
+ */
+interface GlobalComm {
+ /**
+ * puts a variable/value pair into the global communication
+ * space - it will not change the value of the variable if it is
+ * already present. Returns true if success, false if the variable
+ * was already there.
+ */
+ boolean put(string variable, string value);
+
+ /**
+ * gets the value of a variable out of the global communication
+ * space - it returns an empty string when the variable isn't there
+ */
+ string get(string variable);
+
+ /**
+ * removes a variable from the global communication space
+ */
+ void erase(string variable);
+};
+
+/**
+ * global communication based on the /tmp/mcop-<username> directory
+ */
+interface TmpGlobalComm : GlobalComm {
+};
+
+/*
+ * Trading interfaces follow - trading is used to locate objects with certain
+ * properties. This is especially recommended, if you want to allow that after
+ * your code has been released, people can extend it, without changing your
+ * code, by adding new components.
+ */
+
+/**
+ * TraderOffer - this contains an offer of an object (which is usually returned
+ * as result of a query.
+ */
+interface TraderOffer {
+ /**
+ * You can use this interface name to create one of the objects that
+ * fulfill your query
+ */
+ readonly attribute string interfaceName;
+
+ /**
+ * This allows you to query additional information about the offer,
+ * such as the author of the plugin, the name of the library that
+ * implements it (if it is a library) or similar.
+ *
+ * Since some properties support having multiple values, this always
+ * returns a sequence<string>, which may be empty if the property isn't
+ * present at all.
+ */
+ sequence<string> getProperty(string name);
+};
+
+/**
+ * TraderQuery - this is a query against the trader. The idea is simple: you
+ * say what you need, and the trader offers you components that do what you
+ * want.
+ */
+interface TraderQuery {
+ /**
+ * This restricts the query to only objects which support a "property"
+ * with the value "value". For instance, you could say
+ *
+ * aquery.supports("Interface","Arts::PlayObject");
+ *
+ * to restrict the matching objects to only those that support the
+ * interface Arts::PlayObject
+ */
+ void supports(string property, string value);
+
+ /**
+ * This performs the query, and returns a set of results
+ */
+ sequence<TraderOffer> query();
+};
+
+/**
+ * Arts::Object is the base object that every interface implicitely inherits
+ *
+ * it is also the source for generation of the Object_stub stuff
+ * (use mcopidl -e Arts::Object to avoid code generation for this interface)
+ */
+interface Object {
+ /**
+ * access to the flow system this object is running in
+ */
+ readonly attribute FlowSystem _flowSystem;
+
+ /** <interface description>
+ * returns the ID for methodinvocations to this specific method
+ * methodID = 0 => _lookupMethod (always)
+ */
+ long _lookupMethod(MethodDef methodDef);
+
+ /** <interface description>
+ * returns the name of the interface
+ * methodID = 1 => _interfaceName (always)
+ */
+ string _interfaceName();
+
+ /** <interface description>
+ * returns the interface description to a given interface
+ * methodID = 2 => _queryInterface (always)
+ */
+ InterfaceDef _queryInterface(string name);
+
+ /** <interface description>
+ * returns the type description to a given type
+ * methodID = 3 => _queryType (always)
+ */
+ TypeDef _queryType(string name);
+
+ /** <interface description>
+ * returns the enum description to a given enum
+ * methodID = 4 => _queryEnum (always)
+ */
+ EnumDef _queryEnum(string name);
+
+ /**
+ * stringifies the object to one string
+ */
+ string _toString();
+
+ /** <interface description>
+ * Run-time type compatibility check
+ */
+ boolean _isCompatibleWith(string interfacename);
+
+ /** <reference counting>
+ * prepares object for remote transmission (so that it will not be freed
+ * soon, since the remote receiver expects it to be there after receiving
+ * it)
+ */
+ void _copyRemote();
+
+ /** <reference counting>
+ * declares that the object is used remotely now (do that only after
+ * _copyRemote)
+ */
+ void _useRemote();
+
+ /** <reference counting>
+ * declares that the object is no longer used remotely
+ */
+ void _releaseRemote();
+
+ /** <aggregation>
+ * add a child object - this makes this object hold a strong reference to
+ * the child object (i.e. the child object will stay alive at least as
+ * long as the object does)
+ *
+ * if there is already a child with the same name, a postfix will be added
+ * automatically (i.e. if you add an object named "view" twice, the first
+ * will be called view, the second view1).
+ */
+ string _addChild(object child, string name);
+
+ /** <aggregation>
+ * removes a child object
+ */
+ boolean _removeChild(string name);
+
+ /** <aggregation>
+ * gets a child object
+ */
+ object _getChild(string name);
+
+ /** <aggregation>
+ * lists all children
+ */
+ sequence<string> _queryChildren();
+};
+
+/**
+ * a simple struct which can hold any other type
+ */
+struct Any {
+ string type;
+ sequence<byte> value;
+};
+
+/**
+ * TraderEntries as produced by the loader
+ */
+
+struct TraderEntry {
+ string interfaceName;
+ sequence<string> lines;
+};
+
+/**
+ * loader to load plugins (implemented in some language/binary format)
+ */
+interface Loader {
+ object loadObject(TraderOffer offer);
+
+ /*
+ * this is used for the type system to cache your trader data and
+ * module data as long as it stays unchanged
+ */
+ readonly attribute string dataVersion;
+
+ /*
+ * the trader entries of the components that can be loaded
+ */
+ readonly attribute sequence<TraderEntry> traderEntries;
+
+ /*
+ * the interface information of the components that can be loaded
+ */
+ readonly attribute sequence<ModuleDef> modules;
+};
+
+};
diff --git a/mcop/datapacket.cc b/mcop/datapacket.cc
new file mode 100644
index 0000000..8f9848f
--- /dev/null
+++ b/mcop/datapacket.cc
@@ -0,0 +1,65 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <string.h>
+#include "datapacket.h"
+#include "buffer.h"
+
+using namespace Arts;
+
+long GenericDataPacket::_staticDataPacketCount = 0;
+
+/**** specific DataPacket types ****/
+
+void FloatDataPacket::read(Buffer& stream)
+{
+ size = stream.readLong();
+ ensureCapacity(size);
+ for(int i=0;i<size;i++) contents[i] = stream.readFloat();
+}
+
+void FloatDataPacket::write(Buffer& stream)
+{
+ stream.writeLong(size);
+ for(int i=0;i<size;i++) stream.writeFloat(contents[i]);
+}
+
+void ByteDataPacket::read(Buffer& stream)
+{
+ size = stream.readLong();
+ ensureCapacity(size);
+
+ // we know that bytes are marshalled as bytes,
+ // so we can read them as block
+ unsigned char *buffer = (unsigned char *)stream.read(size);
+ if(buffer)
+ memcpy(contents,buffer,size);
+}
+
+void ByteDataPacket::write(Buffer& stream)
+{
+ // we know that bytes are marshalled as bytes,
+ // so we can write them as block
+
+ stream.writeLong(size);
+ stream.write(contents,size);
+}
diff --git a/mcop/datapacket.h b/mcop/datapacket.h
new file mode 100644
index 0000000..34cd211
--- /dev/null
+++ b/mcop/datapacket.h
@@ -0,0 +1,230 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef DATAPACKET_H
+#define DATAPACKET_H
+
+#include "arts_export.h"
+#include "buffer.h"
+
+/*
+ * BC - Status (2002-03-08): GenericDataChannel, DataPacket types
+ *
+ * These classes must be kept binary compatible, as the do interact with
+ * generated code. So you MUST KNOW WHAT YOU ARE DOING, once you start
+ * using the provided d pointers for extensions.
+ */
+
+namespace Arts {
+class GenericDataChannelPrivate;
+class GenericDataPacket;
+/*
+ * The GenericDataChannel interface is to be implemented by the flowsystem
+ */
+class ARTS_EXPORT GenericDataChannel {
+private:
+ GenericDataChannelPrivate *d; // unused
+
+protected:
+ friend class GenericDataPacket;
+
+ /*
+ * this is used internally by DataPacket
+ */
+ virtual void processedPacket(GenericDataPacket *packet) = 0;
+
+ /*
+ * used internally by DataPacket
+ */
+ virtual void sendPacket(GenericDataPacket *packet) = 0;
+
+public:
+ /*
+ * used to set pull delivery mode
+ */
+ virtual void setPull(int packets, int capacity) = 0;
+ virtual void endPull() = 0;
+
+ GenericDataChannel() : d(0)
+ {
+ }
+};
+
+/*
+ * DataPackets are the heard of asynchronous streaming (MCOP has synchronous
+ * and asynchronous streams). They are used
+ *
+ * - in the interface async streams expose to C++ implementations of MCOP
+ * interfaces (they directly deal with datapackets)
+ *
+ * - from the FlowSystem implemenentations
+ */
+
+/**
+ * The GenericDataPacket class provides the interface the flow system can
+ * use to deal with data packets.
+ */
+class GenericDataPacketPrivate;
+
+class ARTS_EXPORT GenericDataPacket {
+private:
+ GenericDataPacketPrivate *d;
+ static long _staticDataPacketCount;
+
+public:
+ /**
+ * the amount of active data packets (memory leak debugging only)
+ */
+ static long _dataPacketCount() { return _staticDataPacketCount; }
+
+ /**
+ * the channel this datapacket belongs to
+ */
+ GenericDataChannel *channel;
+
+ /**
+ * ensureCapactity ensures that there is room for at least capacity
+ * Elements in the packet. This is implemented destructive - that
+ * means: you may not find your old contents in the packet after
+ * calling ensureCapacity
+ */
+ virtual void ensureCapacity(int capacity) = 0;
+
+ /**
+ * read/write write the contents of the packet. Read will also
+ * automatically ensure that capacity is adapted before reading.
+ */
+ virtual void read(Buffer& stream) = 0;
+ virtual void write(Buffer& stream) = 0;
+
+ /**
+ * having size here (and not in the derived concrete DataPackets) is so
+ * that we can see whether the sender can't supply more data (and starts
+ * sending zero size packets
+ */
+ int size;
+
+ /**
+ * useCount is to be set from sendPacket
+ */
+ int useCount;
+
+ inline void send()
+ {
+ channel->sendPacket(this);
+ }
+ inline void processed()
+ {
+ useCount--;
+ if(useCount == 0)
+ {
+ if(channel)
+ channel->processedPacket(this);
+ else
+ delete this;
+ }
+ }
+
+ virtual ~GenericDataPacket()
+ {
+ _staticDataPacketCount--;
+ }
+
+protected:
+ GenericDataPacket(GenericDataChannel *channel)
+ :d(0),channel(channel),useCount(0)
+ {
+ _staticDataPacketCount++;
+ }
+};
+
+/**
+ * The DataPacket<T> interface is what C++ implementations of MCOP interfaces
+ * will need to use.
+ */
+template<class T>
+class DataPacket : public GenericDataPacket {
+public:
+ T *contents;
+
+protected:
+ DataPacket(GenericDataChannel *channel)
+ : GenericDataPacket(channel) {}
+ ~DataPacket() {}
+};
+
+/**
+ * The RawDataPacket<T> interface handles raw class T arrays of data
+ */
+template<class T>
+class RawDataPacket : public DataPacket<T> {
+protected:
+ int capacity;
+ void ensureCapacity(int newCapacity)
+ {
+ if(newCapacity > capacity)
+ {
+ delete[] this->contents;
+ capacity = newCapacity;
+ this->contents = new T[capacity];
+ }
+ }
+ RawDataPacket(int capacity, GenericDataChannel *channel)
+ :DataPacket<T>(channel), capacity(capacity)
+ {
+ this->size = capacity;
+ this->contents = new T[capacity];
+ }
+ ~RawDataPacket()
+ {
+ delete[] this->contents;
+ }
+};
+
+/**
+ * FloatDataPacket finally is one concrete DataPacket (which contains the
+ * information how to marshal a datapacket of type float)
+ */
+class ARTS_EXPORT FloatDataPacket : public RawDataPacket<float> {
+public:
+ FloatDataPacket(int capacity, GenericDataChannel *channel)
+ : RawDataPacket<float>(capacity, channel)
+ {
+ //
+ }
+ void read(Buffer& stream);
+ void write(Buffer& stream);
+};
+
+class ARTS_EXPORT ByteDataPacket : public RawDataPacket<mcopbyte> {
+public:
+ ByteDataPacket(int capacity, GenericDataChannel *channel)
+ : RawDataPacket<mcopbyte>(capacity, channel)
+ {
+ //
+ }
+ void read(Buffer& stream);
+ void write(Buffer& stream);
+};
+
+}
+#endif
diff --git a/mcop/debug.cc b/mcop/debug.cc
new file mode 100644
index 0000000..208727b
--- /dev/null
+++ b/mcop/debug.cc
@@ -0,0 +1,821 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ (see also below for details on the copyright of arts_strdup_printf,
+ which is taken from GLib)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "debug.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "thread.h"
+
+static int arts_debug_level = Arts::Debug::lInfo;
+static bool arts_debug_abort = false;
+static const char *arts_debug_prefix = "";
+static char *messageAppName = 0;
+static Arts::Mutex *arts_debug_mutex = 0;
+
+/* routines for variable length sprintf without buffer overflow (from GLib) */
+static char* arts_strdup_vprintf(const char *format, va_list args1);
+
+namespace Arts {
+
+static char * shell_quote(const char *s)
+{
+ char *result;
+ char *p;
+ p = result = static_cast<char*>( malloc(strlen(s)*5+1) );
+ while(*s)
+ {
+ if (*s == '\'')
+ {
+ *p++ = '\'';
+ *p++ = '"';
+ *p++ = *s++;
+ *p++ = '"';
+ *p++ = '\'';
+ }
+ else
+ {
+ *p++ = *s++;
+ }
+ }
+ *p = '\0';
+ return result;
+}
+
+/*
+ * Call the graphical application to display a message, if
+ * defined. Otherwise, send to standard error. Debug messages are
+ * always sent to standard error because they tend to be very verbose.
+ * Note that the external application is run in the background to
+ * avoid blocking the sound server.
+ */
+static void output_message(Debug::Level level, const char *msg) {
+ char *quoted_msg;
+ char *buff = 0;
+
+ /* default to text output if no message app is defined or if it is a debug message. */
+ if (messageAppName == 0 || !strcmp(messageAppName, "") || (level == Debug::lDebug))
+ {
+ fprintf(stderr, "%s\n", msg);
+ return;
+ }
+
+ quoted_msg = shell_quote(msg);
+ switch (level) {
+ case Debug::lFatal:
+ buff = arts_strdup_printf("%s -e 'Sound server fatal error:\n\n%s' &", messageAppName, quoted_msg);
+ break;
+ case Debug::lWarning:
+ buff = arts_strdup_printf("%s -w 'Sound server warning message:\n\n%s' &", messageAppName, quoted_msg);
+ break;
+ case Debug::lInfo:
+ buff = arts_strdup_printf("%s -i 'Sound server informational message:\n\n%s' &", messageAppName, quoted_msg);
+ break;
+ default:
+ break; // avoid compile warning
+ }
+ free(quoted_msg);
+
+ if(buff != 0)
+ {
+ system(buff);
+ free(buff);
+ }
+}
+
+/*
+ * Display a message using output_message. If the message is the same
+ * as the previous one, just increment a count but don't display
+ * it. This prevents flooding the user with duplicate warnings. If the
+ * message is not the same as the previous one, then we report the
+ * previously repeated message (if any) and reset the last message and
+ * count.
+ */
+static void display_message(Debug::Level level, const char *msg) {
+ static char lastMsg[1024];
+ static Debug::Level lastLevel;
+ static int msgCount = 0;
+
+ if(arts_debug_mutex)
+ arts_debug_mutex->lock();
+
+ if (!strncmp(msg, lastMsg, 1024))
+ {
+ msgCount++;
+ } else {
+ if (msgCount > 0)
+ {
+ char *buff;
+ buff = arts_strdup_printf("%s\n(The previous message was repeated %d times.)", lastMsg, msgCount);
+ output_message(lastLevel, buff);
+ free(buff);
+ }
+ strncpy(lastMsg, msg, 1024);
+ lastMsg[ 1023 ] = '\0';
+ lastLevel = level;
+ msgCount = 0;
+ output_message(level, msg);
+ }
+
+ if(arts_debug_mutex)
+ arts_debug_mutex->unlock();
+}
+
+static class DebugInitFromEnv {
+public:
+ DebugInitFromEnv() {
+ const char *env = getenv("ARTS_DEBUG");
+ if(env)
+ {
+ if(strcmp(env,"debug") == 0)
+ arts_debug_level = Debug::lDebug;
+ else if(strcmp(env,"info") == 0)
+ arts_debug_level = Debug::lInfo;
+ else if(strcmp(env,"warning") == 0)
+ arts_debug_level = Debug::lWarning;
+ else if(strcmp(env,"quiet") == 0)
+ arts_debug_level = Debug::lFatal;
+ else
+ {
+ fprintf(stderr,
+ "ARTS_DEBUG must be one of debug,info,warning,quiet\n");
+ }
+ }
+ env = getenv("ARTS_DEBUG_ABORT");
+ if(env)
+ arts_debug_abort = true;
+ }
+} debugInitFromEnv;
+
+}
+
+void Arts::Debug::init(const char *prefix, Level level)
+{
+ arts_debug_level = level;
+ arts_debug_prefix = prefix;
+}
+
+void Arts::Debug::fatal(const char *fmt, ...)
+{
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lFatal, buff);
+ free(buff);
+
+ if(arts_debug_abort) abort();
+ exit(1);
+}
+
+void Arts::Debug::warning(const char *fmt, ...)
+{
+ if(lWarning >= arts_debug_level)
+ {
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lWarning, buff);
+ free(buff);
+ }
+}
+
+void Arts::Debug::info(const char *fmt, ...)
+{
+ if(lInfo >= arts_debug_level)
+ {
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lInfo, buff);
+ free(buff);
+ }
+}
+
+void Arts::Debug::debug(const char *fmt, ...)
+{
+ if(lDebug >= arts_debug_level)
+ {
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lDebug, buff);
+ free(buff);
+ }
+}
+
+void Arts::Debug::messageApp(const char *appName)
+{
+ messageAppName = (char*) realloc(messageAppName, strlen(appName)+1);
+ strcpy(messageAppName, appName);
+}
+
+void Arts::Debug::initMutex()
+{
+ arts_return_if_fail(arts_debug_mutex == 0);
+
+ arts_debug_mutex = new Arts::Mutex();
+}
+
+void Arts::Debug::freeMutex()
+{
+ arts_return_if_fail(arts_debug_mutex != 0);
+
+ delete arts_debug_mutex;
+ arts_debug_mutex = 0;
+}
+
+/*
+ * For the sake of portability (snprintf is non-portable), what follows is an
+ * implementation of a variant g_strdup_printf, to format debug messages of
+ * an arbitary length appropriately. This is reduntant with flow/gsl/gslglib.c,
+ * however, as libmcop doesn't necessarily link against gslglib.c, this is a
+ * more-or-less complete copy.
+ */
+
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GScanner: Flexible lexical scanner for general purpose.
+ * Copyright (C) 1997, 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define g_warning printf
+#define g_strerror strerror
+
+/*--- gslglib.h ---*/
+
+#include <limits.h>
+#include <float.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+/* --- GLib typedefs --- */
+typedef void* gpointer;
+typedef const void* gconstpointer;
+typedef char gchar;
+typedef unsigned char guchar;
+typedef signed short gshort;
+typedef unsigned short gushort;
+typedef signed int gint;
+typedef unsigned int guint;
+typedef signed long glong;
+typedef unsigned long gulong;
+typedef float gfloat;
+typedef double gdouble;
+typedef size_t gsize;
+typedef gchar gint8;
+typedef guchar guint8;
+typedef gshort gint16;
+typedef gushort guint16;
+typedef gint gint32;
+typedef guint guint32;
+typedef gint gboolean;
+typedef gint32 GTime;
+#ifdef __alpha
+typedef long int gint64;
+typedef unsigned long int guint64;
+#else
+typedef long long int gint64;
+typedef unsigned long long int guint64;
+#endif
+typedef struct _GString GString;
+
+/* --- standard macros --- */
+#ifndef ABS
+#define ABS(a) ((a) > 0 ? (a) : -(a))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef CLAMP
+#define CLAMP(v,l,h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v))
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+/* --- configure stuff!!! --- */
+#ifdef WORDS_BIGENDIAN
+#define G_BYTE_ORDER G_BIG_ENDIAN
+#else
+#define G_BYTE_ORDER G_LITTLE_ENDIAN
+#endif
+
+/* #define GLIB_HAVE_STPCPY 1 */
+/* Define G_VA_COPY() to do the right thing for copying va_list variables.
+ * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
+ */
+#if !defined (G_VA_COPY)
+# if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32) || defined(WIN32)) || defined(__s390__) || defined(__x86_64__)
+# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
+# elif defined (G_VA_COPY_AS_ARRAY)
+# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list))
+# else /* va_list is a pointer */
+# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2))
+# endif /* va_list is a pointer */
+#endif /* !G_VA_COPY */
+
+/* --- glib macros --- */
+#define G_MINFLOAT FLT_MIN
+#define G_MAXFLOAT FLT_MAX
+#define G_MINDOUBLE DBL_MIN
+#define G_MAXDOUBLE DBL_MAX
+#define G_MINSHORT SHRT_MIN
+#define G_MAXSHORT SHRT_MAX
+#define G_MAXUSHORT USHRT_MAX
+#define G_MININT INT_MIN
+#define G_MAXINT INT_MAX
+#define G_MAXUINT UINT_MAX
+#define G_MINLONG LONG_MIN
+#define G_MAXLONG LONG_MAX
+#define G_MAXULONG ULONG_MAX
+#define G_USEC_PER_SEC 1000000
+#define G_LITTLE_ENDIAN 1234
+#define G_BIG_ENDIAN 4321
+
+#define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string)
+#define G_STRINGIFY_ARG(contents) #contents
+#if defined __GNUC__ && !defined __cplusplus
+# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()"
+#else
+# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__)
+#endif
+
+/* subtract from biased_exponent to form base2 exponent (normal numbers) */
+typedef union _GDoubleIEEE754 GDoubleIEEE754;
+typedef union _GFloatIEEE754 GFloatIEEE754;
+#define G_IEEE754_FLOAT_BIAS (127)
+#define G_IEEE754_DOUBLE_BIAS (1023)
+/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
+#define G_LOG_2_BASE_10 (0.30102999566398119521)
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+union _GFloatIEEE754
+{
+ gfloat v_float;
+ struct {
+ guint mantissa : 23;
+ guint biased_exponent : 8;
+ guint sign : 1;
+ } mpn;
+};
+union _GDoubleIEEE754
+{
+ gdouble v_double;
+ struct {
+ guint mantissa_low : 32;
+ guint mantissa_high : 20;
+ guint biased_exponent : 11;
+ guint sign : 1;
+ } mpn;
+};
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+union _GFloatIEEE754
+{
+ gfloat v_float;
+ struct {
+ guint sign : 1;
+ guint biased_exponent : 8;
+ guint mantissa : 23;
+ } mpn;
+};
+union _GDoubleIEEE754
+{
+ gdouble v_double;
+ struct {
+ guint sign : 1;
+ guint biased_exponent : 11;
+ guint mantissa_high : 20;
+ guint mantissa_low : 32;
+ } mpn;
+};
+#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+#error unknown ENDIAN type
+#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define GLIB_SIZEOF_INTMAX (8 /* educated guess */)
+
+typedef struct
+{
+ guint min_width;
+ guint precision;
+ gboolean alternate_format, zero_padding, adjust_left, locale_grouping;
+ gboolean add_space, add_sign, possible_sign, seen_precision;
+ gboolean mod_half, mod_long, mod_extra_long;
+} PrintfArgSpec;
+
+
+static gsize
+printf_string_upper_bound (const gchar *format,
+ gboolean may_warn,
+ va_list args)
+{
+ static gboolean honour_longs = sizeof(long) > 4 || sizeof(void*) > 4;
+ gsize len = 1;
+
+ if (!format)
+ return len;
+
+ while (*format)
+ {
+ register gchar c = *format++;
+
+ if (c != '%')
+ len += 1;
+ else /* (c == '%') */
+ {
+ PrintfArgSpec spec = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ gboolean seen_l = FALSE, conv_done = FALSE;
+ gsize conv_len = 0;
+ const gchar *spec_start = format;
+
+ do
+ {
+ c = *format++;
+ switch (c)
+ {
+ GDoubleIEEE754 u_double;
+ guint v_uint;
+ gint v_int;
+ const gchar *v_string;
+
+ /* beware of positional parameters
+ */
+ case '$':
+ if (may_warn)
+ g_warning (G_STRLOC ": unable to handle positional parameters (%%n$)");
+ len += 1024; /* try adding some safety padding */
+ break;
+
+ /* parse flags
+ */
+ case '#':
+ spec.alternate_format = TRUE;
+ break;
+ case '0':
+ spec.zero_padding = TRUE;
+ break;
+ case '-':
+ spec.adjust_left = TRUE;
+ break;
+ case ' ':
+ spec.add_space = TRUE;
+ break;
+ case '+':
+ spec.add_sign = TRUE;
+ break;
+ case '\'':
+ spec.locale_grouping = TRUE;
+ break;
+
+ /* parse output size specifications
+ */
+ case '.':
+ spec.seen_precision = TRUE;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ v_uint = c - '0';
+ c = *format;
+ while (c >= '0' && c <= '9')
+ {
+ format++;
+ v_uint = v_uint * 10 + c - '0';
+ c = *format;
+ }
+ if (spec.seen_precision)
+ spec.precision = MAX (spec.precision, v_uint);
+ else
+ spec.min_width = MAX (spec.min_width, v_uint);
+ break;
+ case '*':
+ v_int = va_arg (args, int);
+ if (spec.seen_precision)
+ {
+ /* forget about negative precision */
+ if (v_int >= 0)
+ spec.precision = MAX (spec.precision, (unsigned)v_int);
+ }
+ else
+ {
+ if (v_int < 0)
+ {
+ v_int = - v_int;
+ spec.adjust_left = TRUE;
+ }
+ spec.min_width = MAX (spec.min_width, (unsigned)v_int);
+ }
+ break;
+
+ /* parse type modifiers
+ */
+ case 'h':
+ spec.mod_half = TRUE;
+ break;
+ case 'l':
+ if (!seen_l)
+ {
+ spec.mod_long = TRUE;
+ seen_l = TRUE;
+ break;
+ }
+ /* else, fall through */
+ case 'L':
+ case 'q':
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ break;
+ case 'z':
+ case 'Z':
+ if (sizeof(size_t))
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+ case 't':
+ if (sizeof(ptrdiff_t) > 4)
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+ case 'j':
+ if (GLIB_SIZEOF_INTMAX > 4)
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+
+ /* parse output conversions
+ */
+ case '%':
+ conv_len += 1;
+ break;
+ case 'O':
+ case 'D':
+ case 'I':
+ case 'U':
+ /* some C libraries feature long variants for these as well? */
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 'o':
+ conv_len += 2;
+ /* fall through */
+ case 'd':
+ case 'i':
+ conv_len += 1; /* sign */
+ /* fall through */
+ case 'u':
+ conv_len += 4;
+ /* fall through */
+ case 'x':
+ case 'X':
+ spec.possible_sign = TRUE;
+ conv_len += 10;
+ if (spec.mod_long && honour_longs)
+ conv_len *= 2;
+ if (spec.mod_extra_long)
+ conv_len *= 2;
+ if (spec.mod_extra_long)
+ {
+ (void) va_arg (args, gint64);
+ }
+ else if (spec.mod_long)
+ (void) va_arg (args, long);
+ else
+ (void) va_arg (args, int);
+ break;
+ case 'A':
+ case 'a':
+ /* 0x */
+ conv_len += 2;
+ /* fall through */
+ case 'g':
+ case 'G':
+ case 'e':
+ case 'E':
+ case 'f':
+ spec.possible_sign = TRUE;
+ /* n . dddddddddddddddddddddddd E +- eeee */
+ conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
+ if (may_warn && spec.mod_extra_long)
+ g_warning (G_STRLOC ": unable to handle long double, collecting double only");
+#ifdef HAVE_LONG_DOUBLE
+#error need to implement special handling for long double
+#endif
+ u_double.v_double = va_arg (args, double);
+ /* %f can expand up to all significant digits before '.' (308) */
+ if (c == 'f' &&
+ u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
+ {
+ gint exp = u_double.mpn.biased_exponent;
+
+ exp -= G_IEEE754_DOUBLE_BIAS;
+ exp = (gint)(exp * G_LOG_2_BASE_10 + 1);
+ conv_len += ABS (exp); /* exp can be <0 */
+ }
+ /* some printf() implementations require extra padding for rounding */
+ conv_len += 2;
+ /* we can't really handle locale specific grouping here */
+ if (spec.locale_grouping)
+ conv_len *= 2;
+ break;
+ case 'C':
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 'c':
+ conv_len += spec.mod_long ? MB_LEN_MAX : 1;
+ (void) va_arg (args, int);
+ break;
+ case 'S':
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 's':
+ v_string = va_arg (args, char*);
+ if (!v_string)
+ conv_len += 8; /* hold "(null)" */
+ else if (spec.seen_precision)
+ conv_len += spec.precision;
+ else
+ conv_len += strlen (v_string);
+ conv_done = TRUE;
+ if (spec.mod_long)
+ {
+ if (may_warn)
+ g_warning (G_STRLOC": unable to handle wide char strings");
+ len += 1024; /* try adding some safety padding */
+ }
+ break;
+ case 'P': /* do we actually need this? */
+ /* fall through */
+ case 'p':
+ spec.alternate_format = TRUE;
+ conv_len += 10;
+ if (honour_longs)
+ conv_len *= 2;
+ /* fall through */
+ case 'n':
+ conv_done = TRUE;
+ (void) va_arg (args, void*);
+ break;
+ case 'm':
+ /* there's not much we can do to be clever */
+ v_string = g_strerror (errno);
+ v_uint = v_string ? strlen (v_string) : 0;
+ conv_len += MAX (256, v_uint);
+ break;
+
+ /* handle invalid cases
+ */
+ case '\000':
+ /* no conversion specification, bad bad */
+ conv_len += format - spec_start;
+ break;
+ default:
+ if (may_warn)
+ g_warning (G_STRLOC": unable to handle `%c' while parsing format",
+ c);
+ break;
+ }
+ conv_done |= conv_len > 0;
+ }
+ while (!conv_done);
+ /* handle width specifications */
+ conv_len = MAX (conv_len, MAX (spec.precision, spec.min_width));
+ /* handle flags */
+ conv_len += spec.alternate_format ? 2 : 0;
+ conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
+ /* finally done */
+ len += conv_len;
+ } /* else (c == '%') */
+ } /* while (*format) */
+
+ return len;
+}
+
+static char*
+#ifdef __GNUC__
+__attribute__ ( (format (printf, 1, 0) ) )
+#endif
+arts_strdup_vprintf (const char *format, va_list args1)
+{
+ gchar *buffer;
+#ifdef HAVE_VASPRINTF
+ if (vasprintf (&buffer, format, args1) < 0)
+ buffer = NULL;
+#else
+ va_list args2;
+
+ G_VA_COPY (args2, args1);
+
+ buffer = (gchar *)malloc (printf_string_upper_bound (format, TRUE, args1));
+
+ vsprintf (buffer, format, args2);
+ va_end (args2);
+#endif
+ return buffer;
+}
+
+char*
+#ifdef __GNUC__
+__attribute__ ( (format (printf, 1, 0) ) )
+#endif
+arts_strdup_printf (const char *format, ...)
+{
+ gchar *buffer;
+ va_list args;
+
+ va_start (args, format);
+ buffer = arts_strdup_vprintf (format, args);
+ va_end (args);
+
+ return buffer;
+}
diff --git a/mcop/debug.h b/mcop/debug.h
new file mode 100644
index 0000000..94cd01f
--- /dev/null
+++ b/mcop/debug.h
@@ -0,0 +1,138 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+
+ Some inspiration taken from glib.
+ Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ Modified by the GLib Team and others 1997-1999.
+
+ */
+
+#ifndef _ARTSDEBUG_H_
+#define _ARTSDEBUG_H_
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Debug.
+ *
+ * Collection class, no instance, no members. Thus binary compatible (will
+ * be kept).
+ */
+
+#define arts_fatal ::Arts::Debug::fatal
+#define arts_warning ::Arts::Debug::warning
+#define arts_info ::Arts::Debug::info
+#define arts_debug ::Arts::Debug::debug
+
+/* source compatibility with older sources */
+#define artsdebug ::Arts::Debug::debug
+#define setartsdebug(x) arts_warning("setartsdebug is obsolete")
+
+#ifdef __GNUC__
+
+#define arts_return_if_fail(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d (%s): assertion failed: (%s)", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
+ return; \
+ } \
+ } while(0)
+
+#define arts_return_val_if_fail(expr,val) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d (%s): assertion failed: (%s)", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
+ return (val); \
+ } \
+ } while(0)
+
+#define arts_assert(expr) \
+ do { \
+ if (!(expr)) \
+ arts_fatal ("file %s: line %d (%s): assertion failed: (%s)", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
+ } while(0)
+
+#else
+
+#define arts_return_if_fail(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d: assertion failed: (%s)", \
+ __FILE__, __LINE__, #expr); \
+ return; \
+ } \
+ } while(0)
+
+#define arts_return_val_if_fail(expr,val) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d: assertion failed: (%s)", \
+ __FILE__, __LINE__, #expr); \
+ return (val); \
+ } \
+ } while(0)
+
+#define arts_assert(expr) \
+ do { \
+ if (!(expr)) \
+ arts_fatal ("file %s: line %d: assertion failed: (%s)", \
+ __FILE__, __LINE__, #expr); \
+ } while(0)
+
+#endif
+
+ARTS_EXPORT char* arts_strdup_printf (const char *format, ...);
+
+namespace Arts {
+ class ARTS_EXPORT Debug {
+ public:
+ enum Level { lFatal = 3, lWarning = 2, lInfo = 1, lDebug = 0 };
+
+ /**
+ * Initializes at which is the minimum level to react to. If you
+ * call this, call this before creating the Arts::Dispatcher object.
+ */
+ static void init(const char *prefix, Level level);
+
+ static void fatal(const char *fmt,...); // print on stderr & abort
+ static void warning(const char *fmt,...); // print on stderr
+ static void info(const char *fmt,...); // print on stdout
+ static void debug(const char *fmt,...); // print on stdout
+
+ /**
+ * This method sets the name of an external application to
+ * display messages graphically.
+ */
+ static void messageApp(const char *appName);
+
+ static void initMutex(); // called from the dispatcher constructor
+ static void freeMutex(); // called from the dispatcher destructor
+ };
+}
+
+#endif
diff --git a/mcop/delayedreturn.cc b/mcop/delayedreturn.cc
new file mode 100644
index 0000000..1eab0ed
--- /dev/null
+++ b/mcop/delayedreturn.cc
@@ -0,0 +1,71 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <assert.h>
+#include "anyref.h"
+#include "connection.h"
+#include "delayedreturn.h"
+
+using namespace Arts;
+using namespace std;
+
+DelayedReturn::DelayedReturn() : buffer(0), connection(0)
+{
+ //
+}
+
+void DelayedReturn::initialize(Connection *connection, Buffer *buffer)
+{
+ this->connection = connection;
+ this->buffer = buffer;
+ connection->_copy();
+}
+
+DelayedReturn::~DelayedReturn()
+{
+ connection->_release();
+ connection = 0;
+ buffer = 0;
+}
+
+void DelayedReturn::doReturn(const AnyConstRef& value)
+{
+ assert(connection);
+ assert(buffer);
+
+ value.write(buffer);
+ buffer->patchLength();
+ connection->qSendBuffer(buffer);
+
+ delete this;
+}
+
+void DelayedReturn::doReturn()
+{
+ assert(connection);
+ assert(buffer);
+
+ buffer->patchLength();
+ connection->qSendBuffer(buffer);
+
+ delete this;
+}
diff --git a/mcop/delayedreturn.h b/mcop/delayedreturn.h
new file mode 100644
index 0000000..fe2a140
--- /dev/null
+++ b/mcop/delayedreturn.h
@@ -0,0 +1,102 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_MCOP_DELAYEDRETURN_H
+#define ARTS_MCOP_DELAYEDRETURN_H
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): DelayedReturn
+ *
+ * This class will be kept binary compatible. It has a private d-pointer for
+ * further extensions.
+ */
+
+namespace Arts {
+
+class AnyConstRef;
+class Buffer;
+class Connection;
+class DelayedReturnPrivate;
+
+/**
+ * The "DelayedReturn" class implements delayed returning from functions.
+ *
+ * For instance, suppose you would like to return from a wait() operation
+ * only after a certain time has passed, without blocking other clients
+ * from using your interface during this time.
+ *
+ * Your implementation (in the skel file) of wait should look like this
+ *
+ * <pre>
+ * static DelayedReturn *delayedReturn = 0;
+ *
+ * bool TimeServer::waitUntil(long time)
+ * {
+ * if(time(0) < time)
+ * {
+ * // ... initialize timer here ...
+ * delayedReturn = Dispatcher::the()->delayReturn();
+ * }
+ * return false;
+ * }
+ *
+ * void timerEvent()
+ * {
+ * delayedReturn->doReturn(true);
+ * }
+ * </pre>
+ *
+ * NOTE: this class breaks for local use (i.e. you can only use it if the
+ * call was a remote call), so it is strongly recommended not to use it
+ * unless there is no alternative (and you should really know what you are
+ * doing, too).
+ */
+class ARTS_EXPORT DelayedReturn {
+friend class Dispatcher;
+private:
+ DelayedReturnPrivate *d;
+
+protected:
+ Buffer *buffer;
+ Connection *connection;
+
+ DelayedReturn();
+ void initialize(Connection *connection, Buffer *buffer);
+ ~DelayedReturn();
+
+public:
+ /**
+ * call this only once to make the request really return
+ */
+ void doReturn(const AnyConstRef& value);
+
+ /**
+ * return without value (for void functions)
+ */
+ void doReturn();
+};
+
+}
+
+#endif /* ARTS_MCOP_DELAYEDRETURN_H */
diff --git a/mcop/dispatcher.cc b/mcop/dispatcher.cc
new file mode 100644
index 0000000..c055f64
--- /dev/null
+++ b/mcop/dispatcher.cc
@@ -0,0 +1,1090 @@
+ /*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "dispatcher.h"
+#include "delayedreturn.h"
+#include "startupmanager.h"
+#include "unixconnection.h"
+#include "tcpconnection.h"
+#include "referenceclean.h"
+#include "core.h"
+#include "md5auth.h"
+#include "mcoputils.h"
+#include "loopback.h"
+#include "debug.h"
+#include "ifacerepo_impl.h"
+#include "thread.h"
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <signal.h>
+#include <cstring>
+#include <cstdlib>
+#include <errno.h>
+#include <iostream>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#elif HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+/* Dispatcher private data class (to ensure binary compatibility) */
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class DispatcherWakeUpHandler;
+
+class DispatcherPrivate {
+public:
+ GlobalComm globalComm;
+ InterfaceRepo interfaceRepo;
+ AuthAccept *accept;
+ LoopbackConnection *loopbackConnection;
+ DelayedReturn *delayedReturn;
+ bool allowNoAuthentication;
+ Mutex mutex;
+
+ /*
+ * Thread condition that gets signalled whenever something relevant for
+ * waitForResult happens. Note that broken connections are also relevant
+ * for waitForResult.
+ */
+ ThreadCondition requestResultCondition;
+
+ /*
+ * Thread condition that gets signalled whenever something relevant for
+ * the server connection process happens. This is either:
+ * - authentication fails
+ * - authentication succeeds
+ * - a connection breaks
+ */
+ ThreadCondition serverConnectCondition;
+
+ DispatcherWakeUpHandler *wakeUpHandler;
+};
+
+/**
+ * Class that performs dispatcher wakeup.
+ *
+ * The sending thread (requesting wakeup) writes a byte to a pipe. The
+ * main thread watches the pipe, and as soon as the byte arrives, gets
+ * woken by the IOManager. This should work, no matter what type of IOManager
+ * is used (i.e. StdIOManager/GIOManager/QIOManager).
+ */
+class DispatcherWakeUpHandler : public IONotify {
+private:
+ enum { wReceive = 0, wSend = 1 };
+ int wakeUpPipe[2];
+
+public:
+ DispatcherWakeUpHandler()
+ {
+ if(pipe(wakeUpPipe) != 0)
+ arts_fatal("can't initialize wakeUp pipe (%s)",strerror(errno));
+
+ Dispatcher::the()->ioManager()->watchFD(wakeUpPipe[wReceive],
+ IOType::read | IOType::reentrant, this);
+ }
+ virtual ~DispatcherWakeUpHandler()
+ {
+ Dispatcher::the()->ioManager()->remove(this, IOType::all);
+
+ close(wakeUpPipe[wSend]);
+ close(wakeUpPipe[wReceive]);
+ }
+ void notifyIO(int fd, int type)
+ {
+ arts_return_if_fail(fd == wakeUpPipe[wReceive]);
+ arts_return_if_fail(type == IOType::read);
+
+ mcopbyte one;
+ int result;
+ do
+ result = read(wakeUpPipe[wReceive],&one,1);
+ while(result < 0 && errno == EINTR);
+ }
+ void wakeUp()
+ {
+ mcopbyte one = 1;
+
+ int result;
+ do
+ result = write(wakeUpPipe[wSend],&one,1);
+ while(result < 0 && errno == EINTR);
+ }
+};
+
+}
+
+Dispatcher *Dispatcher::_instance = 0;
+
+Dispatcher::Dispatcher(IOManager *ioManager, StartServer startServer)
+{
+ assert(!_instance);
+ _instance = this;
+
+ /* private data pointer */
+ d = new DispatcherPrivate();
+
+ lock();
+
+ /* makes arts_debug/arts_message/arts_return_if_fail/... threadsafe */
+ Debug::initMutex();
+
+ generateServerID();
+
+ if(ioManager)
+ {
+ _ioManager = ioManager;
+ deleteIOManagerOnExit = false;
+ }
+ else
+ {
+ _ioManager = new StdIOManager;
+ deleteIOManagerOnExit = true;
+ }
+
+ d->wakeUpHandler = new DispatcherWakeUpHandler;
+
+ objectManager = new ObjectManager;
+
+ notificationManager = new NotificationManager;
+
+ if(startServer & startUnixServer)
+ {
+ unixServer = new UnixServer(this,serverID);
+ if(!unixServer->running())
+ {
+ delete unixServer;
+ arts_warning("MCOP: couldn't start UnixServer");
+ unixServer = 0;
+ }
+ }
+ else unixServer = 0;
+
+ if(startServer & startTCPServer)
+ {
+ tcpServer = new TCPServer(this);
+ if(!tcpServer->running())
+ {
+ delete tcpServer;
+ arts_warning("MCOP: couldn't start TCPServer");
+ tcpServer = 0;
+ }
+ }
+ else tcpServer = 0;
+
+ d->allowNoAuthentication = startServer & noAuthentication;
+ d->accept = 0;
+ d->loopbackConnection = new LoopbackConnection(serverID);
+ d->interfaceRepo = InterfaceRepo::_from_base(new InterfaceRepo_impl());
+ d->delayedReturn = 0;
+
+ _flowSystem = 0;
+ referenceClean = new ReferenceClean(objectPool);
+
+ /*
+ * setup signal handler for SIGPIPE
+ */
+ orig_sigpipe = signal(SIGPIPE,SIG_IGN);
+ if((orig_sigpipe != SIG_DFL) && (orig_sigpipe != SIG_IGN))
+ {
+ cerr << "mcop warning: user defined signal handler found for"
+ " SIG_PIPE, overriding" << endl;
+ }
+
+ StartupManager::startup();
+
+ /*
+ * this is required for publishing global references - might be a good
+ * reason for startup priorities as since this is required for cookie&co,
+ * no communication is possible without that
+ */
+
+
+ char *env = getenv("ARTS_SERVER");
+ bool envOk = false;
+ if(env)
+ {
+ string url = "tcp:"; url += env;
+ Connection *conn = connectUrl(url);
+ arts_debug("connection to %s for globalComm", url.c_str());
+ if(conn)
+ {
+ arts_debug("hint %s", conn->findHint("GlobalComm").c_str());
+ d->globalComm = Reference(conn->findHint("GlobalComm"));
+ envOk = true;
+ arts_debug("using globalcomm from env variable");
+ }
+ }
+
+ if(!envOk)
+ {
+ string globalCommName
+ = MCOPUtils::readConfigEntry("GlobalComm","Arts::TmpGlobalComm");
+ d->globalComm = GlobalComm(SubClass(globalCommName));
+ }
+
+ // --- initialize MD5auth ---
+ /*
+ * Path for random seed: better to store it in home, because some
+ * installations wipe /tmp on reboot.
+ */
+ string seedpath = MCOPUtils::createFilePath("random-seed");
+ string mcopdir = MCOPUtils::mcopDirectory();
+ if(!mcopdir.empty()) seedpath = mcopdir + "/random-seed";
+ arts_md5_auth_init_seed(seedpath.c_str());
+
+ /*
+ * first generate a new random cookie and try to set secret-cookie to it
+ * as put will not overwrite, this has no effect if there is already a
+ * secret cookie
+ */
+ char *cookie = arts_md5_auth_mkcookie();
+ globalComm().put("secret-cookie",cookie);
+
+ /*
+ * Then get the secret cookie from globalComm. As we've just set one,
+ * and as it is never removed, this always works.
+ */
+ string secretCookie = globalComm().get("secret-cookie");
+ if(!arts_md5_auth_set_cookie(secretCookie.c_str()))
+ {
+ /*
+ * Handle the case where the cookie obtained from GlobalComm is not
+ * a valid cookie (i.e. too short) - this should practically never
+ * happen. In this case, we will remove the cookie and overwrite it
+ * with our previously generated cookie.
+ */
+ arts_warning("bad md5 secret-cookie obtained from %s - replacing it",
+ globalComm()._interfaceName().c_str());
+
+ globalComm().erase("secret-cookie");
+ globalComm().put("secret-cookie",cookie);
+
+ if(!arts_md5_auth_set_cookie(cookie))
+ arts_fatal("error initializing md5 secret cookie "
+ "(generated cookie invalid)");
+ }
+ memset(cookie,0,strlen(cookie)); // try to keep memory clean
+ free(cookie);
+
+ string::iterator i; // try to keep memory clean from secret cookie
+ for(i=secretCookie.begin();i != secretCookie.end();i++) *i = 'y';
+
+ unlock();
+}
+
+Dispatcher::~Dispatcher()
+{
+ lock();
+
+ /* no interaction possible now anymore - remove our global references */
+ if(objectManager)
+ objectManager->removeGlobalReferences();
+
+ /* remove everything that might have been tagged for remote copying */
+ referenceClean->forceClean();
+ delete referenceClean;
+
+ d->globalComm = GlobalComm::null();
+
+ /* shutdown all extensions we loaded */
+ if(objectManager)
+ objectManager->shutdownExtensions();
+
+ StartupManager::shutdown();
+
+ /* drop all open connections */
+ list<Connection *>::iterator ci;
+ for(ci=connections.begin(); ci != connections.end();ci++)
+ {
+ Connection *conn = *ci;
+ conn->drop();
+ }
+ d->requestResultCondition.wakeAll();
+ d->serverConnectCondition.wakeAll();
+
+ /*
+ * remove signal handler for SIGPIPE
+ */
+ signal(SIGPIPE,orig_sigpipe);
+
+
+ d->interfaceRepo = InterfaceRepo::null();
+
+ if(d->accept)
+ {
+ delete d->accept;
+ d->accept = 0;
+ }
+
+ if(d->loopbackConnection)
+ {
+ d->loopbackConnection->_release();
+ d->loopbackConnection = 0;
+ }
+ if(unixServer)
+ {
+ delete unixServer;
+ unixServer = 0;
+ }
+
+ if(tcpServer)
+ {
+ delete tcpServer;
+ tcpServer = 0;
+ }
+
+ if(notificationManager)
+ {
+ delete notificationManager;
+ notificationManager = 0;
+ }
+
+ if(objectManager && Object_base::_objectCount() == 0)
+ {
+ objectManager->removeExtensions();
+ delete objectManager;
+ objectManager = 0;
+ }
+
+ if(d->wakeUpHandler)
+ {
+ delete d->wakeUpHandler;
+ d->wakeUpHandler = 0;
+ }
+
+ if(deleteIOManagerOnExit)
+ {
+ delete _ioManager;
+ _ioManager = 0;
+ }
+
+ if(Object_base::_objectCount())
+ {
+ cerr << "warning: leaving MCOP Dispatcher and still "
+ << Object_base::_objectCount() << " object references alive." << endl;
+ list<Object_skel *> which = objectPool.enumerate();
+ list<Object_skel *>::iterator i;
+ for(i = which.begin(); i != which.end();i++)
+ cerr << " - " << (*i)->_interfaceName() << endl;
+ }
+
+ if(Type::_typeCount())
+ {
+ cerr << "warning: leaving MCOP Dispatcher and still "
+ << Type::_typeCount() << " types alive." << endl;
+ }
+
+ if(GenericDataPacket::_dataPacketCount())
+ {
+ cerr << "warning: leaving MCOP Dispatcher and still "
+ << GenericDataPacket::_dataPacketCount()
+ << " data packets alive." << endl;
+ }
+
+ Debug::freeMutex();
+
+ unlock();
+
+ /* private data pointer */
+ assert(d);
+ delete d;
+ d = 0;
+
+ assert(_instance);
+ _instance = 0;
+}
+
+InterfaceRepo Dispatcher::interfaceRepo()
+{
+ return d->interfaceRepo;
+}
+
+FlowSystem_impl *Dispatcher::flowSystem()
+{
+ assert(_flowSystem);
+ return _flowSystem;
+}
+
+GlobalComm Dispatcher::globalComm()
+{
+ assert(!d->globalComm.isNull());
+ return d->globalComm;
+}
+
+void Dispatcher::setFlowSystem(FlowSystem_impl *fs)
+{
+ assert(!_flowSystem);
+ _flowSystem = fs;
+}
+
+Dispatcher *Dispatcher::the()
+{
+ return _instance;
+}
+
+Buffer *Dispatcher::waitForResult(long requestID, Connection *connection)
+{
+ bool isMainThread = SystemThreads::the()->isMainThread();
+ Buffer *b = requestResultPool[requestID];
+
+ connection->_copy(); // Keep extra ref
+
+ while(!b && !connection->broken()) {
+ if(isMainThread)
+ _ioManager->processOneEvent(true);
+ else
+ d->requestResultCondition.wait(d->mutex);
+
+ b = requestResultPool[requestID];
+ }
+
+ requestResultPool.releaseSlot(requestID);
+
+ if(connection->broken()) // connection went away before we got some result
+ b = 0;
+
+ connection->_release(); // Give up extra ref
+
+ return b;
+}
+
+Buffer *Dispatcher::createRequest(long& requestID, long objectID, long methodID)
+{
+ Buffer *buffer = new Buffer;
+
+ // write mcop header record
+ buffer->writeLong(MCOP_MAGIC);
+ buffer->writeLong(0); // message length - to be patched later
+ buffer->writeLong(mcopInvocation);
+
+ // generate a request ID
+ requestID = requestResultPool.allocSlot();
+
+ // write invocation record
+ buffer->writeLong(objectID);
+ buffer->writeLong(methodID);
+ buffer->writeLong(requestID);
+
+ return buffer;
+}
+
+Buffer *Dispatcher::createOnewayRequest(long objectID, long methodID)
+{
+ Buffer *buffer = new Buffer;
+
+ // write mcop header record
+ buffer->writeLong(MCOP_MAGIC);
+ buffer->writeLong(0); // message length - to be patched later
+ buffer->writeLong(mcopOnewayInvocation);
+
+ // write oneway invocation record
+ buffer->writeLong(objectID);
+ buffer->writeLong(methodID);
+
+ return buffer;
+}
+
+void Dispatcher::handle(Connection *conn, Buffer *buffer, long messageType)
+{
+ _activeConnection = conn;
+
+#ifdef DEBUG_IO
+ printf("got a message %ld, %ld bytes in body\n",
+ messageType,buffer->remaining());
+ if(conn->connState() == Connection::unknown)
+ cout << "connectionState = unknown" << endl;
+ if(conn->connState() == Connection::expectClientHello)
+ cout << "connectionState = expectClientHello" << endl;
+ if(conn->connState() == Connection::expectServerHello)
+ cout << "connectionState = expectServerHello" << endl;
+ if(conn->connState() == Connection::expectAuthAccept)
+ cout << "connectionState = expectAuthAccept" << endl;
+ if(conn->connState() == Connection::established)
+ cout << "connectionState = established" << endl;
+#endif
+ switch(conn->connState())
+ {
+ case Connection::established:
+ /*
+ * we're connected to a trusted server, so we can accept
+ * invocations
+ */
+ if(messageType == mcopInvocation) {
+#ifdef DEBUG_MESSAGES
+ printf("[got Invocation]\n");
+#endif
+ long objectID = buffer->readLong();
+ long methodID = buffer->readLong();
+ long requestID = buffer->readLong();
+
+ Buffer *result = new Buffer;
+ // write mcop header record
+ result->writeLong(MCOP_MAGIC);
+ result->writeLong(0); // message length - to be patched later
+ result->writeLong(mcopReturn);
+
+ // write result record (returnCode is written by dispatch)
+ result->writeLong(requestID);
+
+ // perform the request
+ Object_skel *object = objectPool[objectID];
+ object->_copy();
+ object->_dispatch(buffer,result,methodID);
+ object->_release();
+
+ assert(!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ if(d->delayedReturn)
+ {
+ delete result;
+
+ result = new Buffer;
+ result->writeLong(MCOP_MAGIC);
+ result->writeLong(0); // to be patched later
+ result->writeLong(mcopReturn);
+ result->writeLong(requestID);
+
+ d->delayedReturn->initialize(conn,result);
+ d->delayedReturn = 0;
+ }
+ else /* return normally */
+ {
+ result->patchLength();
+ conn->qSendBuffer(result);
+ }
+ return; /* everything ok - leave here */
+ }
+
+ if(messageType == mcopReturn)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got Return]\n");
+#endif
+ long requestID = buffer->readLong();
+ requestResultPool[requestID] = buffer;
+ d->requestResultCondition.wakeAll();
+
+ return; /* everything ok - leave here */
+ }
+
+ if(messageType == mcopOnewayInvocation) {
+#ifdef DEBUG_MESSAGES
+ printf("[got OnewayInvocation]\n");
+#endif
+ long objectID = buffer->readLong();
+ long methodID = buffer->readLong();
+
+ // perform the request
+ Object_skel *object = objectPool[objectID];
+ object->_copy();
+ object->_dispatch(buffer,methodID);
+ object->_release();
+
+ assert(!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ return; /* everything ok - leave here */
+ }
+ break;
+
+ case Connection::expectServerHello:
+ if(messageType == mcopServerHello)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got ServerHello]\n");
+#endif
+ /*
+ * if we get a server hello, answer with a client hello
+ */
+ ServerHello h;
+ h.readType(*buffer);
+ bool valid = (!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ if(!valid) break; // invalid hello received -> forget it
+
+ conn->setServerID(h.serverID);
+
+ /*
+ * check if md5auth or noauth is offered by the server
+ */
+ bool md5authSupported = false;
+ bool noauthSupported = false;
+ vector<string>::iterator ai;
+ for(ai = h.authProtocols.begin(); ai != h.authProtocols.end(); ai++)
+ {
+ if(*ai == "md5auth") md5authSupported = true;
+ if(*ai == "noauth") noauthSupported = true;
+ }
+
+ if(noauthSupported) // noauth is usually easier to pass ;)
+ {
+ Buffer *helloBuffer = new Buffer;
+
+ Header header(MCOP_MAGIC,0,mcopClientHello);
+ header.writeType(*helloBuffer);
+ ClientHello clientHello(serverID,"noauth","");
+ clientHello.writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+
+ conn->qSendBuffer(helloBuffer);
+ conn->setConnState(Connection::expectAuthAccept);
+ return; /* everything ok - leave here */
+ }
+ else if(md5authSupported)
+ {
+ Buffer *helloBuffer = new Buffer;
+
+ Header header(MCOP_MAGIC,0,mcopClientHello);
+ header.writeType(*helloBuffer);
+ ClientHello clientHello(serverID,"md5auth","");
+
+ const char *random_cookie = h.authSeed.c_str();
+ if(strlen(random_cookie) == 32)
+ {
+ char *response = arts_md5_auth_mangle(random_cookie);
+ clientHello.authData = response;
+#ifdef DEBUG_AUTH
+ printf(" got random_cookie = %s\n",random_cookie);
+ printf("reply with authData = %s\n",response);
+#endif
+ free(response);
+ }
+ clientHello.writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+
+ conn->qSendBuffer(helloBuffer);
+ conn->setConnState(Connection::expectAuthAccept);
+ return; /* everything ok - leave here */
+ }
+ else
+ {
+ cerr << "MCOP error: don't know authentication protocol" << endl;
+ cerr << " server offered: ";
+ for(ai = h.authProtocols.begin(); ai != h.authProtocols.end(); ai++)
+ cerr << *ai << " ";
+ cerr << endl;
+ }
+ }
+ break;
+
+ case Connection::expectClientHello:
+ if(messageType == mcopClientHello)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got ClientHello]\n");
+#endif
+ ClientHello c;
+ c.readType(*buffer);
+ bool valid = (!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ if(valid && (
+ (c.authProtocol == "md5auth" && c.authData == conn->cookie())
+ || (c.authProtocol == "noauth" && d->allowNoAuthentication) ))
+ {
+ conn->setServerID(c.serverID);
+
+ /* build hints only for the first connection */
+ if(!d->accept)
+ {
+ d->accept = new AuthAccept();
+
+ d->accept->hints.push_back(
+ "GlobalComm="+d->globalComm.toString());
+ d->accept->hints.push_back(
+ "InterfaceRepo="+d->interfaceRepo.toString());
+ }
+
+ Buffer *helloBuffer = new Buffer;
+ Header header(MCOP_MAGIC,0,mcopAuthAccept);
+ header.writeType(*helloBuffer);
+ d->accept->writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+ conn->qSendBuffer(helloBuffer);
+ conn->setConnState(Connection::established);
+
+ return; /* everything ok - leave here */
+ }
+ }
+ break;
+
+ case Connection::expectAuthAccept:
+ if(messageType == mcopAuthAccept)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got AuthAccept]\n");
+#endif
+ AuthAccept a;
+ a.readType(*buffer);
+ delete buffer;
+#ifdef DEBUG_MESSAGES
+
+ vector<string>::iterator hi;
+ for(hi = a.hints.begin(); hi != a.hints.end(); hi++)
+ cout << "[got ConnectionHint] " << *hi << endl;
+
+#endif
+
+ conn->setConnState(Connection::established);
+ conn->setHints(a.hints);
+ d->serverConnectCondition.wakeAll();
+ return; /* everything ok - leave here */
+ }
+ break;
+
+ case Connection::unknown:
+ assert(false);
+ break;
+ }
+
+ /*
+ * We shouldn't reach this point if everything went all right
+ */
+ cerr << "Fatal communication error with a client" << endl;
+ if(conn->connState() != Connection::established)
+ {
+ cerr << " Authentication of this client was not successful" << endl;
+ cerr << " Connection dropped" << endl;
+ conn->drop();
+ }
+}
+
+long Dispatcher::addObject(Object_skel *object)
+{
+ long objectID = objectPool.allocSlot();
+
+ objectPool[objectID] = object;
+ return objectID;
+}
+
+void Dispatcher::removeObject(long objectID)
+{
+ assert(objectPool[objectID]);
+ objectPool.releaseSlot(objectID);
+}
+
+void Dispatcher::generateServerID()
+{
+ char *buffer;
+ buffer = arts_strdup_printf("%s-%04x-%08lx",
+ MCOPUtils::getFullHostname().c_str(),
+ getpid(),time(0));
+ serverID = buffer;
+ free(buffer);
+}
+
+string Dispatcher::objectToString(long objectID)
+{
+ Buffer b;
+ ObjectReference oref;
+
+ oref.serverID = serverID;
+ oref.objectID = objectID;
+
+ // prefer a unix domainsocket connection over a plain tcp connection
+ if(unixServer) oref.urls.push_back(unixServer->url());
+ if(tcpServer) oref.urls.push_back(tcpServer->url());
+
+ oref.writeType(b);
+
+ return b.toString("MCOP-Object");
+}
+
+bool Dispatcher::stringToObjectReference(ObjectReference& r, const string& s)
+{
+ if(strncmp(s.c_str(),"global:",7) == 0)
+ {
+ // if the object reference starts with "global:", it refers to
+ // a global object which can be found with the objectManager
+
+ string lookup = objectManager->getGlobalReference(&s.c_str()[7]);
+ return stringToObjectReference(r,lookup);
+ }
+
+
+ Buffer b;
+ if(!b.fromString(s,"MCOP-Object")) return false;
+
+ r.readType(b);
+ if(b.readError() || b.remaining()) return false;
+
+ return true;
+}
+
+void *Dispatcher::connectObjectLocal(ObjectReference& reference,
+ const string& interface)
+{
+ if(reference.serverID == serverID)
+ {
+ void *result = objectPool[reference.objectID]->_cast(interface);
+
+ if(result)
+ {
+ objectPool[reference.objectID]->_copy();
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+Connection *Dispatcher::connectObjectRemote(ObjectReference& reference)
+{
+ if(reference.serverID == "null") // null reference?
+ return 0;
+
+ if(reference.serverID == serverID)
+ return loopbackConnection();
+
+ list<Connection *>::iterator i;
+
+ for(i=connections.begin(); i != connections.end();i++)
+ {
+ Connection *conn = *i;
+
+ if(conn->isConnected(reference.serverID))
+ {
+ // fixme: we should check for the existence of the object
+ // and increment a reference count or something like that
+ return conn;
+ }
+ }
+
+ /* try to connect the server */
+ vector<string>::iterator ui;
+ for(ui = reference.urls.begin(); ui != reference.urls.end(); ui++)
+ {
+ Connection *conn = connectUrl(*ui);
+ if(conn)
+ {
+ if(conn->isConnected(reference.serverID))
+ {
+ return conn;
+ }
+ else
+ {
+ /* we connected somewhere, but not the right server ;) */
+ connections.remove(conn);
+ conn->_release();
+ }
+ }
+ }
+ return 0;
+}
+
+Connection *Dispatcher::connectUrl(const string& url)
+{
+ Connection *conn = 0;
+ bool isMainThread = SystemThreads::the()->isMainThread();
+
+ if(strncmp(url.c_str(),"tcp:",4) == 0)
+ {
+ conn = new TCPConnection(url);
+ }
+ else if(strncmp(url.c_str(),"unix:",5) == 0)
+ {
+ conn = new UnixConnection(url);
+ }
+
+ if(conn)
+ {
+ conn->_copy(); // Keep extra ref for when the connection breaks
+ conn->setConnState(Connection::expectServerHello);
+
+ while((conn->connState() != Connection::established)
+ && !conn->broken())
+ {
+ if(isMainThread)
+ _ioManager->processOneEvent(true);
+ else
+ d->serverConnectCondition.wait(d->mutex);
+ }
+
+ if(conn->connState() == Connection::established)
+ {
+ connections.push_back(conn);
+ conn->_release(); // Give up extra ref
+ return conn;
+ }
+
+ // well - bad luck (building a connection failed)
+
+ // Give up extra ref
+ conn->_release();
+ }
+ return 0;
+}
+
+void Dispatcher::run()
+{
+ assert(SystemThreads::the()->isMainThread());
+
+ _ioManager->run();
+}
+
+void Dispatcher::terminate()
+{
+ _ioManager->terminate();
+}
+
+void Dispatcher::initiateConnection(Connection *connection)
+{
+ vector<string> authProtocols;
+ authProtocols.push_back("md5auth");
+
+ if(d->allowNoAuthentication)
+ authProtocols.push_back("noauth");
+
+ char *authSeed = arts_md5_auth_mkcookie();
+ char *authResult = arts_md5_auth_mangle(authSeed);
+
+ Buffer *helloBuffer = new Buffer;
+
+ Header header(MCOP_MAGIC,0,mcopServerHello);
+ header.writeType(*helloBuffer);
+ ServerHello serverHello("aRts/MCOP-1.0.0",serverID,authProtocols,authSeed);
+ serverHello.writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+
+ connection->qSendBuffer(helloBuffer);
+ connection->setConnState(Connection::expectClientHello);
+
+ connection->setCookie(authResult);
+ free(authSeed);
+ free(authResult);
+
+ connections.push_back(connection);
+}
+
+void Dispatcher::handleCorrupt(Connection *connection)
+{
+ if(connection->connState() != Connection::established)
+ {
+ cerr << "received corrupt message on unauthenticated connection" <<endl;
+ cerr << "closing connection." << endl;
+ connection->drop();
+ d->serverConnectCondition.wakeAll();
+ }
+ else
+ {
+ cerr << "WARNING: got corrupt MCOP message !??" << endl;
+ }
+}
+
+void Dispatcher::handleConnectionClose(Connection *connection)
+{
+ /*
+ * we can't use enumerate here, because the "existing objects list" might
+ * be changing due to the other _disconnectRemote calls we make, so we
+ * enumerate() the objects manually
+ */
+ unsigned long l;
+ for(l=0; l<objectPool.max(); l++)
+ {
+ Object_skel *skel = objectPool[l];
+ if(skel) skel->_disconnectRemote(connection);
+ }
+
+ d->requestResultCondition.wakeAll();
+ d->serverConnectCondition.wakeAll();
+
+ /*
+ * FIXME:
+ *
+ * there may be error handling to do (e.g., check that the _stub's that
+ * still refer to that connection don't crash now).
+ */
+ connection->_release();
+
+ list<Connection *>::iterator i;
+ for(i=connections.begin(); i != connections.end();i++)
+ {
+ if(*i == connection)
+ {
+ connections.erase(i);
+ return;
+ }
+ }
+}
+
+Connection *Dispatcher::activeConnection()
+{
+ return _activeConnection;
+}
+
+Connection *Dispatcher::loopbackConnection()
+{
+ return d->loopbackConnection;
+}
+
+DelayedReturn *Dispatcher::delayReturn()
+{
+ assert(!d->delayedReturn);
+
+ return d->delayedReturn = new DelayedReturn();
+}
+
+Object_skel *Dispatcher::getLocalObject(long objectID)
+{
+ Object_skel *result = objectPool[objectID];
+
+ if(result) result->_copy();
+ return result;
+}
+
+void Dispatcher::lock()
+{
+ _instance->d->mutex.lock();
+}
+
+void Dispatcher::unlock()
+{
+ _instance->d->mutex.unlock();
+}
+
+void Dispatcher::wakeUp()
+{
+ if(SystemThreads::the()->isMainThread()) return;
+
+ _instance->d->wakeUpHandler->wakeUp();
+}
+
+/*
+void Dispatcher::reloadTraderData() is declared in trader_impl.cc
+*/
diff --git a/mcop/dispatcher.h b/mcop/dispatcher.h
new file mode 100644
index 0000000..b143a1e
--- /dev/null
+++ b/mcop/dispatcher.h
@@ -0,0 +1,265 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef DISPATCHER_H
+#define DISPATCHER_H
+
+#include "common.h"
+#include "pool.h"
+#include "iomanager.h"
+#include "tcpserver.h"
+#include "unixserver.h"
+#include "connection.h"
+#include "notification.h"
+
+#include <deque>
+#include <stack>
+#include <vector>
+#include <list>
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Dispatcher
+ *
+ * This is part of the public API (and interacts with generated code) and
+ * has to be kept binary compatible.
+ */
+
+namespace Arts {
+
+class ObjectReference;
+class FlowSystem_impl;
+class GlobalComm;
+class InterfaceRepo;
+class ObjectManager;
+class Object_skel;
+class ReferenceClean;
+class DelayedReturn;
+
+extern "C" {
+ typedef void (*mcop_sighandler)(int);
+}
+
+class ARTS_EXPORT Dispatcher {
+private:
+ class DispatcherPrivate *d;
+
+protected:
+ static Dispatcher *_instance;
+
+ Pool<Buffer> requestResultPool;
+ Pool<Object_skel> objectPool;
+ std::list<Connection *> connections;
+
+ std::string serverID;
+ void generateServerID(); // helper function
+
+ bool deleteIOManagerOnExit;
+
+ TCPServer *tcpServer;
+ UnixServer *unixServer;
+ IOManager *_ioManager;
+ FlowSystem_impl *_flowSystem;
+ ObjectManager *objectManager;
+ ReferenceClean *referenceClean;
+ NotificationManager *notificationManager;
+
+ mcop_sighandler orig_sigpipe; // original signal handler for SIG_PIPE
+ Connection *_activeConnection; // internal use only (for refcounting)
+
+ /**
+ * connects to a given URL
+ *
+ * @returns a valid connection, or a 0 pointer on error
+ */
+ Connection *connectUrl(const std::string& url);
+
+public:
+ enum StartServer {
+ noServer = 0, // don't be a server
+ startUnixServer = 1, // listen on a unix domain socket
+ startTCPServer = 2, // listen on a tcp port
+ noAuthentication = 4 // don't require authentication
+ };
+
+ Dispatcher(IOManager *ioManager = 0, StartServer startServer = noServer);
+ ~Dispatcher();
+
+ static Dispatcher *the();
+ inline IOManager *ioManager() { return _ioManager; };
+ InterfaceRepo interfaceRepo();
+ FlowSystem_impl *flowSystem();
+ GlobalComm globalComm();
+ void setFlowSystem(FlowSystem_impl *fs);
+
+ void refillRequestIDs();
+
+ // blocking wait for result
+ Buffer *waitForResult(long requestID,Connection *connection);
+
+ // request creation for oneway and twoway requests
+ Buffer *createRequest(long& requestID, long objectID, long methodID);
+ Buffer *createOnewayRequest(long objectID, long methodID);
+
+ // processes messages
+ void handle(Connection *conn, Buffer *buffer, long messageType);
+
+ /*
+ * special hook to handle corrupt messages
+ */
+ void handleCorrupt(Connection *conn);
+
+ /**
+ * object registration
+ *
+ * do not call manually, this is used by the Object_skel constructor
+ * to register itself
+ */
+ long addObject(Object_skel *object);
+
+ /**
+ * object deregistration
+ *
+ * do not call manually, this is called by the Object_skel destructor
+ * as soon as the object is deleted
+ */
+ void removeObject(long objectID);
+
+ /**
+ * connects to a local object, returning a readily casted "interface" *
+ * if success, or NULL if this object is not local
+ */
+ void *connectObjectLocal(ObjectReference& reference, const std::string& interface);
+
+ /**
+ * connects to a remote object, establishing a connection if necessary
+ *
+ * returns NULL if connecting fails or object isn't present or whatever
+ * else could go wrong
+ */
+ Connection *connectObjectRemote(ObjectReference& reference);
+
+ /**
+ * stringification of objects (only used by the object implementations,
+ * which in turn provide a _toString method)
+ */
+ std::string objectToString(long objectID);
+
+ /**
+ * destringification of objects (mainly used by the object implementations,
+ * which in turn provide a _fromString method)
+ */
+ bool stringToObjectReference(ObjectReference& r, const std::string& s);
+
+ /**
+ * main loop
+ */
+ void run();
+
+ /**
+ * this function quits the main loop (it must be running, of course)
+ * and causes the run() function to return.
+ */
+ void terminate();
+
+ /**
+ * Is called by the transport services as soon as a new connection is
+ * created - this will send authentication request, etc.
+ */
+ void initiateConnection(Connection *connection);
+
+ /**
+ * Is called by the Connection as soon as the connection goes down,
+ * which may happen due to a normal cause (client exits), and may
+ * happen if an error occurs as well (network down)
+ */
+ void handleConnectionClose(Connection *connection);
+
+ /**
+ * Locks the dispatcher. Whenever you want to do anything with any kind
+ * of aRts object, you will hold a lock on Arts::Dispatcher. There is
+ * only one exception to the rule, and that is: you don't have to lock
+ * the dispatcher when the lock is already held.
+ *
+ * Generally, that is very often the case. Typical situations where you
+ * don't need to lock() the Dispatcher are:
+ *
+ * @li you receive a callback from the IOManager (timer or fd)
+ * @li you get call due to some MCOP request
+ * @li you are called from the NotificationManager
+ * @li you are called from the FlowSystem (calculateBlock)
+ */
+ static void lock();
+
+ /**
+ * Unlocks the dispatcher. Do this to release a lock you hold on
+ * the Arts::Dispatcher.
+ */
+ static void unlock();
+
+ /**
+ * Wakes the dispatcher - normally, the dispatcher will go to sleep in
+ * it's event loop, when nothing is to be done. If you change things from
+ * another thread, like: add a new Timer, write something to a connection,
+ * and so on, the dispatcher will not notice it. To wake the dispatcher
+ * up, this call is provided.
+ */
+ static void wakeUp();
+
+ /**
+ * - internal usage only -
+ *
+ * this will return the Connection the last request came from
+ */
+ Connection *activeConnection();
+
+ /**
+ * - internal usage only -
+ *
+ * this will return a loopback Connection for sending requests to myself
+ */
+ Connection *loopbackConnection();
+
+ /**
+ * - internal usage only -
+ *
+ * this will cause a function to return from a request later
+ * @see DelayedReturn
+ */
+ DelayedReturn *delayReturn();
+
+ /**
+ * - internal usage only -
+ *
+ * gets object with a given ID
+ * @returns the object if successful, 0 otherwise
+ */
+ Object_skel *getLocalObject(long ID);
+
+ /**
+ * reloads the trader data (do this if things have been added/changed
+ * there)
+ */
+ void reloadTraderData();
+};
+}
+#endif
diff --git a/mcop/dynamicrequest.cc b/mcop/dynamicrequest.cc
new file mode 100644
index 0000000..6ba64f7
--- /dev/null
+++ b/mcop/dynamicrequest.cc
@@ -0,0 +1,152 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "dynamicrequest.h"
+#include "common.h"
+#include "debug.h"
+#include <iostream>
+
+using namespace Arts;
+using namespace std;
+
+class Arts::DynamicRequestPrivate {
+public:
+ Connection *connection;
+ Buffer *buffer;
+ MethodDef method;
+ Object object;
+
+ /**
+ * methodID is kept between the requests, so that we don't need to lookup
+ * a method again when it gets called twice - the value for "we need to
+ * lookup again" is -1, which gets set whenever the current request differs
+ * from the last
+ */
+ long requestID, methodID, objectID;
+ unsigned long paramCount;
+
+ /**
+ * constructor
+ */
+ DynamicRequestPrivate(const Object &obj)
+ : buffer(0), object(obj), methodID(-1)
+ {
+ }
+};
+
+DynamicRequest::DynamicRequest(const Object& obj)
+{
+ d = new DynamicRequestPrivate(obj);
+ d->connection = obj._base()->_connection;
+ d->objectID = obj._base()->_objectID;
+}
+
+DynamicRequest::~DynamicRequest()
+{
+ delete d;
+}
+
+DynamicRequest& DynamicRequest::method(const string& method)
+{
+ assert(!d->buffer);
+
+ // methodID will be set later
+ d->buffer = Dispatcher::the()->createRequest(d->requestID, d->objectID, 0);
+
+ if(d->method.name != method)
+ {
+ d->method.name = method;
+ d->methodID = -1;
+ }
+ d->paramCount = 0;
+ return *this;
+}
+
+DynamicRequest& DynamicRequest::param(const AnyConstRef& ref)
+{
+ if(d->paramCount == d->method.signature.size())
+ {
+ ParamDef pd;
+ pd.type = ref.type();
+ d->method.signature.push_back(pd);
+ }
+ else
+ {
+ if(d->method.signature[d->paramCount].type != ref.type())
+ {
+ d->method.signature[d->paramCount].type = ref.type();
+ d->methodID = -1;
+ }
+ }
+ d->paramCount++;
+ ref.write(d->buffer);
+ return *this;
+}
+
+bool DynamicRequest::invoke()
+{
+ AnyRef voidReference;
+ return invoke(voidReference);
+}
+
+bool DynamicRequest::invoke(const AnyRef& returnCode)
+{
+ if(d->method.type != returnCode.type())
+ {
+ d->method.type = returnCode.type();
+ d->methodID = -1;
+ }
+ if(d->method.signature.size() != d->paramCount)
+ d->methodID = -1;
+
+ /*
+ * need to lookup method? (if the requested method is exactly the
+ * same as the last, we need not, which signigicantly improves performance
+ */
+ if(d->methodID == -1)
+ {
+ d->method.signature.resize(d->paramCount);
+ d->methodID = d->object._lookupMethod(d->method);
+
+ if(d->methodID == -1)
+ {
+ arts_warning("DynamicRequest: invalid method called");
+ return false;
+ }
+ }
+
+
+ d->buffer->patchLength();
+ d->buffer->patchLong(16,d->methodID);
+ d->connection->qSendBuffer(d->buffer);
+ d->buffer = 0;
+
+ Buffer *result =
+ Dispatcher::the()->waitForResult(d->requestID,d->connection);
+
+ if(result)
+ {
+ returnCode.read(result);
+ delete result;
+ }
+ return result != 0;
+}
diff --git a/mcop/dynamicrequest.h b/mcop/dynamicrequest.h
new file mode 100644
index 0000000..f749637
--- /dev/null
+++ b/mcop/dynamicrequest.h
@@ -0,0 +1,133 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef MCOP_DYNAMICREQUEST_H
+#define MCOP_DYNAMICREQUEST_H
+
+#include "buffer.h"
+#include "anyref.h"
+#include <vector>
+#include <string>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): DynamicRequest
+ *
+ * Has to be kept binary compatible (use d ptr).
+ */
+
+namespace Arts {
+
+class Object;
+class Type;
+class DynamicRequestPrivate;
+
+/**
+ * The DynamicRequest class can be used to invoke requests on objects, without
+ * using IDL generated code to do so (i.e. you can talk to objects without
+ * having to know their interfaces at compile time)
+ *
+ * Suppose you have the interface
+ *
+ * interface SimpleSoundServer {
+ * [...]
+ * long play(string file); // plays a file and returns an id
+ * [...]
+ * };
+ *
+ * And server is of type SimpleSoundServer, you can write in your C++ code:
+ *
+ * long id;
+ * if(DynamicRequest(server).method("play").param("/tmp/bong.wav").invoke(id))
+ * {
+ * cout << "playing file now, id is " << id << endl;
+ * }
+ * else
+ * {
+ * cout << "something went wrong with the dynamic request" << endl;
+ * }
+ *
+ * You can of course also add parameters and other information one-by-one:
+ *
+ * DynamicRequest request(server);
+ * request.method("play");
+ * request.param("/tmp/bong.wav");
+ *
+ * long id;
+ * if(request.invoke(id)) cout << "success" << endl;
+ */
+
+class ARTS_EXPORT DynamicRequest {
+public:
+ /**
+ * creates a dynamic request which will be sent to a specific object
+ */
+ DynamicRequest(const Object& object);
+
+ /**
+ * deletes the dynamic request
+ */
+ ~DynamicRequest();
+
+ /**
+ * says that the following method will be a oneway method, for example
+ *
+ * DynamicRequest(someobject).oneway().method("stop").invoke();
+ */
+ DynamicRequest& oneway();
+
+ /**
+ * sets the method to invoke
+ */
+ DynamicRequest& method(const std::string& method);
+
+ /**
+ * adds a parameter to the call
+ */
+ DynamicRequest& param(const AnyConstRef& value);
+
+ /**
+ * executes the request, call this if you don't expect a return type
+ *
+ * @returns true if the request could be performed
+ */
+ bool invoke();
+
+ /**
+ * executes the request: this version accepts an AnyRef& as result type
+ *
+ * @returns true if the request could be performed
+ */
+ bool invoke(const AnyRef& result);
+
+ /*
+ * TODO: Some types can't yet be used in dynamic requests, these are
+ * enum, sequence<enum>, type, sequence<type>, object, sequence<object>
+ */
+private:
+ DynamicRequestPrivate *d;
+};
+
+}
+
+#endif /* MCOP_DYNAMICREQUEST_H */
diff --git a/mcop/dynamicskeleton.cc b/mcop/dynamicskeleton.cc
new file mode 100644
index 0000000..99d6dd1
--- /dev/null
+++ b/mcop/dynamicskeleton.cc
@@ -0,0 +1,204 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "dynamicskeleton.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include "stdio.h"
+
+using namespace Arts;
+using namespace std;
+
+/* we could share the "class part" of those implicitely, as
+ types never change */
+
+namespace Arts {
+class DynamicSkeletonData {
+public:
+ DynamicSkeletonData(DynamicSkeletonBase *base,
+ Object_skel *skel,
+ const string& interfaceName,
+ const string& interfaceNameParent)
+ : base(base), skel(skel), interfaceName(interfaceName),
+ interfaceNameParent(interfaceNameParent)
+ {
+ }
+
+ enum InterfaceType { itNone, itParent, itDynamic };
+
+ void buildInterfaces();
+ void buildInterfaces(const string& s, InterfaceType t);
+ void buildMethodTable();
+
+ DynamicSkeletonBase *base;
+ Object_skel *skel;
+ string interfaceName, interfaceNameParent;
+ map<string, InterfaceType> interfaceMap;
+ map<string, void**> attrs;
+};
+}
+
+DynamicSkeletonBase::DynamicSkeletonBase(Object_skel *skel,
+ const std::string& interfaceName, const std::string& interfaceNameParent)
+{
+ arts_assert(skel != 0);
+ _dsInit(skel,interfaceName,interfaceNameParent);
+}
+
+DynamicSkeletonBase::DynamicSkeletonBase()
+{
+}
+
+void DynamicSkeletonBase::_dsInit(Object_skel *skel,
+ const std::string& interfaceName, const std::string& interfaceNameParent)
+{
+ d = new DynamicSkeletonData(this,skel,interfaceName,interfaceNameParent);
+ d->buildInterfaces();
+
+ /* TODO: optimize me! */
+ map<string, DynamicSkeletonData::InterfaceType>::iterator ii;
+ for(ii = d->interfaceMap.begin(); ii != d->interfaceMap.end(); ii++)
+ {
+ if(ii->second == DynamicSkeletonData::itDynamic)
+ {
+ InterfaceDef id;
+ id = Dispatcher::the()->interfaceRepo().queryInterface(ii->first);
+
+ vector<AttributeDef>::iterator ai;
+ for(ai = id.attributes.begin(); ai != id.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+ if((ad.flags & attributeStream) == attributeStream)
+ {
+ void**& data = d->attrs[ad.name.c_str()];
+ arts_assert(data == 0);
+ data = new (void*);
+ d->skel->_initStream(ad.name.c_str(),data,ad.flags);
+ }
+ }
+ }
+ }
+}
+
+DynamicSkeletonBase::~DynamicSkeletonBase()
+{
+ delete d;
+}
+
+std::string DynamicSkeletonBase::_dsInterfaceName()
+{
+ return d->interfaceName;
+}
+
+bool DynamicSkeletonBase::_dsIsCompatibleWith(const std::string& interfacename)
+{
+ d->buildInterfaces();
+ return d->interfaceMap[interfacename] != 0;
+}
+
+void DynamicSkeletonBase::_dsBuildMethodTable()
+{
+ d->buildMethodTable();
+}
+
+static void _dispatch_dynamic(void *object, long methodID, Buffer *request, Buffer *result)
+{
+ ((DynamicSkeletonBase *)object)->process(methodID, request, result);
+}
+
+void DynamicSkeletonData::buildMethodTable()
+{
+ buildInterfaces();
+
+ map<string, DynamicSkeletonData::InterfaceType>::iterator ii;
+ for(ii = interfaceMap.begin(); ii != interfaceMap.end(); ii++)
+ {
+ if(ii->second == itDynamic)
+ {
+ InterfaceDef id;
+ id = Dispatcher::the()->interfaceRepo().queryInterface(ii->first);
+
+ /* methods */
+ vector<MethodDef>::iterator mi;
+ for(mi = id.methods.begin(); mi != id.methods.end(); mi++)
+ skel->_addMethod(_dispatch_dynamic, base, *mi);
+
+ /* _get_ and _set_ methods for attributes */
+ vector<AttributeDef>::iterator ai;
+ for(ai = id.attributes.begin();ai != id.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if(ad.flags & attributeAttribute)
+ {
+ MethodDef md;
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ md.name = "_get_"+ad.name;
+ md.type = ad.type;
+ md.flags = methodTwoway;
+ /* no parameters (don't set md.signature) */
+
+ skel->_addMethod(_dispatch_dynamic, base, md);
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ md.name = "_set_"+ad.name;
+ md.type = "void";
+ md.flags = methodTwoway;
+
+ ParamDef pd;
+ pd.type = ad.type;
+ pd.name = "newValue";
+ md.signature.push_back(pd);
+
+ skel->_addMethod(_dispatch_dynamic, base, md);
+ }
+ }
+ }
+ }
+ }
+}
+
+void DynamicSkeletonData::buildInterfaces()
+{
+ if(interfaceMap.size() != 0) return;
+
+ buildInterfaces(interfaceName, itDynamic);
+ buildInterfaces(interfaceNameParent, itParent);
+}
+
+void DynamicSkeletonData::buildInterfaces(const string& name, DynamicSkeletonData::InterfaceType t)
+{
+ InterfaceDef id = Dispatcher::the()->interfaceRepo().queryInterface(name);
+
+ if(interfaceMap[name] == t) return;
+ interfaceMap[name] = t;
+
+ vector<string>::iterator ii;
+ for(ii = id.inheritedInterfaces.begin();
+ ii != id.inheritedInterfaces.end(); ii++)
+ {
+ buildInterfaces(*ii,t);
+ }
+ buildInterfaces("Arts::Object",t);
+}
diff --git a/mcop/dynamicskeleton.h b/mcop/dynamicskeleton.h
new file mode 100644
index 0000000..0c5cba7
--- /dev/null
+++ b/mcop/dynamicskeleton.h
@@ -0,0 +1,163 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_MCOP_DYNAMICSKELETON_H
+#define ARTS_MCOP_DYNAMICSKELETON_H
+
+#include "arts_export.h"
+
+#include "object.h"
+
+/*
+ * BC - Status (2002-03-08): DynamicSkeletonBase, DynamicSkeleton
+ *
+ * Will be kept binary compatible (using d ptr).
+ */
+namespace Arts {
+
+class DynamicSkeletonData;
+
+class ARTS_EXPORT DynamicSkeletonBase {
+private:
+ DynamicSkeletonData *d;
+
+protected:
+ DynamicSkeletonBase();
+ /* <obsolete compatibility code> */
+ DynamicSkeletonBase(Object_skel *skel,
+ const std::string& interfacename,
+ const std::string& interfacenameparent);
+ /* </obsolete compatibility code> */
+ virtual ~DynamicSkeletonBase();
+
+ void _dsInit(Object_skel *skel, const std::string& interfacename,
+ const std::string& interfacenameparent);
+ std::string _dsInterfaceName();
+ bool _dsIsCompatibleWith(const std::string& interfacename);
+ void _dsBuildMethodTable();
+
+public:
+ /**
+ * process is called whenever you get a request that you need to implement
+ * dynamically
+ *
+ * @param methodID contains the ID of the method that you need to
+ * implement - you can get the full signature by calling
+ * getMethodDef
+ *
+ * @param request contains the marshalled parameters
+ *
+ * @param result is for the return code - if your method returns a
+ * value, you need to write the it in the result Buffer
+ */
+ virtual void process(long methodID, Buffer *request, Buffer *result) = 0;
+};
+
+/**
+ * DynamicSkeleton is used to dynamically implement an interface (i.e. without
+ * static type bindings as generated by the MCOP idl compiler.
+ *
+ * You will always implement a mixed version: mcopidl generated skeletons up
+ * to a certain point, and above this, dynamically implemented interfaces.
+ * So you'll inherit DynamicSkeleton<Static_skel> and give the interface you
+ * want to implement dynamically as argument. Suppose your idl file looks
+ * like
+ *
+ * <pre>
+ * interface A { void a(); };
+ * interface B : A { void b(); };
+ * </pre>
+ *
+ * And you want to implement interface A "classic" (i.e. with mcopidl generated
+ * virtual void a()) and interface B "dynamic", you would do
+ *
+ * <pre>
+ * typedef Arts::DynamicSkeleton<A_skel> A_dskel; // convenient with typedef
+ *
+ * class B_impl : public A_dskel {
+ * public:
+ * B_impl() : A_dskel("B") { // we dynamically implement the B interface
+ * }
+ * void a() { // through A_skel
+ * arts_info("a called");
+ * }
+ * void process(long methodID, Arts::Buffer *request, Arts::Buffer *result)
+ * {
+ * const Arts::MethodDef& methodDef = getMethodDef(methodID);
+ *
+ * if(methodDef.name == "b")
+ * arts_info("b called!");
+ * else
+ * arts_fatal("Unknown method '%s' called");
+ * }
+ * };
+ * </pre>
+ */
+template<class Parent_skel>
+class DynamicSkeleton : virtual public Parent_skel, public DynamicSkeletonBase
+{
+public:
+ /**
+ * constructor
+ */
+ DynamicSkeleton(const std::string& interface)
+ {
+ _dsInit(this, interface, Parent_skel::_interfaceNameSkel());
+ }
+
+ /**
+ * getMethodDef returns a MethodDef structure for a given methodID - it
+ * is quite useful if you implement process
+ *
+ * <pre>
+ * void process(long methodID, Arts::Buffer *request, Arts::Buffer *result)
+ * {
+ * const Arts::MethodDef& methodDef = getMethodDef(methodID);
+ *
+ * if(methodDef.name == "hello") // the method named hello was called
+ * printf("Hello!\n");
+ * else // method with other name was called
+ * arts_fatal("Method '%s' not implemented",methodDef.name.c_str());
+ * }
+ * </pre>
+ */
+ const MethodDef& getMethodDef(long methodID) {
+ return this->_dsGetMethodDef(methodID);
+ }
+
+/*-- reimplemented from Arts::Object_skel: --*/
+ std::string _interfaceName() {
+ return _dsInterfaceName();
+ }
+
+ bool _isCompatibleWith(const std::string& interfacename) {
+ if(_dsIsCompatibleWith(interfacename)) return true;
+ return Parent_skel::_isCompatibleWith(interfacename);
+ }
+ void _buildMethodTable() {
+ Parent_skel::_buildMethodTable();
+ _dsBuildMethodTable();
+ }
+};
+
+}
+#endif /* ARTS_MCOP_DYNAMICSKELETON_H */
diff --git a/mcop/extensionloader.cc b/mcop/extensionloader.cc
new file mode 100644
index 0000000..82c56c5
--- /dev/null
+++ b/mcop/extensionloader.cc
@@ -0,0 +1,116 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "extensionloader.h"
+#include "startupmanager.h"
+#include "mcoputils.h"
+#include "debug.h"
+#include <unistd.h>
+#include <assert.h>
+
+using namespace std;
+using namespace Arts;
+
+ExtensionLoader::ExtensionLoader(const string& filename) :handle(0)
+{
+ string dlfilename;
+
+ assert(filename.size());
+ if(filename[0] == '/')
+ dlfilename = filename;
+ else
+ {
+ const vector<string> *path = MCOPUtils::extensionPath();
+
+ vector<string>::const_iterator pi;
+ for(pi = path->begin(); pi != path->end(); pi++)
+ {
+ dlfilename = *pi + "/" + filename;
+
+ if(access(dlfilename.c_str(),F_OK) == 0)
+ break;
+ }
+ }
+
+
+ /* this will catch all startup classes here */
+ StartupManager::setExtensionLoader(this);
+
+ lt_dlinit();
+ handle = lt_dlopen(dlfilename.c_str());
+
+ StartupManager::setExtensionLoader(0);
+
+ if(handle)
+ {
+ /* now process all startup classes of the loaded extension */
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses.begin(); i != startupClasses.end(); i++)
+ (*i)->startup();
+ needShutdown = true;
+ }
+ else
+ {
+ arts_warning("loading extension from '%s' failed: %s",
+ dlfilename.c_str(), lt_dlerror());
+ }
+}
+
+bool ExtensionLoader::success()
+{
+ return (handle != 0);
+}
+
+void ExtensionLoader::shutdown()
+{
+ if(handle && needShutdown)
+ {
+ /* shutdown the loaded extension properly */
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses.begin(); i != startupClasses.end(); i++)
+ (*i)->shutdown();
+ needShutdown = false;
+ }
+}
+
+ExtensionLoader::~ExtensionLoader()
+{
+ if(handle)
+ {
+ shutdown();
+ lt_dlclose(handle);
+
+ /*
+ * lt_dlexit & lt_dlinit have a counter, so there is no harm in
+ * calling one lt_dlinit in the constructor and one lt_dlexit here
+ */
+ lt_dlexit();
+ }
+}
+
+void ExtensionLoader::addStartupClass(class StartupClass *sc)
+{
+ startupClasses.push_back(sc);
+}
diff --git a/mcop/extensionloader.h b/mcop/extensionloader.h
new file mode 100644
index 0000000..ce67f12
--- /dev/null
+++ b/mcop/extensionloader.h
@@ -0,0 +1,59 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef EXTENSIONLOADER_H
+#define EXTENSIONLOADER_H
+
+#include <string>
+#include <list>
+#include <ltdl.h>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): ExtensionLoader
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. No binary compatibility guaranteed. (Interactions:
+ * ObjectManager, Startup stuff)
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT ExtensionLoader {
+protected:
+ std::list<class StartupClass *> startupClasses;
+ lt_dlhandle handle;
+ bool needShutdown;
+
+public:
+ ExtensionLoader(const std::string& path);
+ ~ExtensionLoader();
+
+ bool success();
+ void shutdown();
+
+ void addStartupClass(class StartupClass *sc);
+};
+
+}
+#endif /* EXTENSIONLOADER_H */
diff --git a/mcop/factory.cc b/mcop/factory.cc
new file mode 100644
index 0000000..f0cb2ab
--- /dev/null
+++ b/mcop/factory.cc
@@ -0,0 +1,36 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "factory.h"
+#include "objectmanager.h"
+
+using namespace Arts;
+
+void Factory::startup()
+{
+ ObjectManager::the()->registerFactory(this);
+}
+
+void Factory::shutdown()
+{
+ ObjectManager::the()->removeFactory(this);
+}
diff --git a/mcop/factory.h b/mcop/factory.h
new file mode 100644
index 0000000..91970ad
--- /dev/null
+++ b/mcop/factory.h
@@ -0,0 +1,69 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef FACTORY_H
+#define FACTORY_H
+
+#include <string>
+
+#include "arts_export.h"
+
+#include "object.h"
+#include "startupmanager.h"
+
+/*
+ * BC - Status (2002-03-08): Factory
+ *
+ * Will need to remain binary compatible (REGISTER_IMPLEMENTATION), d ptr
+ * provided for convenience, watch out for interactions with generated
+ * code.
+ */
+
+namespace Arts {
+
+class FactoryPrivate;
+
+class ARTS_EXPORT Factory : public StartupClass {
+private:
+ FactoryPrivate *d;
+public:
+ void startup();
+ void shutdown();
+ virtual Object_skel *createInstance() = 0;
+ virtual std::string interfaceName() = 0;
+};
+
+/*
+ * Dont's forget to place a semicolon after the use of this macro,
+ * like:
+ * REGISTER_IMPLEMENTATION(MyClass);
+ */
+#define REGISTER_IMPLEMENTATION(impl) \
+ class impl ## _Factory : virtual public Arts::Factory { \
+ public: \
+ std::string interfaceName() { return impl::_interfaceNameSkel(); } \
+ Arts::Object_skel *createInstance() { return new impl ; } \
+} The_ ## impl ## _Factory
+
+}
+
+#endif
diff --git a/mcop/flowsystem.cc b/mcop/flowsystem.cc
new file mode 100644
index 0000000..50ca26b
--- /dev/null
+++ b/mcop/flowsystem.cc
@@ -0,0 +1,180 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "flowsystem.h"
+#include "debug.h"
+
+using namespace Arts;
+
+//-------------- ScheduleNode -----------------
+
+ScheduleNode::ScheduleNode(Object_base *object) : _nodeObject(object)
+{
+ //
+}
+
+ScheduleNode::~ScheduleNode()
+{
+ //
+}
+
+Object ScheduleNode::nodeObject()
+{
+ assert(_nodeObject);
+ return Object::_from_base(_nodeObject->_copy());
+}
+
+RemoteScheduleNode *ScheduleNode::remoteScheduleNode()
+{
+ return 0;
+}
+
+void *ScheduleNode::cast(const std::string&)
+{
+ return 0;
+}
+
+
+//----------- RemoteScheduleNode -------------
+
+RemoteScheduleNode::RemoteScheduleNode(Object_stub *stub) : ScheduleNode(stub)
+{
+ //
+}
+
+RemoteScheduleNode *RemoteScheduleNode::remoteScheduleNode()
+{
+ return this;
+}
+
+void RemoteScheduleNode::initStream(const std::string&, void *, long)
+{
+ // not for stub objects
+ assert(false);
+}
+
+void RemoteScheduleNode::requireFlow()
+{
+ // stub objects can't require flow on this server (they don't live here)
+ assert(false);
+}
+
+void RemoteScheduleNode::virtualize(const std::string&, ScheduleNode *,
+ const std::string&)
+{
+ // (de)virtualization of ports is only implemented locally
+ assert(false);
+}
+
+void RemoteScheduleNode::devirtualize(const std::string&, ScheduleNode *,
+ const std::string&)
+{
+ // (de)virtualization of ports is only implemented locally
+ assert(false);
+}
+
+// interface to modify the node from outside
+
+void RemoteScheduleNode::start()
+{
+ FlowSystem remoteFs = nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.startObject(nodeObject());
+}
+
+void RemoteScheduleNode::stop()
+{
+ FlowSystem remoteFs = nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.stopObject(nodeObject());
+}
+
+void RemoteScheduleNode::connect(const std::string& port,
+ ScheduleNode *remoteNode,
+ const std::string& remotePort)
+{
+ arts_return_if_fail(remoteNode != 0);
+
+ FlowSystem fs = nodeObject()._flowSystem();
+ arts_return_if_fail(!fs.isNull());
+
+ AttributeType flags = fs.queryFlags(nodeObject(),port);
+ arts_return_if_fail(flags != 0);
+
+ // connectObject must be called as connectObject([sourcePort], [destPort]);
+
+ if(flags & streamOut) // if our port is an output port, this order
+ {
+ fs.connectObject(nodeObject(),port,remoteNode->nodeObject(),remotePort);
+ }
+ else if(flags & streamIn)
+ {
+ FlowSystem remoteFs = remoteNode->nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.connectObject(remoteNode->nodeObject(),
+ remotePort,nodeObject(),port);
+ } else {
+ assert(false);
+ }
+}
+
+void RemoteScheduleNode::disconnect(const std::string& port,
+ ScheduleNode *remoteNode,
+ const std::string& remotePort)
+{
+ arts_return_if_fail(remoteNode != 0);
+
+ FlowSystem fs = nodeObject()._flowSystem();
+ arts_return_if_fail(!fs.isNull());
+
+ AttributeType flags = fs.queryFlags(nodeObject(),port);
+ arts_return_if_fail(flags != 0);
+
+ // connectObject must be called as connectObject([sourcePort], [destPort]);
+
+ if(flags & streamOut) // if our port is an output port, this order
+ {
+ fs.disconnectObject(nodeObject(),port,remoteNode->nodeObject(),remotePort);
+ }
+ else if(flags & streamIn)
+ {
+ FlowSystem remoteFs = remoteNode->nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.disconnectObject(remoteNode->nodeObject(),
+ remotePort,nodeObject(),port);
+ } else {
+ assert(false);
+ }
+}
+
+// constant values
+void RemoteScheduleNode::setFloatValue(const std::string& port, float value)
+{
+ FlowSystem fs = nodeObject()._flowSystem();
+ arts_return_if_fail(!fs.isNull());
+
+ fs.setFloatValue(nodeObject(), port, value);
+}
diff --git a/mcop/flowsystem.h b/mcop/flowsystem.h
new file mode 100644
index 0000000..c64c57b
--- /dev/null
+++ b/mcop/flowsystem.h
@@ -0,0 +1,147 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef FLOWSYSTEM_H
+#define FLOWSYSTEM_H
+
+#include "arts_export.h"
+#include "object.h"
+#include "common.h"
+
+/*
+ * BC - Status (2002-03-08): ScheduleNode, FlowSystem, FlowSystem_impl,
+ * RemoteScheduleNode
+ *
+ * Heavy interactions with generated and hand-written code, flowsystem binding
+ * and whatever. DO KEEP COMPATIBLE. Do not change the underlying IDL MODEL.
+ * d ptrs available.
+ */
+
+namespace Arts {
+
+class Object_skel;
+class Object_stub;
+class RemoteScheduleNode;
+class ScheduleNodePrivate;
+
+class ARTS_EXPORT ScheduleNode
+{
+private:
+ Object_base *_nodeObject;
+ ScheduleNodePrivate *d; // unused
+
+public:
+ ScheduleNode(Object_base *object);
+ virtual ~ScheduleNode();
+
+ Object nodeObject();
+
+ // check if this is a remote schedule node
+
+ virtual RemoteScheduleNode *remoteScheduleNode();
+
+ // other casts
+
+ virtual void *cast(const std::string& target);
+
+ // internal interface against Object_skel
+
+ typedef bool (*QueryInitStreamFunc)(Object_skel *object,
+ const std::string& name);
+
+ virtual void initStream(const std::string& name, void *ptr, long flags) = 0;
+
+ // interface against node implementation
+
+ virtual void requireFlow() = 0;
+ virtual void virtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort) = 0;
+ virtual void devirtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort) = 0;
+
+ // interface to modify the node from outside
+
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ virtual void connect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort) = 0;
+ virtual void disconnect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort) = 0;
+
+ // constant values
+ virtual void setFloatValue(const std::string& port, float value) = 0;
+};
+
+class RemoteScheduleNodePrivate;
+
+class ARTS_EXPORT RemoteScheduleNode : public ScheduleNode
+{
+private:
+ RemoteScheduleNodePrivate *d; // unused
+public:
+ RemoteScheduleNode(Object_stub *stub);
+
+ RemoteScheduleNode *remoteScheduleNode();
+
+ // internal interface against Object_skel
+
+ void initStream(const std::string& name, void *ptr, long flags);
+
+ // interface against node implementation
+
+ void requireFlow();
+ virtual void virtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort);
+ virtual void devirtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort);
+
+ // interface to modify the node from outside
+
+ void start();
+ void stop();
+ void connect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort);
+ void disconnect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort);
+
+ // constant values
+ void setFloatValue(const std::string& port, float value);
+};
+
+class FlowSystem_impl_private;
+
+class FlowSystem_impl :virtual public FlowSystem_skel
+{
+private:
+ FlowSystem_impl_private *d;
+public:
+ virtual ScheduleNode *addObject(Object_skel *object) = 0;
+ virtual void removeObject(ScheduleNode *node) = 0;
+ virtual bool suspendable() = 0;
+ virtual bool suspended() = 0;
+ virtual void suspend() = 0;
+ virtual void restart() = 0;
+};
+
+}
+
+#endif
diff --git a/mcop/idlfilereg.cc b/mcop/idlfilereg.cc
new file mode 100644
index 0000000..4c15e24
--- /dev/null
+++ b/mcop/idlfilereg.cc
@@ -0,0 +1,44 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "common.h"
+
+using namespace Arts;
+
+IDLFileReg::IDLFileReg(const char *name, const char *contents)
+{
+ _name = name;
+ _contents = contents;
+}
+
+void IDLFileReg::startup()
+{
+ Buffer b;
+ b.fromString(_contents,"IDLFile");
+
+ nr = Dispatcher::the()->interfaceRepo().insertModule(ModuleDef(b));
+}
+
+void IDLFileReg::shutdown()
+{
+ Dispatcher::the()->interfaceRepo().removeModule(nr);
+}
diff --git a/mcop/idlfilereg.h b/mcop/idlfilereg.h
new file mode 100644
index 0000000..e9146ba
--- /dev/null
+++ b/mcop/idlfilereg.h
@@ -0,0 +1,51 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef IDLFILEREG_H
+#define IDLFILEREG_H
+
+#include <string>
+#include "startupmanager.h"
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): IDLFileReg
+ *
+ * Will be kept binary compatible by NOT TOUCHING AT ALL. Do not change this.
+ * (Interaction with generated code). Add a new class if you need something
+ * else than this does.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT IDLFileReg : public StartupClass {
+ long nr;
+ const char *_name, *_contents;
+public:
+ IDLFileReg(const char *name, const char *contents);
+ void startup();
+ void shutdown();
+};
+
+}
+#endif /* IDLFILEREG_H */
diff --git a/mcop/ifacerepo_impl.cc b/mcop/ifacerepo_impl.cc
new file mode 100644
index 0000000..5a7572c
--- /dev/null
+++ b/mcop/ifacerepo_impl.cc
@@ -0,0 +1,305 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "ifacerepo_impl.h"
+#include "debug.h"
+#include <iostream>
+#include <stdio.h>
+
+using namespace std;
+using namespace Arts;
+
+InterfaceRepo_impl::InterfaceRepo_impl()
+{
+ nextModuleID = 1;
+ tiMap["void"] = tiVoid;
+ tiMap["byte"] = tiByte;
+ tiMap["string"] = tiString;
+ tiMap["boolean"] = tiBoolean;
+ tiMap["float"] = tiFloat;
+ tiMap["long"] = tiLong;
+ tiMap["object"] = tiInterface;
+}
+
+InterfaceRepo_impl::~InterfaceRepo_impl()
+{
+ while(!unloadModuleList.empty())
+ {
+ removeModule(unloadModuleList.front());
+ unloadModuleList.pop_front();
+ }
+}
+
+long InterfaceRepo_impl::insertModule(const ModuleDef& newModule)
+{
+ long moduleID = nextModuleID++;
+
+ /* insert interfaces */
+ vector<InterfaceDef>::const_iterator ii;
+ for(ii=newModule.interfaces.begin();
+ ii != newModule.interfaces.end();ii++)
+ {
+ Buffer b;
+ ii->writeType(b);
+ InterfaceEntry *ie = new InterfaceEntry(b,moduleID);
+ interfaces.push_back(ie);
+
+ tiMap[ie->name] = tiInterface;
+ }
+
+ /* insert types */
+ vector<TypeDef>::const_iterator ti;
+ for(ti=newModule.types.begin();
+ ti != newModule.types.end();ti++)
+ {
+ Buffer b;
+ ti->writeType(b);
+ TypeEntry *entry = new TypeEntry(b,moduleID);
+ types.push_back(entry);
+
+ tiMap[entry->name] = tiType;
+ }
+
+ /* insert enums */
+ vector<EnumDef>::const_iterator ei;
+ for(ei=newModule.enums.begin();
+ ei != newModule.enums.end();ei++)
+ {
+ Buffer b;
+ ei->writeType(b);
+ EnumEntry *entry = new EnumEntry(b,moduleID);
+ enums.push_back(entry);
+
+ tiMap[entry->name] = tiEnum;
+ }
+
+ return moduleID;
+}
+
+void InterfaceRepo_impl::removeModule(long moduleID)
+{
+ /* erase interfaces */
+ list<InterfaceEntry *>::iterator ii;
+ ii = interfaces.begin();
+ while(ii != interfaces.end())
+ {
+ if((*ii)->moduleID == moduleID)
+ {
+ delete (*ii);
+ interfaces.erase(ii);
+ ii = interfaces.begin();
+ }
+ else ii++;
+ }
+
+ /* erase types */
+ list<TypeEntry *>::iterator ti;
+ ti = types.begin();
+ while(ti != types.end())
+ {
+ if((*ti)->moduleID == moduleID)
+ {
+ delete (*ti);
+ types.erase(ti);
+ ti = types.begin();
+ }
+ else ti++;
+ }
+
+ /* erase enums */
+ list<EnumEntry *>::iterator ei;
+ ei = enums.begin();
+ while(ei != enums.end())
+ {
+ if((*ei)->moduleID == moduleID)
+ {
+ delete (*ei);
+ enums.erase(ei);
+ ei = enums.begin();
+ }
+ else ei++;
+ }
+}
+
+InterfaceDef InterfaceRepo_impl::queryInterfaceLocal(const string& name)
+{
+ list<InterfaceEntry *>::iterator ii;
+
+ for(ii = interfaces.begin();ii != interfaces.end();ii++)
+ {
+ if((*ii)->name == name)
+ return **ii;
+ }
+ return InterfaceDef();
+}
+
+InterfaceDef InterfaceRepo_impl::queryInterface(const string& name)
+{
+ InterfaceDef def = queryInterfaceLocal(name);
+
+ if(def.name.empty())
+ {
+ TraderQuery q;
+ q.supports("Type",name);
+ vector<TraderOffer> *offers = q.query();
+ vector<TraderOffer>::iterator i;
+ for(i = offers->begin(); i != offers->end();i++)
+ {
+ TraderOffer& offer = *i;
+
+ if(def.name.empty())
+ {
+ vector<string> *types = offer.getProperty("TypeFile");
+ if(types->size() == 1)
+ {
+ const vector<string> *path = MCOPUtils::traderPath();
+
+ vector<string>::const_iterator pi = path->begin();
+ while(pi != path->end() && def.name.empty())
+ {
+ string filename = *pi++ + "/" + types->front();
+
+ FILE *extfile = fopen(filename.c_str(),"r");
+ if(extfile)
+ {
+ arts_debug("InterfaceRepo: loading %s",
+ filename.c_str());
+
+ Buffer b;
+ int c;
+ while((c = fgetc(extfile)) >= 0) b.writeByte(c);
+ fclose(extfile);
+
+ long id = insertModule(ModuleDef(b));
+ def = queryInterfaceLocal(name);
+ unloadModuleList.push_back(id);
+ }
+ }
+ }
+ delete types;
+ }
+ }
+ delete offers;
+ }
+
+ if(def.name.empty())
+ {
+ arts_warning("InterfaceRepo: no information about the interface %s "
+ "is known", name.c_str());
+ }
+
+ return def;
+}
+
+TypeDef InterfaceRepo_impl::queryType(const string& name)
+{
+ list<TypeEntry *>::iterator ti;
+
+ for(ti = types.begin();ti != types.end();ti++)
+ {
+ if((*ti)->name == name)
+ return **ti;
+ }
+
+ arts_warning("InterfaceRepo: no information about the type %s is known.",
+ name.c_str());
+ return TypeDef();
+}
+
+EnumDef InterfaceRepo_impl::queryEnum(const string& name)
+{
+ list<EnumEntry *>::iterator ei;
+
+ for(ei = enums.begin();ei != enums.end();ei++)
+ {
+ if((*ei)->name == name)
+ return **ei;
+ }
+
+ arts_warning("InterfaceRepo: no information about the enum %s is known.",
+ name.c_str());
+ return EnumDef();
+}
+
+vector<string> *InterfaceRepo_impl::queryChildren(const std::string& name)
+{
+ vector<string> *result = new vector<string>;
+ list<InterfaceEntry *>::iterator ii;
+
+ for(ii = interfaces.begin();ii != interfaces.end();ii++)
+ {
+ bool found = false;
+ vector<string>::iterator j;
+
+ for(j = (*ii)->inheritedInterfaces.begin();
+ j != (*ii)->inheritedInterfaces.end() && !found; j++)
+ {
+ if(*j == name)
+ {
+ result->push_back((*ii)->name);
+ found = true;
+ }
+ }
+ if((*ii)->inheritedInterfaces.empty() && ((name == "Arts::Object") || (name == "object")) && ((*ii)->name != "Arts::Object"))
+ result->push_back((*ii)->name);
+ }
+
+ return result;
+}
+
+vector<string> *InterfaceRepo_impl::queryInterfaces()
+{
+ vector<string> *result = new vector<string>;
+ list<InterfaceEntry *>::iterator ii;
+
+ for(ii = interfaces.begin();ii != interfaces.end();ii++)
+ result->push_back((*ii)->name);
+
+ return result;
+}
+
+vector<string> *InterfaceRepo_impl::queryTypes()
+{
+ vector<string> *result = new vector<string>;
+ list<TypeEntry *>::iterator ti;
+
+ for(ti = types.begin();ti != types.end();ti++)
+ result->push_back((*ti)->name);
+
+ return result;
+}
+
+vector<string> *InterfaceRepo_impl::queryEnums()
+{
+ vector<string> *result = new vector<string>;
+ list<EnumEntry *>::iterator ei;
+
+ for(ei = enums.begin();ei != enums.end();ei++)
+ result->push_back((*ei)->name);
+
+ return result;
+}
+
+TypeIdentification InterfaceRepo_impl::identifyType(const string& name)
+{
+ return tiMap[name];
+}
diff --git a/mcop/ifacerepo_impl.h b/mcop/ifacerepo_impl.h
new file mode 100644
index 0000000..ffa98de
--- /dev/null
+++ b/mcop/ifacerepo_impl.h
@@ -0,0 +1,98 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): InterfaceRepo_impl
+ *
+ * This is an implementation class, and not kept binary compatible. It's
+ * only here since the REGISTER_IMPLEMENTATION bootstrapping may not yet
+ * be done before the first piece of startup code (IDLFileReg) needs the
+ * Interface repository.
+ */
+
+#ifndef IFACEREPO_H
+#define IFACEREPO_H
+
+#include "common.h"
+#include <map>
+
+namespace Arts {
+
+class InterfaceRepo_impl : virtual public InterfaceRepoV2_skel {
+ class Entry {
+ public:
+ long moduleID;
+ Entry(long moduleID) : moduleID(moduleID)
+ {
+ }
+ };
+ class EnumEntry : public EnumDef, public Entry {
+ public:
+ EnumEntry(Buffer& stream, long moduleID)
+ :EnumDef(stream), Entry(moduleID)
+ {
+ }
+ };
+ class TypeEntry : public TypeDef, public Entry {
+ public:
+ TypeEntry(Buffer& stream, long moduleID)
+ :TypeDef(stream), Entry(moduleID)
+ {
+ }
+ };
+ class InterfaceEntry : public InterfaceDef, public Entry {
+ public:
+ InterfaceEntry(Buffer& stream, long moduleID)
+ :InterfaceDef(stream), Entry(moduleID)
+ {
+ };
+ };
+
+ std::list<EnumEntry *> enums;
+ std::list<TypeEntry *> types;
+ std::list<InterfaceEntry *> interfaces;
+ std::map<std::string, TypeIdentification> tiMap;
+ std::list<long> unloadModuleList;
+
+ long nextModuleID;
+
+ InterfaceDef queryInterfaceLocal(const std::string& name);
+public:
+
+ InterfaceRepo_impl();
+ ~InterfaceRepo_impl();
+
+ long insertModule(const ModuleDef& newModule);
+ void removeModule(long moduleID);
+ InterfaceDef queryInterface(const std::string& name);
+ TypeDef queryType(const std::string& name);
+ EnumDef queryEnum(const std::string& name);
+
+ TypeIdentification identifyType(const std::string& name);
+
+ std::vector<std::string> *queryChildren(const std::string& name);
+ std::vector<std::string> *queryInterfaces();
+ std::vector<std::string> *queryTypes();
+ std::vector<std::string> *queryEnums();
+};
+}
+#endif /* IFACEREPO_H */
diff --git a/mcop/iomanager.cc b/mcop/iomanager.cc
new file mode 100644
index 0000000..442318a
--- /dev/null
+++ b/mcop/iomanager.cc
@@ -0,0 +1,494 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "iomanager.h"
+#include "dispatcher.h"
+#include "notification.h"
+#include "thread.h"
+#include <stdio.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h> // Needed on some systems.
+#endif
+// WABA: NOTE!
+// sys/select.h is needed on e.g. AIX to define "fd_set".
+// However, we can not include config.h in a header file.
+// The right solution would be not to use "fd_set" in the
+// header file but to use it only in a private datastructure
+// defined in the .cc file.
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+/* internal data structures */
+class IOWatchFD {
+ int _fd, _types;
+ IONotify *_notify;
+
+public:
+ int activeTypes;
+
+ IOWatchFD(int fd, int types, IONotify *notify);
+
+ inline int fd() { return _fd; };
+ inline int types() { return _types; };
+ inline IONotify *notify() { return _notify; };
+ inline void remove(int types) { _types &= ~types; }
+};
+
+class TimeWatcher {
+ int milliseconds;
+ TimeNotify *_notify;
+ timeval nextNotify;
+ bool active, destroyed;
+
+ bool earlier(const timeval& reference);
+public:
+ TimeWatcher(int _milliseconds, TimeNotify *notify);
+
+ inline TimeNotify *notify() { return _notify; };
+ timeval advance(const timeval& currentTime);
+ void destroy();
+};
+}
+
+/*
+ * Enable this if you want to debug how long certain plugins / operations
+ * take to perform. You'll get the times between two select() calls that are
+ * done by the IOManager, which is equivalent to the time the input/output
+ * remains unserved. For apps like artsd, it gives the minimum audio latency
+ * users will need to specify to avoid dropouts.
+ */
+#undef IOMANAGER_DEBUG_LATENCY
+
+#ifdef IOMANAGER_DEBUG_LATENCY
+static timeval iomanager_debug_latency_time = { 0, 0 };
+
+static void iomanager_debug_latency_end()
+{
+ if(iomanager_debug_latency_time.tv_sec)
+ {
+ timeval end;
+ gettimeofday(&end,0);
+
+ float diff = (end.tv_usec-iomanager_debug_latency_time.tv_usec)/1000.0
+ + (end.tv_sec-iomanager_debug_latency_time.tv_sec)*1000.0;
+
+ /* change this value if you get your screen filled up with messages */
+ if(diff >= 1.5)
+ fprintf(stderr,"IOManager: latency for operation: %2.3f ms\n",diff);
+ }
+}
+
+static void iomanager_debug_latency_start()
+{
+ gettimeofday(&iomanager_debug_latency_time,0);
+}
+#else
+static inline void iomanager_debug_latency_end()
+{
+}
+
+static inline void iomanager_debug_latency_start()
+{
+}
+#endif
+
+IOWatchFD::IOWatchFD(int fd, int types, IONotify *notify)
+{
+ _fd = fd;
+ _types = types;
+ _notify = notify;
+ activeTypes = 0;
+}
+
+StdIOManager::StdIOManager()
+{
+ // force initialization of the fd_set's
+ fdListChanged = true;
+ timeListChanged = false;
+ level = 0;
+}
+
+void StdIOManager::processOneEvent(bool blocking)
+{
+ assert(SystemThreads::the()->isMainThread());
+
+ level++;
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::lock();
+
+ // notifications not carried out reentrant
+ if(level == 1)
+ NotificationManager::the()->run();
+
+ // FIXME: timers *could* change the file descriptors to select...
+ //---
+ if(fdListChanged)
+ {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ FD_ZERO(&reentrant_readfds);
+ FD_ZERO(&reentrant_writefds);
+ FD_ZERO(&reentrant_exceptfds);
+
+ maxfd = 0;
+
+ list<IOWatchFD *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++)
+ {
+ IOWatchFD *w = *i;
+
+ if(w->types() & IOType::read) FD_SET(w->fd(),&readfds);
+ if(w->types() & IOType::write) FD_SET(w->fd(),&writefds);
+ if(w->types() & IOType::except) FD_SET(w->fd(),&exceptfds);
+
+ if(w->types() & IOType::reentrant)
+ {
+ if(w->types() & IOType::read)
+ FD_SET(w->fd(),&reentrant_readfds);
+ if(w->types() & IOType::write)
+ FD_SET(w->fd(),&reentrant_writefds);
+ if(w->types() & IOType::except)
+ FD_SET(w->fd(),&reentrant_exceptfds);
+ }
+
+ if(w->types() && w->fd() > maxfd) maxfd = w->fd();
+ }
+
+ fdListChanged = false;
+ }
+ fd_set rfd,wfd,efd;
+ if(level == 1)
+ {
+ rfd = readfds;
+ wfd = writefds;
+ efd = exceptfds;
+ }
+ else
+ {
+ // watch out, this is reentrant I/O
+ rfd = reentrant_readfds;
+ wfd = reentrant_writefds;
+ efd = reentrant_exceptfds;
+ }
+
+ /* default timeout 5 seconds */
+ long selectabs;
+
+ if(blocking)
+ selectabs = 5000000;
+ else
+ selectabs = 0;
+
+ /* prepare timers - only at level 1 */
+ if(level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<TimeWatcher *>::iterator ti;
+
+ timeListChanged = false;
+ ti = timeList.begin();
+ while(ti != timeList.end())
+ {
+ TimeWatcher *w = *ti++;
+ timeval timertime = w->advance(currenttime);
+
+ // if that may happen in the next ten seconds
+ if(timertime.tv_sec < currenttime.tv_sec+10)
+ {
+ long timerabs = (timertime.tv_sec - currenttime.tv_sec)*1000000;
+ timerabs += (timertime.tv_usec - currenttime.tv_usec);
+
+ if(timerabs < selectabs) selectabs = timerabs;
+ }
+
+ if(timeListChanged)
+ {
+ ti = timeList.begin();
+ timeListChanged = false;
+ }
+ }
+ }
+
+ timeval select_timeout;
+ select_timeout.tv_sec = selectabs / 1000000;
+ select_timeout.tv_usec = selectabs % 1000000;
+
+ if(level == 1) iomanager_debug_latency_end();
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::unlock();
+
+ int retval = select(maxfd+1,&rfd,&wfd,&efd,&select_timeout);
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::lock();
+
+ if(level == 1) iomanager_debug_latency_start();
+
+ if(retval > 0)
+ {
+ /*
+ * the problem is, that objects that are being notified may change
+ * the watch list, add fds, remove fds, remove objects and whatever
+ * else
+ *
+ * so we can' notify them from the loop - but we can make a stack
+ * of "notifications to do" and send them as soon as we looked up
+ * in the list what to send
+ */
+ long tonotify = 0;
+
+ list<IOWatchFD *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++) {
+ IOWatchFD *w = *i;
+ int match = 0;
+
+ if(FD_ISSET(w->fd(),&rfd) && (w->types() & IOType::read))
+ match |= IOType::read;
+
+ if(FD_ISSET(w->fd(),&wfd) && (w->types() & IOType::write))
+ match |= IOType::write;
+
+ if(FD_ISSET(w->fd(),&efd) && (w->types() & IOType::except))
+ match |= IOType::except;
+
+ if((w->types() & IOType::reentrant) == 0 && level != 1)
+ match = 0;
+
+ if(match) {
+ tonotify++;
+ w->activeTypes = match;
+ notifyStack.push(w);
+ }
+ }
+
+ while(tonotify != 0)
+ {
+ if(!fdListChanged)
+ {
+ IOWatchFD *w = notifyStack.top();
+ int activeTypes = w->activeTypes;
+ int fd = w->fd();
+ IONotify *notify = w->notify();
+
+ w->activeTypes = 0;
+ notify->notifyIO(fd, activeTypes);
+ // warning: w and notify might no longer exist here
+ }
+
+ notifyStack.pop();
+ tonotify--;
+ }
+ }
+ /* handle timers - only at level 1 */
+ if(level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<TimeWatcher *>::iterator ti;
+
+ timeListChanged = false;
+ ti = timeList.begin();
+ while(ti != timeList.end())
+ {
+ TimeWatcher *w = *ti++;
+ w->advance(currenttime);
+ if (timeListChanged)
+ {
+ ti = timeList.begin();
+ timeListChanged = false;
+ }
+ }
+ }
+
+ // notifications not carried out reentrant
+ if(level == 1)
+ NotificationManager::the()->run();
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::unlock();
+
+ level--;
+}
+
+void StdIOManager::run()
+{
+ assert(SystemThreads::the()->isMainThread());
+ assert(level == 0);
+
+ // FIXME: this might not be threadsafe, as there is no lock here!
+ terminated = false;
+ while(!terminated)
+ processOneEvent(true);
+}
+
+void StdIOManager::terminate()
+{
+ terminated = true;
+ Dispatcher::wakeUp();
+}
+
+void StdIOManager::watchFD(int fd, int types, IONotify *notify)
+{
+ /*
+ IOWatchFD *watchfd = findWatch(fd,notify);
+ if(watchfd)
+ {
+ watchfd->add(types);
+ }
+ else
+ {
+ fdList.push_back(new IOWatchFD(fd,types,notify));
+ }
+ */
+
+ // FIXME: might want to reuse old watches
+ fdList.push_back(new IOWatchFD(fd,types,notify));
+ fdListChanged = true;
+ Dispatcher::wakeUp();
+}
+
+void StdIOManager::remove(IONotify *notify, int types)
+{
+ list<IOWatchFD *>::iterator i;
+
+ i = fdList.begin();
+
+ while(i != fdList.end())
+ {
+ IOWatchFD *w = *i;
+
+ if(w->notify() == notify) w->remove(types);
+
+ // nothing left to watch?
+ if(w->types() == 0 || w->types() == IOType::reentrant)
+ {
+ i = fdList.erase(i);
+ delete w; // FIXME: shouldn't we have a destroy() similar
+ // to the one for timers
+ }
+ else i++;
+ }
+ fdListChanged = true;
+}
+
+void StdIOManager::addTimer(int milliseconds, TimeNotify *notify)
+{
+ if (milliseconds == -1 && notify == 0) {
+ // HACK: in order to not add a virtual function to IOManager we're calling addTimer with
+ // magic values. This call tells the ioManager that notifications are pending and
+ // NotificationManager::run() should get called soon.
+ } else {
+ timeList.push_back(new TimeWatcher(milliseconds,notify));
+ timeListChanged = true;
+ Dispatcher::wakeUp();
+ }
+}
+
+void StdIOManager::removeTimer(TimeNotify *notify)
+{
+ list<TimeWatcher *>::iterator i;
+
+ i = timeList.begin();
+
+ while(i != timeList.end())
+ {
+ TimeWatcher *w = *i;
+
+ if(w->notify() == notify)
+ {
+ i = timeList.erase(i);
+ timeListChanged = true;
+ w->destroy();
+ }
+ else i++;
+ }
+}
+
+TimeWatcher::TimeWatcher(int _milliseconds, TimeNotify *notify)
+ : milliseconds(_milliseconds),_notify(notify),active(false),destroyed(false)
+{
+ gettimeofday(&nextNotify,0);
+
+ nextNotify.tv_usec += (milliseconds%1000)*1000;
+ nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000);
+ nextNotify.tv_usec %= 1000000;
+}
+
+timeval TimeWatcher::advance(const timeval& currentTime)
+{
+ active = true;
+ while(earlier(currentTime))
+ {
+ nextNotify.tv_usec += (milliseconds%1000)*1000;
+ nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000);
+ nextNotify.tv_usec %= 1000000;
+
+ _notify->notifyTime();
+
+ if(destroyed)
+ {
+ delete this;
+
+ struct timeval never = { 0xffffffff, 0 };
+ return never;
+ }
+ }
+ active = false;
+ return nextNotify;
+}
+
+bool TimeWatcher::earlier(const timeval& reference)
+{
+ if(nextNotify.tv_sec > reference.tv_sec) return false;
+ if(nextNotify.tv_sec < reference.tv_sec) return true;
+
+ return (nextNotify.tv_usec < reference.tv_usec);
+}
+
+void TimeWatcher::destroy()
+{
+ if(active)
+ {
+ destroyed = true;
+ }
+ else
+ {
+ delete this;
+ }
+}
diff --git a/mcop/iomanager.h b/mcop/iomanager.h
new file mode 100644
index 0000000..a226e0c
--- /dev/null
+++ b/mcop/iomanager.h
@@ -0,0 +1,214 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08):
+ * BINARY COMPATIBLE: IONotify, TimeNotify, IOManager
+ * NO BC FOR: StdIOManager
+ *
+ * Whereas the first three are part of the Interface (i.e. DEFINITELY to be
+ * kept binary compatible), the next three are part of the implementation
+ * in libmcop and subject to any kind of change.
+ */
+
+#ifndef IOMANAGER_H
+#define IOMANAGER_H
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <list>
+#include <stack>
+
+#include "arts_export.h"
+
+namespace Arts {
+// constants:
+
+/**
+ * What does the reentrant flag do?
+ *
+ * The IOManager offers a processOneEvent call. This means, that you can ask
+ * that I/O is handled, even while in a routine that handles I/O. As a
+ * practical example: you may have got a remote invocation for the function
+ * foo. Now you are in function foo() and call function bar() on a remote
+ * server. When you wait for the result, you obviously will again require
+ * the IOManager to wait for it. Thus this is a case where you need reentrant
+ * I/O handling.
+ *
+ * That way, you get a multiple level stack:
+ *
+ * <pre>
+ * [...]
+ * |
+ * [ Hander for I/O ]
+ * |
+ * [ IOManager ] level 2
+ * |
+ * [ Some other function ]
+ * |
+ * [ Hander for I/O ]
+ * |
+ * [ IOManager ] level 1
+ * |
+ * [ main() ]
+ * </pre>
+ *
+ * What reentrant does, is to allow that IO Watch to be activated at levels
+ * higher than one.
+ *
+ * Timers and notifications, on the other hand will only be carried out at
+ * level 1.
+ */
+struct IOType {
+ enum { read = 1, write = 2, except = 4, reentrant = 8, all = 15 };
+};
+
+/**
+ * IONotify is the base class you can derive from to receive callbacks about
+ * IO activity. You will need to call the watchFD function of the IOManager
+ * to start watching a filedescriptor.
+ *
+ * @see Arts::IOManager
+ */
+class ARTS_EXPORT IONotify {
+public:
+ /**
+ * This is the function that gets called if something relevant happened
+ * on the filedescriptor you watched with IOManager::watchFD.
+ *
+ * @param fd is the filedescriptor that has seen some IO activity
+ * @param type is the type of activity (as combination of IOType)
+ */
+ virtual void notifyIO(int fd, int type) = 0;
+};
+
+/**
+ * TimeNotify is the base class you can derive from to receive timer callbacks.
+ * You will need to call the addTimer function of the IOManager to start
+ * watching a filedescriptor.
+ *
+ * @see Arts::IOManager
+ */
+class ARTS_EXPORT TimeNotify {
+public:
+ /**
+ * This function gets whenever the timer is activated. Note that the
+ * IOManager will try to "catch up" lost time, that is, if you have a
+ * 300ms timer that didn't get called for a second (because there was
+ * something else to do), you'll receive three calls in a row.
+ */
+ virtual void notifyTime() = 0;
+};
+
+/**
+ * Provides services like timers and notifications when filedescriptors get
+ * ready to read/write.
+ */
+class ARTS_EXPORT IOManager {
+public:
+ virtual ~IOManager() {};
+
+ /**
+ * processes exactly one io event
+ */
+ virtual void processOneEvent(bool blocking) = 0;
+
+ /**
+ * enters a loop which processes io events, until terminate is called
+ *
+ * may only be called once (use processOneEvent for other purposes)
+ */
+ virtual void run() = 0;
+
+ /**
+ * terminates the io event loop (which was started with run)
+ */
+ virtual void terminate() = 0;
+
+ /**
+ * starts watching one filedescriptor for certain types of operations
+ *
+ * notifies the notify object when e.g. the fd requires (allows) reading
+ * and types contained IOType::read.
+ *
+ * @see Arts::IOType
+ * @see Arts::IONotify
+ */
+ virtual void watchFD(int fd, int types, IONotify *notify) = 0;
+
+ /**
+ * stops watching a filedescriptor
+ */
+ virtual void remove(IONotify *notify, int types) = 0;
+ /*
+ * BCI when breaking BC, probably int fd should be added as argument
+ * to remove, this would be more consistent with the way watches are added
+ */
+
+ /**
+ * starts a periodic timer
+ *
+ * @see Arts::TimeNotify
+ */
+ virtual void addTimer(int milliseconds, TimeNotify *notify) = 0;
+
+ /**
+ * stops the timer
+ */
+ virtual void removeTimer(TimeNotify *notify) = 0;
+};
+
+class IOWatchFD;
+class TimeWatcher;
+
+class ARTS_EXPORT StdIOManager : public IOManager {
+protected:
+ std::list<IOWatchFD *> fdList;
+ std::list<TimeWatcher *> timeList;
+ std::stack<IOWatchFD *> notifyStack;
+
+ bool terminated;
+
+ bool fdListChanged; // causes the fd_sets to be rebuilt before using them
+ bool timeListChanged;
+ fd_set readfds, writefds, exceptfds;
+ fd_set reentrant_readfds, reentrant_writefds, reentrant_exceptfds;
+ int maxfd;
+
+ int level;
+
+public:
+ StdIOManager();
+
+ void processOneEvent(bool blocking);
+ void run();
+ void terminate();
+ void watchFD(int fd, int types, IONotify *notify);
+ void remove(IONotify *notify, int types);
+ void addTimer(int milliseconds, TimeNotify *notify);
+ void removeTimer(TimeNotify *notify);
+};
+
+}
+
+#endif
diff --git a/mcop/loopback.cc b/mcop/loopback.cc
new file mode 100644
index 0000000..0cc58a8
--- /dev/null
+++ b/mcop/loopback.cc
@@ -0,0 +1,57 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "loopback.h"
+#include "common.h"
+
+using namespace Arts;
+using namespace std;
+
+LoopbackConnection::LoopbackConnection(const std::string& serverID)
+{
+ setServerID(serverID);
+ _connState = established;
+}
+
+void LoopbackConnection::qSendBuffer(Buffer *buffer)
+{
+ assert(buffer->size() >= 12);
+
+ long magic = buffer->readLong();
+ assert(magic == MCOP_MAGIC);
+
+ /* messageSize, irrelevant here, since we've got the buffer already */
+ buffer->readLong();
+ long messageType = buffer->readLong();
+
+ Dispatcher::the()->handle(this,buffer,messageType);
+}
+
+void LoopbackConnection::drop()
+{
+ assert(false);
+}
+
+bool LoopbackConnection::broken()
+{
+ return false;
+}
diff --git a/mcop/loopback.h b/mcop/loopback.h
new file mode 100644
index 0000000..0e0c092
--- /dev/null
+++ b/mcop/loopback.h
@@ -0,0 +1,51 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef MCOP_LOOPBACKCONNECTION_H
+#define MCOP_LOOPBACKCONNECTION_H
+
+#include "connection.h"
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): LoopbackConnection
+ *
+ * Not part of the public API. Do NOT use it in your apps. No binary
+ * compatibility guaranteed.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT LoopbackConnection : public Connection
+{
+public:
+ LoopbackConnection(const std::string& serverID);
+
+ void qSendBuffer(Buffer *buffer);
+ void drop();
+ bool broken();
+};
+
+}
+
+#endif /* MCOP_LOOPBACKCONNECTION_H */
diff --git a/mcop/mcopconfig.cc b/mcop/mcopconfig.cc
new file mode 100644
index 0000000..ad56c55
--- /dev/null
+++ b/mcop/mcopconfig.cc
@@ -0,0 +1,67 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "mcopconfig.h"
+#include "mcoputils.h"
+#include <fstream>
+
+using namespace std;
+using namespace Arts;
+
+MCOPConfig::MCOPConfig(const string& filename) :filename(filename)
+{
+}
+
+string MCOPConfig::readEntry(const string& key, const string& defaultValue)
+{
+ ifstream in(filename.c_str());
+ string keyvalue;
+
+ while(in >> keyvalue)
+ {
+ int i = keyvalue.find("=",0);
+ if(i != 0 && keyvalue.substr( 0, i ) == key)
+ return keyvalue.substr( i+1, keyvalue.size()-(i+1) );
+ }
+ return defaultValue;
+}
+
+vector<string> *MCOPConfig::readListEntry(const string& key)
+{
+ vector<string> *result = new vector<string>;
+
+ ifstream in(filename.c_str());
+ string keyvalue;
+
+ while(in >> keyvalue)
+ {
+ string k;
+
+ MCOPUtils::tokenize(keyvalue,k,*result);
+ if(k == key)
+ return result;
+
+ result->clear();
+ }
+
+ return result;
+}
diff --git a/mcop/mcopconfig.h b/mcop/mcopconfig.h
new file mode 100644
index 0000000..04531f0
--- /dev/null
+++ b/mcop/mcopconfig.h
@@ -0,0 +1,55 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): MCOPConfig
+ *
+ * Is guaranteed to stay binary compatible. d ptr provided.
+ */
+
+#ifndef MCOPCONFIG_H
+#define MCOPCONFIG_H
+
+#include <string>
+#include <vector>
+
+#include "arts_export.h"
+
+namespace Arts {
+
+class MCOPConfigPrivate;
+class ARTS_EXPORT MCOPConfig {
+private:
+ MCOPConfigPrivate *d; // unused
+protected:
+ std::string filename;
+
+public:
+ MCOPConfig(const std::string& filename);
+
+ std::string readEntry(const std::string& key,
+ const std::string& defaultValue = "");
+ std::vector<std::string> *readListEntry(const std::string& key);
+};
+
+}
+#endif /* MCOPCONFIG_H */
diff --git a/mcop/mcoputils.cc b/mcop/mcoputils.cc
new file mode 100644
index 0000000..14275fb
--- /dev/null
+++ b/mcop/mcoputils.cc
@@ -0,0 +1,574 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "mcoputils.h"
+#include "mcopconfig.h"
+#include "debug.h"
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <config.h>
+#include <ctype.h>
+#include <cstdlib>
+#include <cstring>
+#include <stdio.h>
+#include <map>
+
+using namespace std;
+using namespace Arts;
+
+// 0: Dir ok
+// 1: Dir not ok
+static int check_tmp_dir(const char *tmp_dir)
+{
+ int result;
+ struct stat stat_buf;
+ result = lstat(tmp_dir, &stat_buf);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ return 1;
+ }
+ if ((result == -1) || (!S_ISDIR(stat_buf.st_mode)))
+ {
+ arts_warning("Error: \"%s\" is not a directory.\n", tmp_dir);
+ return 1;
+ }
+
+ if (stat_buf.st_uid != getuid())
+ {
+ arts_warning("Error: \"%s\" is owned by uid %d instead of uid %d.\n", tmp_dir, stat_buf.st_uid, getuid());
+ return 1;
+ }
+ return 0;
+}
+
+
+// 0: Link not ok
+// != 0: location of mcop directory
+static char *locate_mcop_dir()
+{
+ struct passwd *pw_ent;
+ char kde_tmp_dir[PATH_MAX+1];
+ char user_tmp_dir[PATH_MAX+1];
+ int uid = getuid();
+ const char *home_dir = getenv("HOME");
+ const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME");
+ const char *kde_prefix = "/socket-";
+ const char *tmp;
+ char *tmp_buf;
+ int result;
+ struct stat stat_buf;
+
+ tmp = getenv("KDETMP");
+ if (!tmp || !tmp[0])
+ tmp = getenv("TMPDIR");
+ if (!tmp || !tmp[0])
+ tmp = "/tmp";
+
+ kde_tmp_dir[0] = 0;
+
+ pw_ent = getpwuid(uid);
+ if (!pw_ent)
+ {
+ arts_warning("Error: Can not find password entry for uid %d.\n", getuid());
+ return 0;
+ }
+
+ strncpy(user_tmp_dir, tmp, PATH_MAX );
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, "/ksocket-", PATH_MAX - strlen(user_tmp_dir) );
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(user_tmp_dir));
+ user_tmp_dir[ PATH_MAX ] = '\0';
+
+ if (!kde_home || !kde_home[0])
+ {
+ kde_home = "~/.kde/";
+ }
+
+ if (kde_home[0] == '~')
+ {
+ if (uid == 0)
+ {
+ home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root";
+ }
+ if (!home_dir || !home_dir[0])
+ {
+ arts_fatal("Aborting. $HOME not set!");
+ }
+ if (strlen(home_dir) > (PATH_MAX-100))
+ {
+ arts_fatal("Aborting. Home directory path too long!");
+ }
+ kde_home++;
+ strncpy(kde_tmp_dir, home_dir, PATH_MAX);
+ kde_tmp_dir[ PATH_MAX ] = '\0';
+ }
+ strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir));
+
+ /** Strip trailing '/' **/
+ if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/')
+ kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0;
+
+ result = stat(kde_tmp_dir, &stat_buf);
+ if (result == -1)
+ {
+ return 0;
+ }
+
+ strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir));
+ if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0)
+ {
+ arts_fatal("Aborting. Could not determine hostname or hostname too long.");
+ }
+ kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0';
+
+ result = lstat(kde_tmp_dir, &stat_buf);
+ if ((result == 0) && (S_ISDIR(stat_buf.st_mode)))
+ {
+ /* $KDEHOME/socket-$HOSTNAME is a normal directory. Do nothing. */
+ tmp_buf = (char *) malloc(PATH_MAX+1);
+ if (!tmp_buf)
+ return 0;
+
+ strncpy(tmp_buf, kde_tmp_dir, PATH_MAX);
+ tmp_buf[ PATH_MAX ] = '\0';
+
+ return tmp_buf;
+ }
+
+ if ((result == -1) && (errno == ENOENT))
+ {
+ // Link mising...
+ return 0;
+ }
+ if ((result == -1) || (!S_ISLNK(stat_buf.st_mode)))
+ {
+ arts_warning("Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir);
+ return 0;
+ }
+ tmp_buf = (char *) malloc(PATH_MAX+1);
+ if (!tmp_buf)
+ return 0;
+
+ /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
+ result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX);
+ if (result == -1)
+ {
+ arts_warning("Error: \"%s\" could not be read.\n", kde_tmp_dir);
+ free(tmp_buf);
+ return 0;
+ }
+ tmp_buf[result] = '\0';
+// printf("Link points to \"%s\"\n", tmp_buf);
+ if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0)
+ {
+ arts_warning("Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir);
+ free(tmp_buf);
+ return 0;
+ }
+ result = check_tmp_dir(tmp_buf);
+ if (result == 0) return tmp_buf; /* Success */
+
+ free(tmp_buf);
+ return 0;
+}
+
+/* blatant and literal copy from lnusertemp to avoid kdelibs dependency */
+/* Copyright (c) 2000 Waldo Bastian <bastian@kde.org>, released under LGPL */
+
+static
+int create_link(const char *file, const char *tmp_dir)
+{
+ int result;
+ result = check_tmp_dir(tmp_dir);
+ if (result)
+ {
+ return result;
+ }
+ result = symlink(tmp_dir, file);
+ if (result == -1)
+ {
+ fprintf(stderr, "Error: Can not create link from \"%s\" to \"%s\"\n", file, tmp_dir);
+ return 1;
+ }
+ printf("Created link from \"%s\" to \"%s\"\n", file, tmp_dir);
+ return 0;
+}
+
+
+static
+int build_link(const char *tmp_prefix, const char *kde_prefix)
+{
+ struct passwd *pw_ent;
+ char kde_tmp_dir[PATH_MAX+1];
+ char user_tmp_dir[PATH_MAX+1];
+ char tmp_buf[PATH_MAX+1];
+ int uid = getuid();
+ const char *home_dir = getenv("HOME");
+ const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME");
+ int result;
+ struct stat stat_buf;
+
+ kde_tmp_dir[0] = 0;
+
+ pw_ent = getpwuid(uid);
+ if (!pw_ent)
+ {
+ fprintf(stderr, "Error: Can not find password entry for uid %d.\n", getuid());
+ return 1;
+ }
+
+ strncpy(user_tmp_dir, tmp_prefix, PATH_MAX);
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(tmp_prefix));
+
+ if (!kde_home || !kde_home[0])
+ {
+ kde_home = "~/.kde/";
+ }
+
+ if (kde_home[0] == '~')
+ {
+ if (uid == 0)
+ {
+ home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root";
+ }
+ if (!home_dir || !home_dir[0])
+ {
+ fprintf(stderr, "Aborting. $HOME not set!");
+ exit(255);
+ }
+ if (strlen(home_dir) > (PATH_MAX-100))
+ {
+ fprintf(stderr, "Aborting. Home directory path too long!");
+ exit(255);
+ }
+ kde_home++;
+ strncpy(kde_tmp_dir, home_dir, PATH_MAX);
+ kde_tmp_dir[ PATH_MAX ] = '\0';
+ }
+ strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir));
+
+ /** Strip trailing '/' **/
+ if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/')
+ kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0;
+
+ result = stat(kde_tmp_dir, &stat_buf);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ result = mkdir(kde_tmp_dir, 0700);
+ }
+ if (result == -1)
+ {
+ return 1;
+ }
+
+ strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir));
+ if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0)
+ {
+ perror("Aborting. Could not determine hostname: ");
+ exit(255);
+ }
+ kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0';
+
+ result = lstat(kde_tmp_dir, &stat_buf);
+ if ((result == 0) && (S_ISDIR(stat_buf.st_mode)))
+ {
+ /* $KDEHOME/tmp is a normal directory. Do nothing. */
+ printf("Directory \"%s\" already exists.\n", kde_tmp_dir);
+ return 0;
+ }
+ if ((result == -1) && (errno == ENOENT))
+ {
+ printf("Creating link %s.\n", kde_tmp_dir);
+ result = create_link(kde_tmp_dir, user_tmp_dir);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+ }
+ if ((result == -1) || (!S_ISLNK(stat_buf.st_mode)))
+ {
+ fprintf(stderr, "Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir);
+ return 1;
+ }
+ /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
+ result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX);
+ if (result == -1)
+ {
+ fprintf(stderr, "Error: \"%s\" could not be read.\n", kde_tmp_dir);
+ return 1;
+ }
+ tmp_buf[result] = '\0';
+ printf("Link points to \"%s\"\n", tmp_buf);
+ if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0)
+ {
+ fprintf(stderr, "Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir);
+ unlink(kde_tmp_dir);
+ printf("Creating link %s.\n", kde_tmp_dir);
+ result = create_link(kde_tmp_dir, user_tmp_dir);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+ return 1;
+ }
+ result = check_tmp_dir(tmp_buf);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+}
+
+string MCOPUtils::createFilePath(string name)
+{
+ static char *mcop_dir = 0;
+ if (!mcop_dir)
+ {
+ mcop_dir = locate_mcop_dir();
+ }
+ if (!mcop_dir)
+ {
+
+ const char *tmp = 0;
+ tmp = getenv("KDETMP");
+ if (!tmp || !tmp[0])
+ tmp = getenv("TMPDIR");
+ if (!tmp || !tmp[0])
+ tmp = "/tmp";
+
+ char tmp_prefix[PATH_MAX+1];
+ strcpy(tmp_prefix, tmp);
+ strcat(tmp_prefix, "/ksocket-");
+
+ build_link(tmp_prefix, "/socket-");
+ mcop_dir = locate_mcop_dir();
+ }
+ if (!mcop_dir)
+ {
+ arts_fatal("can't create mcop directory");
+ }
+ string tmpdir = mcop_dir;
+ return tmpdir+"/"+name;
+}
+
+/*
+ * try to figure out full hostname - this is important as every client which
+ * tries to connect objects located here will need to be able to resolve that
+ * correctly
+ */
+string MCOPUtils::getFullHostname()
+{
+ char buffer[1024];
+ string result;
+ struct hostent *hp;
+
+ if(gethostname(buffer,1024) == 0) {
+ buffer[1023] = '\0';
+ result = buffer;
+ } else
+ return "localhost";
+
+ /*
+ * if gethostname() isn't a FQDN (guess that by checking whether it
+ * contains a dot), try to look it up to ensure it is
+ */
+ if(result.find('.') == string::npos && (hp = gethostbyname(buffer)) != 0)
+ result = hp->h_name;
+
+ return result;
+}
+
+string MCOPUtils::readConfigEntry(const string& key, const string& defaultValue)
+{
+ const char *home = getenv("HOME");
+ if(home)
+ {
+ string rcname = home + string("/.mcoprc");
+
+ MCOPConfig config(rcname);
+ return config.readEntry(key,defaultValue);
+ }
+ return defaultValue;
+}
+
+/** IID generation **/
+
+unsigned long MCOPUtils::makeIID(const string& interfaceName)
+{
+ static map<string, unsigned long> *iidmapobj = 0;
+ static unsigned long nextiid = 1;
+
+ if(!iidmapobj) iidmapobj = new map<string,unsigned long>;
+
+ map<string,unsigned long>& iidmap = *iidmapobj;
+
+ if(iidmap.find(interfaceName) == iidmap.end()) {
+ iidmap[interfaceName] = nextiid++;
+ return nextiid-1; // no need to lookup in the map thrice
+ }
+
+ return iidmap[interfaceName];
+}
+
+static vector<string> *readPath(const string& name, const string& defaultValue)
+{
+ vector<string> *result = 0;
+ const char *home = getenv("HOME");
+
+ if(home)
+ {
+ string rcname = home + string("/.mcoprc");
+
+ MCOPConfig config(rcname);
+ result = config.readListEntry(name);
+ }
+ if(!result)
+ result = new vector<string>;
+ if(result->empty())
+ result->push_back(defaultValue);
+
+ return result;
+}
+
+const vector<string> *MCOPUtils::extensionPath()
+{
+ static vector<string> *result = 0;
+
+ if(!result) result = readPath("ExtensionPath", EXTENSION_DIR);
+ return result;
+}
+
+const vector<string> *MCOPUtils::traderPath()
+{
+ static vector<string> *result = 0;
+
+ if(!result)
+ {
+ result = readPath("TraderPath", TRADER_DIR);
+
+ const char *home = getenv("HOME");
+ if(home) result->push_back(home + string("/.mcop/trader-cache"));
+ }
+ return result;
+}
+
+string MCOPUtils::mcopDirectory()
+{
+ static bool initialized = false;
+ static string mcopDirectory;
+
+ if(initialized)
+ return mcopDirectory;
+ initialized = true;
+
+ const char *home = getenv("HOME");
+ arts_return_val_if_fail(home != 0, "");
+
+ mcopDirectory = home + string("/.mcop");
+
+ mkdir(home,0755);
+ if(mkdir(mcopDirectory.c_str(),0755) != 0)
+ {
+ string why = strerror(errno);
+
+ struct stat st;
+ stat(mcopDirectory.c_str(),&st);
+ if(!S_ISDIR(st.st_mode))
+ {
+ arts_warning("can't create directory %s (%s)",
+ mcopDirectory.c_str(), why.c_str());
+
+ mcopDirectory = "";
+ }
+ }
+ return mcopDirectory;
+}
+
+bool MCOPUtils::tokenize(const string& line, string& key,vector<string>& values)
+{
+ string value;
+ enum { sKey, sValue, sValueQuoted, sValueQuotedEscaped, sBad } state;
+
+ state = sKey;
+ for(string::const_iterator i = line.begin(); i != line.end(); i++)
+ {
+ char c = *i;
+ unsigned char uc = static_cast<unsigned char>(c);
+
+ arts_assert(c != '\n');
+
+ if(state == sKey)
+ {
+ if(c == ' ' || c == '\t')
+ ; // ignore
+ else if(isalnum(c))
+ key += c;
+ else if(c == '=')
+ state = sValue;
+ else
+ state = sBad;
+ }
+ else if(state == sValue)
+ {
+ if(c == ' ' || c == '\t')
+ ; // ignore
+ else if(c == '"')
+ state = sValueQuoted;
+ else if(c == ',')
+ {
+ values.push_back(value);
+ value = "";
+ }
+ else if(uc > 32 && uc < 128)
+ value += c;
+ else
+ state = sBad;
+ }
+ else if(state == sValueQuoted)
+ {
+ if(c == '"')
+ state = sValue;
+ else if(c == '\\')
+ state = sValueQuotedEscaped;
+ else
+ value += c;
+ }
+ else if(state == sValueQuotedEscaped)
+ {
+ value += c;
+ state = sValueQuoted;
+ }
+ }
+ if(state == sValue)
+ values.push_back(value);
+
+ return(state != sBad);
+}
diff --git a/mcop/mcoputils.h b/mcop/mcoputils.h
new file mode 100644
index 0000000..ecfe9b0
--- /dev/null
+++ b/mcop/mcoputils.h
@@ -0,0 +1,97 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): MCOPUtils
+ *
+ * Collection class for all kinds of utility functions. BC, since never
+ * instanciated.
+ */
+
+#ifndef MCOPUTILS_H
+#define MCOPUTILS_H
+
+#include <string>
+#include <vector>
+
+#include "arts_export.h"
+
+namespace Arts {
+
+class ARTS_EXPORT MCOPUtils {
+public:
+ /**
+ * Returns the full pathname to a file in the mcop directory which
+ * is called "name". It will also care that no other characters than
+ * A-Z,a-z,0-9,-,_ occur.
+ *
+ * The result is something like /tmp/mcop-<username>/name, the directory
+ * will be created when necessary.
+ */
+ static std::string createFilePath(std::string name);
+
+ /**
+ * Returns the fully qualified hostname, such as "www.kde.org" (of course
+ * this may fail due to misconfiguration).
+ *
+ * The result is "localhost" if nothing at all can be found out.
+ */
+ static std::string getFullHostname();
+
+ /**
+ * Returns configuration values from .mcoprc
+ */
+ static std::string readConfigEntry(const std::string& key,
+ const std::string& defaultValue = "");
+
+ /**
+ * Makes an interface ID from string - if the given string is already
+ * known, the returned IID will be the one returned last time. If not,
+ * a new IID is generated
+ */
+ static unsigned long makeIID(const std::string& interfaceName);
+
+ /**
+ * Returns the directories for the trader to look into
+ */
+ static const std::vector<std::string> *traderPath();
+
+ /**
+ * Returns the directories from where extensions can be loaded
+ */
+ static const std::vector<std::string> *extensionPath();
+
+ /**
+ * Returns the full path of the ~/.mcop directory
+ */
+ static std::string mcopDirectory();
+
+ /**
+ * Tokenization of a key = value1, "value 2", "value III" line into the key
+ * and the values.
+ */
+ static bool tokenize(const std::string& line, std::string& key,
+ std::vector<std::string>& values);
+};
+
+}
+#endif /* MCOPUTILS_H */
diff --git a/mcop/md5.c b/mcop/md5.c
new file mode 100644
index 0000000..782ce30
--- /dev/null
+++ b/mcop/md5.c
@@ -0,0 +1,197 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "md5.h"
+
+/*
+ * this is okay for all architectures with int = 32bit, so IMHO all
+ * current architectures supported by KDE.
+ */
+typedef unsigned int uint32;
+
+static void MD5Transform(uint32 buf[4], uint32 in[MD5_BINARY_LEN]);
+
+void arts_md5sum(unsigned char *message, long len, char *md5sum)
+{
+ long finalsize = len+1; /* in bytes */
+ int i = 0, j = 0;
+ unsigned char w = '\0';
+ uint32 buffer[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
+ uint32 in[MD5_BINARY_LEN];
+
+ while((finalsize & 63) != 56) finalsize++;
+ finalsize += 8;
+
+ for( i=0, j=0;i<finalsize;i++)
+ {
+ if(i < len) {
+ w = message[i];
+ } else if(i == len) {
+ w = 0x80;
+ } else if((finalsize-i > 8) || (finalsize-i <= 4)) {
+ w = 0;
+ } else {
+ /* well, the length thing encoded in here will only
+ work until 2^32 bits (though md5 would support 2^64
+ bits) */
+ w = ((len*8) >> ((i+8-finalsize)*8)) & 0xff;
+ }
+ switch(i & 3) {
+ case 0: in[j] = w;
+ break;
+ case 1: in[j] |= w << 8;
+ break;
+ case 2: in[j] |= w << 16;
+ break;
+ case 3: in[j] |= w << 24;
+ j++;
+ if(j == MD5_BINARY_LEN) {
+ MD5Transform(buffer,in);
+ j = 0;
+ }
+ break;
+ }
+ }
+
+ for( i=0, j=0;j<4;j++)
+ {
+ md5sum[i++] = buffer[j] & 0xff;
+ md5sum[i++] = (buffer[j] >> 8) & 0xff;
+ md5sum[i++] = (buffer[j] >> 16) & 0xff;
+ md5sum[i++] = (buffer[j] >> 24) & 0xff;
+ }
+}
+
+/*
+ * I used the central part of Colin Plumb's public domain MD5 implementation
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ */
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(uint32 buf[4], uint32 in[MD5_BINARY_LEN])
+{
+ uint32 a = buf[0];
+ uint32 b = buf[1];
+ uint32 c = buf[2];
+ uint32 d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
diff --git a/mcop/md5.h b/mcop/md5.h
new file mode 100644
index 0000000..5670d7e
--- /dev/null
+++ b/mcop/md5.h
@@ -0,0 +1,45 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): arts_md5sum
+ *
+ * No binary compatibility guaranteed (part of Dispatcher's security model).
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define MD5_BINARY_LEN 16
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+void arts_md5sum(unsigned char *message, long len, char *md5sum);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/mcop/md5auth.cc b/mcop/md5auth.cc
new file mode 100644
index 0000000..1e6fe1a
--- /dev/null
+++ b/mcop/md5auth.cc
@@ -0,0 +1,213 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#elif HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+#include "md5.h"
+#include "md5auth.h"
+#include "debug.h"
+
+// MD5_BINARY_LEN is defined in md5.h
+#define MD5_COOKIE_LEN (MD5_BINARY_LEN*2)
+#define MD5_MANGLE_LEN (MD5_COOKIE_LEN*2)
+
+
+
+struct random_info {
+ struct timeval tv;
+ int pid;
+ struct utsname un;
+ char dev_urandom[MD5_BINARY_LEN];
+ char seed[MD5_COOKIE_LEN+1];
+ int number;
+};
+
+static char md5_seed[MD5_COOKIE_LEN+1];
+static char md5_cookie[MD5_COOKIE_LEN+1];
+static int md5_init = 0;
+static int md5_random_cookie_number = 0;
+
+static char *md5_to_ascii_overwrite(char *md5)
+{
+ char outascii[MD5_COOKIE_LEN+1];
+ char *result;
+ int i;
+
+ // convert to readable text
+ for(i = 0; i < MD5_BINARY_LEN; i++) {
+ sprintf(&outascii[i*2],"%02x",md5[i] & 0xff);
+ }
+ outascii[MD5_COOKIE_LEN] = 0;
+ result = strdup(outascii);
+
+ // try to zero out traces
+ memset(md5,0,MD5_BINARY_LEN);
+ memset(outascii,0,MD5_COOKIE_LEN);
+
+ // well, here it is
+ return result;
+}
+
+char *arts_md5_auth_mangle(const char *cookie)
+{
+ char mangle[MD5_MANGLE_LEN+1];
+ char out[MD5_BINARY_LEN];
+ assert(md5_init);
+
+ // concat the two cookies and mangle them to a new one
+ strncpy(mangle,md5_cookie, MD5_COOKIE_LEN);
+ mangle[MD5_COOKIE_LEN] = 0;
+ strncat(mangle,cookie, MD5_COOKIE_LEN);
+ mangle[MD5_MANGLE_LEN] = 0;
+ arts_md5sum((unsigned char *)mangle,MD5_MANGLE_LEN,out);
+
+ // try to zero out traces
+ memset(mangle,0,MD5_MANGLE_LEN);
+
+ return md5_to_ascii_overwrite(out);
+}
+
+char *arts_md5_auth_mkcookie()
+{
+ struct random_info r;
+ char out[MD5_BINARY_LEN];
+ int rndfd;
+
+ memset(&r,0,sizeof(struct random_info));
+
+ // collect some "random" system information
+ gettimeofday(&r.tv,0);
+ r.pid = getpid();
+ uname(&r.un);
+
+ // linux random device ; if that works, we have good random anyway, the
+ // above are just helpers for the case that it doesn't
+ rndfd = open("/dev/urandom",O_RDONLY);
+ if(rndfd != -1)
+ {
+ read(rndfd,r.dev_urandom,MD5_BINARY_LEN);
+ close(rndfd);
+ }
+
+ // ensure that two cookies that are requested very shortly after each
+ // other (so that it looks like "at the same time") won't be the same
+ r.number = ++md5_random_cookie_number;
+
+ // this is some seed from a file which is updated sometimes with a
+ // new "arts_md5_auth_mkcookie()" after initialization
+ strncpy(r.seed,md5_seed,MD5_COOKIE_LEN);
+
+ // build hash value of all information
+ arts_md5sum((unsigned char *)&r,sizeof(struct random_info),out);
+
+ // zero out traces and return
+ memset(&r,0,sizeof(struct random_info));
+ return md5_to_ascii_overwrite(out);
+}
+
+const char *arts_md5_auth_cookie()
+{
+ assert(md5_init);
+ return md5_cookie;
+}
+
+static int md5_load_cookie(const char *filename, char *cookie)
+{
+ int fd = open(filename,O_RDONLY);
+ int i;
+
+ if(fd != -1) {
+ struct stat st;
+ for(i=0;i<5;i++) {
+ fstat(fd,&st);
+ if(st.st_size == MD5_COOKIE_LEN) {
+ lseek(fd, 0, SEEK_SET);
+ if(read(fd,cookie,MD5_COOKIE_LEN) == MD5_COOKIE_LEN)
+ {
+ cookie[MD5_COOKIE_LEN] = 0;
+ close(fd);
+ return 1;
+ }
+ }
+ arts_warning("MCOP: "
+ "authority file has wrong size (just being written?)");
+ sleep(1);
+ }
+ }
+ return 0;
+}
+
+void arts_md5_auth_init_seed(const char *seedname)
+{
+ // don't care if it works - no harm is being done if it doesn't
+ md5_load_cookie(seedname,md5_seed);
+
+ /*
+ * maxage ensures that not everybody will try to update the seed
+ * at the same time, while it will take at most 5 hours between
+ * updates (if there are any initialization calls)
+ */
+ struct stat st;
+ int maxage = 300 + (getpid() & 0xfff)*4;
+ int lstat_result = lstat(seedname,&st);
+ if(lstat_result != 0 || (time(0) - st.st_mtime) > maxage)
+ {
+ int fd = open(seedname,O_TRUNC|O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
+ if(fd != -1) {
+ char *cookie = arts_md5_auth_mkcookie();
+ write(fd,cookie,strlen(cookie));
+ memset(cookie,0,strlen(cookie));
+ free(cookie);
+ close(fd);
+ }
+ }
+}
+
+bool arts_md5_auth_set_cookie(const char *cookie)
+{
+ if(strlen(cookie) != MD5_COOKIE_LEN)
+ return false;
+
+ strncpy(md5_cookie,cookie,MD5_COOKIE_LEN);
+ md5_cookie[MD5_COOKIE_LEN] = 0;
+ md5_init = 1;
+ return true;
+}
diff --git a/mcop/md5auth.h b/mcop/md5auth.h
new file mode 100644
index 0000000..c0197ff
--- /dev/null
+++ b/mcop/md5auth.h
@@ -0,0 +1,105 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): arts_md5_*
+ *
+ * No guarantees - do not use.
+ */
+
+#ifndef MD5_AUTH_H
+#define MD5_AUTH_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * How that MD5 auth stuff is supposed to work:
+ *
+ * Initialization:
+ *
+ * Your service calls arts_md5_auth_set_cookie and passes a "secret cookie".
+ * Lets call the "secret cookie" S. As soon as a client wants to connect,
+ * he needs the same secret cookie S.
+ *
+ * Of course the user can copy the "secret cookie" using a secure connection
+ * to any computer from which he wants to access the service.
+ *
+ * 0. SERVER: if no common secret cookie is available, generate a random
+ * cookie and keep it secret - ensure (through secure connections)
+ * that the client gets the secret cookie
+ *
+ * 1. SERVER: generate a new (random) cookie R
+ * 2. SERVER: send it to the client
+ * 3. CLIENT: (should get/have the "secret cookie" S from somewhere secure)
+ * 4. CLIENT: mangle the cookies R and S to a mangled cookie M
+ * 5. CLIENT: send M to the server
+ * 6. SERVER: verify that mangling R and S gives just the same thing as the
+ * cookie M received from the client. If yes, authentication is successful.
+ *
+ * The advantage of that protocol is, that even somebody who can read all
+ * network traffic can't find out the secret cookie S, as that is never
+ * transferred as plaintext.
+ */
+
+/*
+ * generates a new random cookie R (also be used to generate secret cookies)
+ * => free it when you don't need it any more
+ */
+char *arts_md5_auth_mkcookie();
+
+/*
+ * mangles a "secret cookie" with another "random cookie"
+ * => free result when done
+ */
+char *arts_md5_auth_mangle(const char *random);
+
+/*
+ * using arts_md5_auth_init_seed, the security will be improved by loading a
+ * randomseed from that file, and (if it has no recent date) saving a new
+ * seed to it - this will ensure that the arts_md5_auth_mkcookie() routine will
+ * return a really unpredictable result (as it depends on all processes that
+ * ever have touched the seed)
+ */
+void arts_md5_auth_init_seed(const char *seedname);
+
+/*
+ * use this routine to set the "secret cookie" - you can pass a newly
+ * generated random cookie here, or the secret cookie you got from
+ * elsewhere (to communicate with others)
+ *
+ * returns true if success (good cookie), false if setting the cookie failed
+ */
+bool arts_md5_auth_set_cookie(const char *cookie);
+
+/*
+ * returns "secret cookie"
+ */
+const char *arts_md5_auth_cookie();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/mcop/namedstore.h b/mcop/namedstore.h
new file mode 100644
index 0000000..e5fad59
--- /dev/null
+++ b/mcop/namedstore.h
@@ -0,0 +1,125 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_NAMEDSTORE_H
+#define ARTS_NAMEDSTORE_H
+
+#include <string>
+#include <list>
+#include <vector>
+#include "stdio.h"
+
+/*
+ * BC - Status (2002-03-08): NamedStore
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of object.cc and not
+ * to be used elsewhere.
+ */
+
+namespace Arts {
+
+/**
+ * -- internal class --
+ *
+ * this stores key-value pairs, where key is a string which is kept unique
+ */
+template<class T>
+class NamedStore
+{
+private:
+ class Element {
+ public:
+ T t;
+ std::string name;
+
+ Element(const T& t, const std::string& name) :t(t), name(name) { }
+ };
+ typedef std::list<Element> Element_list;
+ Element_list elements;
+
+public:
+ bool get(const std::string& name, T& result)
+ {
+ typename Element_list::iterator i;
+ for(i = elements.begin(); i != elements.end(); i++)
+ {
+ if(i->name == name)
+ {
+ result = i->t;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ bool remove(const std::string& name)
+ {
+ typename Element_list::iterator i;
+ for(i = elements.begin(); i != elements.end(); i++)
+ {
+ if(i->name == name)
+ {
+ elements.erase(i);
+ return true;
+ }
+ }
+ return false;
+ }
+ std::vector<std::string> *contents()
+ {
+ std::vector<std::string> *result = new std::vector<std::string>;
+
+ typename Element_list::iterator i;
+ for(i = elements.begin(); i != elements.end(); i++)
+ result->push_back(i->name);
+
+ return result;
+ }
+ std::string put(const std::string& name, const T& t)
+ {
+ std::string xname = name;
+ int append = 1;
+
+ for(;;)
+ {
+ typename Element_list::iterator i;
+
+ i = elements.begin();
+ while(i != elements.end() && i->name != xname)
+ i++;
+
+ if(i == elements.end())
+ {
+ elements.push_back(Element(t,xname));
+ return xname;
+ }
+
+ char buffer[1024];
+ sprintf(buffer,"%d",append++);
+ xname = name + std::string(buffer);
+ }
+ }
+};
+
+}
+#endif /* ARTS_NAMEDSTORE_H */
diff --git a/mcop/notification.cc b/mcop/notification.cc
new file mode 100644
index 0000000..3fd70d1
--- /dev/null
+++ b/mcop/notification.cc
@@ -0,0 +1,101 @@
+ /*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "notification.h"
+#include "debug.h"
+#include "dispatcher.h"
+
+using namespace Arts;
+
+void NotificationClient::notify(const Notification&)
+{
+}
+
+NotificationManager::NotificationManager()
+{
+ arts_assert(!instance);
+ instance = this;
+}
+
+NotificationManager::~NotificationManager()
+{
+ arts_assert(instance);
+ instance = 0;
+}
+
+void NotificationManager::send(Notification wm)
+{
+ if (todo.empty()) {
+ // HACK: in order to not add a virtual function to IOManager we're calling addTimer with
+ // magic values. This call tells the ioManager that notifications are pending and
+ // NotificationManager::run() should get called soon.
+ Arts::Dispatcher::the()->ioManager()->addTimer(-1, 0);
+ }
+ todo.push(wm);
+}
+
+bool NotificationManager::run()
+{
+ if(todo.empty()) return false;
+
+ while(!todo.empty())
+ {
+ Notification wm = todo.front();
+ todo.pop();
+
+ /*
+ * we'll copy and remove the notification first, to be sure that
+ * nothing bad happens to it if we rebuild "todo" (for instance in
+ * removeClient)
+ */
+ wm.receiver->notify(wm);
+ }
+ return true;
+}
+
+void NotificationManager::removeClient(NotificationClient *client)
+{
+ std::queue<Notification> newTodo;
+
+ while(!todo.empty())
+ {
+ const Notification& n = todo.front();
+ if(n.receiver != client)
+ newTodo.push(n);
+ else
+ {
+ arts_debug("NotificationManager: removing one notification");
+ NotificationDestroyFunction destroy =
+ (NotificationDestroyFunction)n.internal;
+ if(destroy) destroy(n);
+ }
+ todo.pop();
+ }
+ todo = newTodo;
+}
+
+void Notification::setDestroy(NotificationDestroyFunction destroy)
+{
+ internal = (void*)destroy;
+}
+
+NotificationManager *NotificationManager::instance = 0;
diff --git a/mcop/notification.h b/mcop/notification.h
new file mode 100644
index 0000000..6a8582f
--- /dev/null
+++ b/mcop/notification.h
@@ -0,0 +1,87 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef NOTIFICATION_H
+#define NOTIFICATION_H
+
+#include <queue>
+#include "arts_export.h"
+
+namespace Arts {
+
+/*
+ * BC - Status (2002-03-08): Notification, NotificationClient,
+ * NotificationManager
+ *
+ * All need to be kept BC, NotificationManager with usual d ptr.
+ *
+ * Notifications have to be FAST. Currently, they use ID, data & receiver.
+ * However, there may be future extensions. For this, one more internal
+ * field is provided. Set it to ZERO currently when sending notifications.
+ */
+
+struct Notification;
+typedef void (*NotificationDestroyFunction)(const Notification& n);
+
+struct Notification {
+ class NotificationClient *receiver;
+ int ID;
+ void *data;
+ void *internal; /* handle with care, equivalent to private d ptr */
+
+ void setDestroy(NotificationDestroyFunction destroy);
+};
+
+class ARTS_EXPORT NotificationClient {
+public:
+ virtual void notify(const Notification& wm);
+};
+
+class NotificationManagerPrivate;
+class ARTS_EXPORT NotificationManager {
+private:
+ NotificationManagerPrivate *d; // unused
+protected:
+ std::queue<Notification> todo;
+ static NotificationManager *instance;
+
+public:
+ NotificationManager();
+ ~NotificationManager();
+
+ static inline NotificationManager *the()
+ {
+ return instance;
+ }
+ void send(Notification wm);
+ inline bool pending()
+ {
+ return !todo.empty();
+ }
+ bool run();
+ void removeClient(NotificationClient *client);
+
+};
+
+}
+
+#endif /* NOTIFICATION_H */
diff --git a/mcop/object.cc b/mcop/object.cc
new file mode 100644
index 0000000..9f01912
--- /dev/null
+++ b/mcop/object.cc
@@ -0,0 +1,1528 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "object.h"
+#include "dispatcher.h"
+#include "flowsystem.h"
+#include "weakreference.h"
+#include "namedstore.h"
+#include "debug.h"
+#include "anyref.h"
+#include <stdio.h>
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+ class AttributeSlotBind;
+}
+
+class Arts::ObjectInternalData {
+public:
+ struct MethodTableEntry {
+ union {
+ DispatchFunction dispatcher;
+ OnewayDispatchFunction onewayDispatcher;
+ DynamicDispatchFunction dynamicDispatcher;
+ } dispFunc;
+ enum { dfNormal, dfOneway, dfDynamic } dispatchStyle;
+ void *object;
+ MethodDef methodDef;
+ };
+
+ list<WeakReferenceBase *> weakReferences;
+ NamedStore<Arts::Object> children;
+ bool stubForLocalObject;
+
+ // for _skel classes only:
+ bool methodTableInit;
+ std::vector<MethodTableEntry> methodTable;
+ list<AttributeSlotBind *> attributeSlots;
+};
+
+struct Object_base::ObjectStreamInfo {
+ string name;
+ long flags;
+ void *ptr;
+};
+
+/*****************************************************************************/
+/* the following methods/classes are necessary for attribute notifications */
+/*****************************************************************************/
+
+namespace Arts {
+ class AttributeDataPacket : public GenericDataPacket {
+ public:
+ Buffer b;
+ AttributeDataPacket(GenericDataChannel *channel)
+ : GenericDataPacket(channel)
+ {
+ size = 0;
+ b.writeLong(0);
+ }
+ void add(const AnyConstRef& r)
+ {
+ r.write(&b);
+ b.patchLong(0,++size);
+ }
+
+ void ensureCapacity(int)
+ {
+ }
+ void read(Buffer& stream)
+ {
+ vector<mcopbyte> all;
+ size = stream.readLong();
+ b.patchLong(0,size);
+ stream.read(all,stream.remaining());
+ b.write(all);
+ }
+ void write(Buffer& stream)
+ {
+ vector<mcopbyte> all;
+ b.rewind();
+ b.read(all,b.remaining());
+ stream.write(all);
+ }
+ };
+ class AttributeSlotBind : public GenericAsyncStream {
+ public:
+ GenericDataPacket *createPacket(int)
+ {
+ return allocPacket();
+ }
+ AttributeDataPacket *allocPacket()
+ {
+ return new AttributeDataPacket(channel);
+ }
+
+ void freePacket(GenericDataPacket *packet)
+ {
+ delete packet;
+ }
+
+ GenericAsyncStream *createNewStream()
+ {
+ return new AttributeSlotBind();
+ }
+
+ virtual ~AttributeSlotBind()
+ {
+ }
+
+ string method;
+ bool output;
+ };
+}
+
+bool Object_skel::_initAttribute(const AttributeDef& attribute)
+{
+ long flags = attribute.flags;
+
+ if(flags & attributeAttribute)
+ {
+ flags |= attributeStream | streamAsync;
+ flags &= ~attributeAttribute;
+ }
+ else
+ {
+ arts_warning("attribute init on stream %s", attribute.name.c_str());
+ return false;
+ }
+
+ list<AttributeSlotBind *>::iterator i;
+ for(i = _internalData->attributeSlots.begin();
+ i != _internalData->attributeSlots.end(); i++)
+ {
+ AttributeSlotBind *b = *i;
+ if(b->method == "_set_"+attribute.name
+ || b->method == attribute.name + "_changed")
+ {
+ arts_warning("double attribute init %s",b->method.c_str());
+ return false;
+ }
+ }
+ if(flags & streamIn)
+ {
+ AttributeSlotBind *b = new AttributeSlotBind();
+ b->output = false;
+ b->method = "_set_"+attribute.name;
+ _internalData->attributeSlots.push_back(b);
+
+ _scheduleNode->initStream(attribute.name, b, flags & (~streamOut));
+ }
+ if(flags & streamOut)
+ {
+ string changed = attribute.name + "_changed";
+ AttributeSlotBind *b = new AttributeSlotBind();
+ b->output = true;
+ b->method = changed;
+ _internalData->attributeSlots.push_back(b);
+
+ _scheduleNode->initStream(changed, b, flags & (~streamIn));
+ }
+ return true;
+}
+
+void Object_skel::_defaultNotify(const Notification& notification)
+{
+ list<AttributeSlotBind *>::iterator i;
+ list<AttributeSlotBind *>& slots = _internalData->attributeSlots;
+
+ for(i = slots.begin(); i != slots.end(); i++)
+ {
+ if((*i)->notifyID() == notification.ID)
+ {
+ GenericDataPacket *dp = (GenericDataPacket *)notification.data;
+ Buffer params;
+
+ dp->write(params);
+
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+
+ typedef ObjectInternalData::MethodTableEntry MTE;
+ vector<MTE>::iterator mti;
+
+ for(mti = _internalData->methodTable.begin();
+ mti != _internalData->methodTable.end(); mti++)
+ {
+ if(mti->methodDef.name == (*i)->method)
+ {
+ Buffer result;
+
+ long count = params.readLong();
+ while(params.remaining())
+ {
+ if(mti->dispatchStyle == MTE::dfNormal)
+ {
+ mti->dispFunc.dispatcher(mti->object, &params, &result);
+ }
+ else if(mti->dispatchStyle == MTE::dfDynamic)
+ {
+ long methodID;
+ methodID = mti - _internalData->methodTable.begin();
+ mti->dispFunc.dynamicDispatcher(mti->object, methodID,
+ &params, &result);
+ }
+ else
+ {
+ arts_assert(0);
+ }
+ count--;
+ }
+ arts_assert(count == 0);
+ }
+ }
+ dp->processed();
+ }
+ }
+}
+
+void Object_skel::notify(const Notification& notification)
+{
+ _copy();
+ _defaultNotify(notification);
+ _release();
+}
+
+/* for simplicity and efficiency, enums are emitted as normal "long" values,
+ * so that finding out/using the enum type via value.type() is not be possible
+ */
+void Object_skel::_emit_changed(const char *attrib, const AnyConstRef& value)
+{
+ list<AttributeSlotBind *>::iterator i;
+ list<AttributeSlotBind *>& slots = _internalData->attributeSlots;
+
+ for(i = slots.begin(); i != slots.end(); i++)
+ {
+ if((*i)->method == attrib)
+ {
+ AttributeDataPacket *adp =
+ (AttributeDataPacket *)(*i)->createPacket(1);
+ adp->add(value);
+ adp->send();
+ return;
+ }
+ }
+}
+
+
+bool Object_skel::_generateSlots(const std::string& name,
+ const std::string& interface)
+{
+ InterfaceDef d = _queryInterface(interface);
+ vector<string>::iterator ii;
+ for(ii = d.inheritedInterfaces.begin();
+ ii != d.inheritedInterfaces.end(); ii++)
+ {
+ if(_generateSlots(name, *ii)) return true;
+ }
+
+ vector<AttributeDef>::iterator ai;
+ for(ai = d.attributes.begin(); ai != d.attributes.end(); ai++)
+ {
+ if(ai->flags & attributeAttribute)
+ {
+ if((ai->flags & streamIn && ai->name == name)
+ || (ai->flags & streamOut && ai->name+"_changed" == name))
+ {
+ _initAttribute(*ai);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Object_skel::_QueryInitStreamFunc(Object_skel *skel, const
+ std::string& name)
+{
+ /*
+ * this function
+ *
+ * checks if there is a stream which should be added called <name>,
+ * and returns true if it in fact added a stream, so that requesting
+ * function needs to retry
+ */
+ bool result = skel->_generateSlots(name, skel->_interfaceName());
+ if(!result)
+ {
+ arts_warning("used stream %s on object %s, which doesn't seem to exist",
+ name.c_str(), skel->_interfaceName().c_str());
+ }
+ return result;
+}
+
+/*****************************************************************************/
+
+
+/*
+ * Object: common for every object
+ */
+
+long Object_base::_staticObjectCount = 0;
+
+Object_base::Object_base() : _deleteOk(false), _scheduleNode(0), _nextNotifyID(1),
+ _refCnt(1)
+{
+ _internalData = new Arts::ObjectInternalData();
+ _internalData->stubForLocalObject = false;
+ _staticObjectCount++;
+}
+
+void Object_base::_destroy()
+{
+ _deleteOk = true;
+
+ if(_scheduleNode && !_internalData->stubForLocalObject)
+ {
+ if(_scheduleNode->remoteScheduleNode())
+ {
+ delete _scheduleNode;
+ }
+ else
+ {
+ FlowSystem_impl *fs = Dispatcher::the()->flowSystem();
+ assert(fs);
+
+ fs->removeObject(_scheduleNode);
+ }
+ }
+ delete this;
+}
+
+Object_base::~Object_base()
+{
+ if(!_deleteOk)
+ {
+ arts_fatal("reference counting violation - you may not call delete "
+ "manually - use _release() instead");
+ }
+ assert(_deleteOk);
+
+ /* remove attribute slots */
+ list<AttributeSlotBind *>::iterator ai;
+ for(ai = _internalData->attributeSlots.begin();
+ ai != _internalData->attributeSlots.end(); ai++)
+ {
+ delete (*ai);
+ }
+
+ /* clear stream list */
+ list<ObjectStreamInfo *>::iterator osii;
+ for(osii = _streamList.begin(); osii != _streamList.end(); osii++)
+ delete (*osii);
+
+ /* inform weak references that we don't exist any longer */
+ while(!_internalData->weakReferences.empty())
+ _internalData->weakReferences.front()->release();
+
+ /* inform notification manager that we don't exist any longer */
+ NotificationManager::the()->removeClient(this);
+
+ delete _internalData;
+ _staticObjectCount--;
+}
+
+ScheduleNode *Object_base::_node()
+{
+ if(!_scheduleNode)
+ {
+ switch(_location())
+ {
+ case objectIsLocal:
+ {
+ FlowSystem_impl *fs = Dispatcher::the()->flowSystem();
+ assert(fs);
+ _scheduleNode = fs->addObject(_skel());
+
+ /* init streams */
+
+ list<ObjectStreamInfo *>::iterator osii;
+ for(osii = _streamList.begin(); osii != _streamList.end(); osii++)
+ {
+ _scheduleNode->initStream((*osii)->name,(*osii)->ptr,(*osii)->flags);
+ }
+ _scheduleNode->initStream("QueryInitStreamFunc",
+ (void *)Object_skel::_QueryInitStreamFunc, -1);
+ }
+ break;
+
+ case objectIsRemote:
+ {
+ /*
+ * if we're just a stub to an object that is local inside
+ * this process, then we don't create a new schedule node,
+ * but find the one associated with the implementation
+ *
+ * (this happens for instance for objects implemented as
+ * artsbuilder structures)
+ */
+ if(_internalData->stubForLocalObject)
+ {
+ Dispatcher *disp = Dispatcher::the();
+ Object_skel *localObject;
+
+ localObject = disp->getLocalObject(_stub()->_objectID);
+ arts_assert(localObject);
+
+ _scheduleNode = localObject->_node();
+ localObject->_release();
+ }
+ else
+ {
+ _scheduleNode = new RemoteScheduleNode(_stub());
+ }
+ }
+ break;
+ }
+
+ assert(_scheduleNode);
+ }
+ return _scheduleNode;
+}
+
+bool Object_base::_isEqual(Object_base *object) const
+{
+ return (_internalObjectID == object->_internalObjectID);
+}
+
+void *Object_base::_cast(unsigned long iid)
+{
+ if(iid == Object_base::_IID) return (Object *)this;
+ return 0;
+}
+
+void *Object_base::_cast(const std::string& interface)
+{
+ return _cast(MCOPUtils::makeIID(interface));
+}
+
+bool Object_base::_error()
+{
+ // no error as default ;)
+ return false;
+}
+
+Object_skel *Object_base::_skel()
+{
+ assert(false);
+ return 0;
+}
+
+Object_stub *Object_base::_stub()
+{
+ assert(false);
+ return 0;
+}
+
+Object_stub *Object_stub::_stub()
+{
+ return this;
+}
+
+Object_base::ObjectLocation Object_stub::_location() const
+{
+ return objectIsRemote;
+}
+
+Object_skel *Object_skel::_skel()
+{
+ return this;
+}
+
+Object_base::ObjectLocation Object_skel::_location() const
+{
+ return objectIsLocal;
+}
+
+void Object_skel::_initStream(const string& name, void *ptr, long flags)
+{
+ ObjectStreamInfo *osi = new ObjectStreamInfo;
+ osi->name = name;
+ osi->ptr = ptr;
+ osi->flags = flags;
+ _streamList.push_back(osi);
+}
+
+void Object_base::calculateBlock(unsigned long)
+{
+}
+
+string Object_base::_interfaceName()
+{
+ assert(0); // derived classes *must* override this
+ return "";
+}
+
+Buffer *Object_base::_allocCustomMessage(long /*handlerID*/)
+{
+ assert(0);
+ return 0;
+}
+
+void Object_base::_sendCustomMessage(Buffer *buffer)
+{
+ assert(0);
+ delete buffer;
+}
+
+// Default I/O: nothing at this level, use child virtuals
+vector<std::string> Object_base::_defaultPortsIn() const
+{
+ vector<std::string> ret;
+ return ret;
+}
+vector<std::string> Object_base::_defaultPortsOut() const
+{
+ vector<std::string> ret;
+ return ret;
+}
+
+// Weak References
+
+void Object_base::_addWeakReference(WeakReferenceBase *b)
+{
+ _internalData->weakReferences.push_back(b);
+}
+
+void Object_base::_removeWeakReference(WeakReferenceBase *b)
+{
+ _internalData->weakReferences.remove(b);
+}
+
+/*
+ * Stuff for object skeletons
+ */
+
+Object_skel::Object_skel() :_remoteSendCount(0), _remoteSendUpdated(false)
+{
+ _objectID = Dispatcher::the()->addObject(this);
+ _connection = Dispatcher::the()->loopbackConnection();
+ _internalData->methodTableInit = false;
+
+/* big enough for our header + 0x + needed number of hex characters + ending NULL */
+ char ioid[7 + 2*sizeof(void *)+1];
+ sprintf(ioid,"SKEL:%p",(void *)this);
+ _internalObjectID = ioid;
+}
+
+Object_skel::~Object_skel()
+{
+ Dispatcher::the()->removeObject(_objectID);
+}
+
+// flow system
+
+FlowSystem Object_skel::_flowSystem()
+{
+ FlowSystem_base *fs = Dispatcher::the()->flowSystem();
+ if(fs)
+ return FlowSystem::_from_base(fs->_copy());
+ else
+ return FlowSystem::null();
+}
+
+// reference counting
+
+void Object_skel::_release()
+{
+ arts_return_if_fail(_refCnt > 0);
+
+ _refCnt--;
+ if(_refCnt == 0) _destroy();
+}
+
+void Object_skel::_copyRemote()
+{
+ // cout << "_copyRemote();" << endl;
+
+ _copy();
+ _remoteSendCount++;
+ _remoteSendUpdated = true;
+}
+
+void Object_skel::_releaseRemote()
+{
+ //cout << "_releaseRemote();" << endl;
+
+ Connection *conn = Dispatcher::the()->activeConnection();
+ list<Connection *>::iterator i;
+ bool found = false;
+
+ for(i=_remoteUsers.begin(); !found && i != _remoteUsers.end(); i++)
+ {
+ found = (*i) == conn;
+ if(found)
+ {
+ _remoteUsers.erase(i);
+ break;
+ }
+ }
+ assert(found);
+ _release();
+}
+
+void Object_skel::_useRemote()
+{
+ //cout << "_useRemote();" << endl;
+
+ Connection *conn = Dispatcher::the()->activeConnection();
+ if(_remoteSendCount == 0)
+ {
+ arts_warning("_useRemote without prior _copyRemote() - this might fail sometimes");
+ _copyRemote();
+ }
+
+ _remoteSendCount--;
+ _remoteUsers.push_back(conn);
+}
+
+/*
+ * This is needed when we've received an object from wire which we now
+ * hold locally. Of course it has been _copyRemote()d (rightly so), but
+ * we will not use it remotely, so we need to cancel the _copyRemote().
+ *
+ * Added to _base due to BC.
+ */
+void Object_base::_cancelCopyRemote()
+{
+ assert(_location() == objectIsLocal);
+
+ if(_skel()->_remoteSendCount == 0)
+ {
+ arts_warning("_cancelCopyRemote without prior _copyRemote() - this might fail sometimes");
+ }
+ else
+ {
+ _skel()->_remoteSendCount--;
+ _release();
+ }
+}
+
+void Object_skel::_disconnectRemote(Connection *conn)
+{
+ //cout << "_disconnectRemote();" << endl;
+
+ int rcount = 0;
+ list<Connection *>::iterator i;
+
+ i=_remoteUsers.begin();
+ while(i != _remoteUsers.end())
+ {
+ if((*i) == conn)
+ {
+ _remoteUsers.erase(i);
+ i = _remoteUsers.begin();
+ rcount++;
+ }
+ else i++;
+ }
+
+ while(rcount) {
+ arts_debug("client disconnected: dropped one object reference");
+ rcount--;
+ _release();
+ }
+ /* warning: object may not exist any longer here */
+}
+
+void Object_skel::_referenceClean()
+{
+ if(_remoteSendCount > 0)
+ {
+ if(_remoteSendUpdated)
+ {
+ // this ensures that every client gets at least five
+ // seconds to connect
+ _remoteSendUpdated = false;
+ }
+ else
+ {
+ int rcount = _remoteSendCount;
+
+ arts_debug("_referenceClean: found unused object marked by "
+ "_copyRemote => releasing");
+
+ while(rcount--)
+ {
+ _remoteSendCount--;
+ _release();
+ }
+ }
+ /* warning: object may be gone here */
+ }
+}
+
+string Object_skel::_toString()
+{
+ return Dispatcher::the()->objectToString(_objectID);
+}
+
+string Object_skel::_interfaceName()
+{
+ assert(0); // derived classes *must* override this
+ return "";
+}
+
+string Object_skel::_interfaceNameSkel()
+{
+ // derived classes *must* override this, but we return a sane value here
+ // anyway, because DynamicSkeleton depends on this
+ return "Arts::Object";
+}
+
+bool Object_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename=="Arts::Object") return true;
+ return false;
+}
+
+InterfaceDef Object_skel::_queryInterface(const string& name)
+{
+ return Dispatcher::the()->interfaceRepo().queryInterface(name);
+}
+
+TypeDef Object_skel::_queryType(const string& name)
+{
+ return Dispatcher::the()->interfaceRepo().queryType(name);
+}
+
+EnumDef Object_skel::_queryEnum(const string& name)
+{
+ return Dispatcher::the()->interfaceRepo().queryEnum(name);
+}
+
+// Aggregation
+std::string Object_skel::_addChild(Arts::Object child, const std::string& name)
+{
+ return _internalData->children.put(name,child);
+}
+
+bool Object_skel::_removeChild(const std::string& name)
+{
+ return _internalData->children.remove(name);
+}
+
+Arts::Object Object_skel::_getChild(const std::string& name)
+{
+ Arts::Object result;
+ if(_internalData->children.get(name,result))
+ return result;
+ else
+ return Arts::Object::null();
+}
+
+std::vector<std::string> *Object_skel::_queryChildren()
+{
+ return _internalData->children.contents();
+}
+
+void Object_skel::_addMethod(DispatchFunction disp, void *obj,
+ const MethodDef& md)
+{
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.dispatcher = disp;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfNormal;
+ me.object = obj;
+ me.methodDef = md;
+ _internalData->methodTable.push_back(me);
+}
+
+void Object_skel::_addMethod(OnewayDispatchFunction disp, void *obj,
+ const MethodDef& md)
+{
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.onewayDispatcher = disp;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfOneway;
+ me.object = obj;
+ me.methodDef = md;
+ _internalData->methodTable.push_back(me);
+}
+
+void Object_skel::_addMethod(DynamicDispatchFunction disp, void *obj,
+ const MethodDef& md)
+{
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.dynamicDispatcher = disp;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfDynamic;
+ me.object = obj;
+ me.methodDef = md;
+ _internalData->methodTable.push_back(me);
+}
+
+
+long Object_skel::_addCustomMessageHandler(OnewayDispatchFunction handler,
+ void *obj)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.onewayDispatcher = handler;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfOneway;
+ me.object = obj;
+ me.methodDef.name = "_userdefined_customdatahandler";
+ _internalData->methodTable.push_back(me);
+ return _internalData->methodTable.size()-1;
+}
+
+void Object_skel::_dispatch(Buffer *request, Buffer *result,long methodID)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+
+ const ObjectInternalData::MethodTableEntry& me
+ = _internalData->methodTable[methodID];
+
+ if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfNormal)
+ me.dispFunc.dispatcher(me.object, request, result);
+ else if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfDynamic)
+ me.dispFunc.dynamicDispatcher(me.object, methodID, request, result);
+ else
+ {
+ arts_assert(0);
+ }
+}
+
+void Object_skel::_dispatch(Buffer *request,long methodID)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+ const ObjectInternalData::MethodTableEntry& me
+ = _internalData->methodTable[methodID];
+
+ if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfOneway)
+ me.dispFunc.onewayDispatcher(me.object, request);
+ else if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfDynamic)
+ me.dispFunc.dynamicDispatcher(me.object, methodID, request, 0);
+ else
+ {
+ arts_assert(0);
+ }
+}
+
+long Object_skel::_lookupMethod(const MethodDef& md)
+{
+ long mcount = 0;
+
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+
+ vector<Arts::ObjectInternalData::MethodTableEntry>::iterator i;
+ for(i=_internalData->methodTable.begin(); i != _internalData->methodTable.end(); i++)
+ {
+ MethodDef& mdm = i->methodDef;
+ if(mdm.name == md.name && mdm.type == md.type)
+ {
+ /* TODO: compare signature
+ vector<ParamDef *>::const_iterator j,k;
+ j = md.signature.begin();
+ k = mdm.signature.begin();
+ while(j != md.signature.end() && (*j) == (*k))
+ {
+ j++;
+ k++;
+ }
+
+ if(j == md.signature.end() && k == mdm.signature.end())
+ */
+ return mcount;
+ }
+ mcount++;
+ }
+ arts_warning("_lookupMethod %s %s failed this might be caused by "
+ "incompatible IDL files and is likely to result in crashes",
+ md.type.c_str(),md.name.c_str());
+ return -1;
+}
+
+const MethodDef& Object_skel::_dsGetMethodDef(long methodID)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+ return _internalData->methodTable[methodID].methodDef;
+}
+
+// _lookupMethod
+static void _dispatch_Arts_Object_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::MethodDef methodDef(*request);
+ result->writeLong(((Arts::Object_skel *)object)->_lookupMethod(methodDef));
+}
+
+// _interfaceName
+static void _dispatch_Arts_Object_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::Object_skel *)object)->_interfaceName());
+}
+
+// _queryInterface
+static void _dispatch_Arts_Object_02(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::InterfaceDef _returnCode = ((Arts::Object_skel *)object)->_queryInterface(name);
+ _returnCode.writeType(*result);
+}
+
+// _queryType
+static void _dispatch_Arts_Object_03(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::TypeDef _returnCode = ((Arts::Object_skel *)object)->_queryType(name);
+ _returnCode.writeType(*result);
+}
+
+// _queryEnum
+static void _dispatch_Arts_Object_04(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::EnumDef _returnCode = ((Arts::Object_skel *)object)->_queryEnum(name);
+ _returnCode.writeType(*result);
+}
+
+// _toString
+static void _dispatch_Arts_Object_05(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::Object_skel *)object)->_toString());
+}
+
+// _isCompatibleWith
+static void _dispatch_Arts_Object_06(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string interfacename;
+ request->readString(interfacename);
+ result->writeBool(((Arts::Object_skel *)object)->_isCompatibleWith(interfacename));
+}
+
+// _copyRemote
+static void _dispatch_Arts_Object_07(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::Object_skel *)object)->_copyRemote();
+}
+
+// _useRemote
+static void _dispatch_Arts_Object_08(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::Object_skel *)object)->_useRemote();
+}
+
+// _releaseRemote
+static void _dispatch_Arts_Object_09(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::Object_skel *)object)->_releaseRemote();
+}
+
+// _addChild
+static void _dispatch_Arts_Object_10(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::Object_base* _temp_child;
+ readObject(*request,_temp_child);
+ Arts::Object child = Arts::Object::_from_base(_temp_child);
+ std::string name;
+ request->readString(name);
+ result->writeString(((Arts::Object_skel *)object)->_addChild(child,name));
+}
+
+// _removeChild
+static void _dispatch_Arts_Object_11(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ result->writeBool(((Arts::Object_skel *)object)->_removeChild(name));
+}
+
+// _getChild
+static void _dispatch_Arts_Object_12(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::Object returnCode = ((Arts::Object_skel *)object)->_getChild(name);
+ writeObject(*result,returnCode._base());
+}
+
+// _queryChildren
+static void _dispatch_Arts_Object_13(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::Object_skel *)object)->_queryChildren();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// _get__flowSystem
+static void _dispatch_Arts_Object_14(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ Arts::FlowSystem returnCode = ((Arts::Object_skel *)object)->_flowSystem();
+ writeObject(*result,returnCode._base());
+}
+
+void Arts::Object_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000e5f6c6f6f6b75704d6574686f6400000000056c6f6e6700"
+ "000000020000000100000010417274733a3a4d6574686f64446566000000000a6d"
+ "6574686f644465660000000000000000000000000f5f696e746572666163654e61"
+ "6d650000000007737472696e6700000000020000000000000000000000105f7175"
+ "657279496e746572666163650000000013417274733a3a496e7465726661636544"
+ "656600000000020000000100000007737472696e6700000000056e616d65000000"
+ "0000000000000000000b5f717565727954797065000000000e417274733a3a5479"
+ "706544656600000000020000000100000007737472696e6700000000056e616d65"
+ "0000000000000000000000000b5f7175657279456e756d000000000e417274733a"
+ "3a456e756d44656600000000020000000100000007737472696e6700000000056e"
+ "616d650000000000000000000000000a5f746f537472696e670000000007737472"
+ "696e6700000000020000000000000000000000125f6973436f6d70617469626c65"
+ "576974680000000008626f6f6c65616e0000000002000000010000000773747269"
+ "6e67000000000e696e746572666163656e616d650000000000000000000000000c"
+ "5f636f707952656d6f74650000000005766f696400000000020000000000000000"
+ "0000000b5f75736552656d6f74650000000005766f696400000000020000000000"
+ "0000000000000f5f72656c6561736552656d6f74650000000005766f6964000000"
+ "000200000000000000000000000a5f6164644368696c640000000007737472696e"
+ "67000000000200000002000000076f626a65637400000000066368696c64000000"
+ "000000000007737472696e6700000000056e616d65000000000000000000000000"
+ "0d5f72656d6f76654368696c640000000008626f6f6c65616e0000000002000000"
+ "0100000007737472696e6700000000056e616d650000000000000000000000000a"
+ "5f6765744368696c6400000000076f626a65637400000000020000000100000007"
+ "737472696e6700000000056e616d650000000000000000000000000f5f71756572"
+ "794368696c6472656e00000000082a737472696e67000000000200000000000000"
+ "00000000115f6765745f5f666c6f7753797374656d0000000011417274733a3a46"
+ "6c6f7753797374656d00000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_Object_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_03,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_04,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_05,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_06,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_07,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_08,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_09,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_10,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_11,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_12,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_13,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_14,this,Arts::MethodDef(m));
+}
+
+/*
+ * Stuff for object stubs
+ */
+
+Object_stub::Object_stub()
+{
+ assert(0); // never use this constructor, as it doesn't assign an object ID
+}
+
+Object_stub::Object_stub(Connection *connection, long objectID)
+{
+ _connection = connection;
+ _connection->_copy();
+ _objectID = objectID;
+ _lookupCacheRandom = rand();
+
+ if(_connection == Dispatcher::the()->loopbackConnection())
+ _internalData->stubForLocalObject = true;
+
+ char ioid[128];
+ sprintf(ioid,"STUB:%ld:%p",_objectID,(void *)connection);
+ _internalObjectID = ioid;
+}
+
+Object_stub::~Object_stub()
+{
+ /*
+ * invalidate method lookup cache entries of this object, as it might
+ * happen, that another Object_stub is created just at the same position
+ */
+ if(_lookupMethodCache)
+ {
+ for(long p=0;p<_lookupMethodCacheSize;p++)
+ {
+ if(_lookupMethodCache[p].obj == this)
+ _lookupMethodCache[p].obj = NULL;
+ }
+ }
+ _connection->_release();
+}
+
+bool Object_stub::_error()
+{
+ /*
+ * servers are trustworthy - they don't do things wrong (e.g. send
+ * wrong buffers or things like that) - however, if the connection is
+ * lost, this indicates that something went terrible wrong (probably
+ * the remote server crashed, or maybe the network is dead), and you
+ * can't rely on results of invocations any longer
+ */
+ return _connection->broken();
+}
+
+void Object_stub::_release()
+{
+ arts_return_if_fail(_refCnt > 0);
+
+ _refCnt--;
+ if(_refCnt == 0)
+ {
+ _releaseRemote();
+ _destroy();
+ }
+}
+
+Object_base *Object_base::_create(const std::string& subClass)
+{
+ Object_skel *skel = ObjectManager::the()->create(subClass);
+ assert(skel);
+ return skel;
+}
+
+Object_base *Object_base::_fromString(const string& objectref)
+{
+ Object_base *result = 0;
+ ObjectReference r;
+
+ if(Dispatcher::the()->stringToObjectReference(r,objectref))
+ {
+ result = (Object_base *)Dispatcher::the()->connectObjectLocal(r,"Object");
+ if(!result)
+ {
+ Connection *conn = Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Object_stub(conn,r.objectID);
+ result->_useRemote();
+ }
+ }
+ }
+ return result;
+}
+
+Object_base *Object_base::_fromReference(ObjectReference r, bool needcopy)
+{
+ Object_base *result;
+ result = (Object_base *)Dispatcher::the()->connectObjectLocal(r,"Object");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Connection *conn = Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Object_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ }
+ }
+ return result;
+}
+
+string Object_stub::_interfaceName()
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,1);
+ // methodID = 1 => _interfaceName (always)
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return ""; // error
+ string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+InterfaceDef Object_stub::_queryInterface(const string& name)
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,2);
+ // methodID = 2 => _queryInterface (always)
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return InterfaceDef(); // error
+ InterfaceDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+TypeDef Object_stub::_queryType(const string& name)
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,3);
+ // methodID = 3 => _queryType (always)
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return TypeDef(); // error
+ TypeDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+EnumDef Object_stub::_queryEnum(const string& name)
+{
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,4);
+ // methodID = 4 => _queryEnum (always)
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return EnumDef(); // error occurred
+ EnumDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+long Object_stub::_lookupMethod(const MethodDef& methodDef)
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,0);
+ // methodID = 0 => _lookupMethod (always)
+ methodDef.writeType(*request);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return 0; // error
+ long returnCode = result->readLong();
+ delete result;
+ return returnCode;
+}
+
+Object_stub::methodCacheEntry *Object_stub::_lookupMethodCache = 0;
+
+long Object_stub::_lookupMethodFast(const char *method)
+{
+ unsigned long c1 = (unsigned long)this;
+ unsigned long c2 = (unsigned long)method;
+ unsigned long pos = (c1^c2^_lookupCacheRandom)%_lookupMethodCacheSize;
+ /* FIXME this hashing method sucks. at a bare minimum, we're using only every 4th bin */
+
+ if(!_lookupMethodCache)
+ _lookupMethodCache = new methodCacheEntry[_lookupMethodCacheSize];
+
+ if(_lookupMethodCache[pos].obj == this && _lookupMethodCache[pos].method == method)
+ return _lookupMethodCache[pos].ID;
+
+ Buffer _methodBuffer;
+ _methodBuffer.fromString(method,"method");
+ long methodID = _lookupMethod(MethodDef(_methodBuffer));
+ //cout << "methodID = " << methodID << endl;
+
+ _lookupMethodCache[pos].obj = this;
+ _lookupMethodCache[pos].method = method;
+ _lookupMethodCache[pos].ID = methodID;
+ return methodID;
+}
+
+// other (normal) methods without fixed location
+
+std::string Arts::Object_stub::_toString()
+{
+ long methodID = _lookupMethodFast("method:0000000a5f746f537472696e670000000007737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+bool Arts::Object_stub::_isCompatibleWith(const std::string& interfacename)
+{
+ long methodID = _lookupMethodFast("method:000000125f6973436f6d70617469626c65576974680000000008626f6f6c65616e00000000020000000100000007737472696e67000000000e696e746572666163656e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(interfacename);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return false; // error occurred
+ bool returnCode = result->readBool();
+ delete result;
+ return returnCode;
+}
+
+void Arts::Object_stub::_copyRemote()
+{
+ long methodID = _lookupMethodFast("method:0000000c5f636f707952656d6f74650000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::Object_stub::_useRemote()
+{
+ long methodID = _lookupMethodFast("method:0000000b5f75736552656d6f74650000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::Object_stub::_releaseRemote()
+{
+ long methodID = _lookupMethodFast("method:0000000f5f72656c6561736552656d6f74650000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::string Arts::Object_stub::_addChild(Arts::Object child, const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a5f6164644368696c640000000007737472696e67000000000200000002000000076f626a65637400000000066368696c64000000000000000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ writeObject(*request,child._base());
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+bool Arts::Object_stub::_removeChild(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000d5f72656d6f76654368696c640000000008626f6f6c65616e00000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return false; // error occurred
+ bool returnCode = result->readBool();
+ delete result;
+ return returnCode;
+}
+
+Arts::Object Arts::Object_stub::_getChild(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a5f6765744368696c6400000000076f626a65637400000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::Object::null();
+ Arts::Object_base* returnCode;
+ readObject(*result,returnCode);
+ delete result;
+ return Arts::Object::_from_base(returnCode);
+}
+
+std::vector<std::string> * Arts::Object_stub::_queryChildren()
+{
+ long methodID = _lookupMethodFast("method:0000000f5f71756572794368696c6472656e00000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+Arts::FlowSystem Arts::Object_stub::_flowSystem()
+{
+ long methodID = _lookupMethodFast("method:000000115f6765745f5f666c6f7753797374656d0000000011417274733a3a466c6f7753797374656d00000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::FlowSystem::null();
+ Arts::FlowSystem_base* returnCode;
+ readObject(*result,returnCode);
+ delete result;
+ return Arts::FlowSystem::_from_base(returnCode);
+}
+
+/*
+ * custom messaging
+ */
+
+Buffer *Object_stub::_allocCustomMessage(long handlerID)
+{
+ return Dispatcher::the()->createOnewayRequest(_objectID,handlerID);
+}
+
+void Object_stub::_sendCustomMessage(Buffer *buffer)
+{
+ buffer->patchLength();
+ _connection->qSendBuffer(buffer);
+}
+
+unsigned long Object_base::_IID = MCOPUtils::makeIID("Object");
+
+/*
+ * global cleanup
+ */
+
+void Object_stub::_cleanupMethodCache()
+{
+ if(_lookupMethodCache)
+ {
+ delete[] _lookupMethodCache;
+ _lookupMethodCache = 0;
+ }
+}
+
+namespace Arts {
+ static class Object_stub_Shutdown : public StartupClass {
+ public:
+ void startup() { }
+ void shutdown() { Object_stub::_cleanupMethodCache(); }
+ } The_Object_stub_Shutdown;
+}
diff --git a/mcop/object.h b/mcop/object.h
new file mode 100644
index 0000000..efe8c59
--- /dev/null
+++ b/mcop/object.h
@@ -0,0 +1,390 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef OBJECT_H
+#define OBJECT_H
+
+#include "buffer.h"
+#include "connection.h"
+#include "notification.h"
+
+#include <assert.h>
+#include <map>
+#include <list>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Object_base, Object_skel, Object_stub
+ *
+ * All of them have to be kept binary compatible carefully, due to interaction
+ * with generated code. There are d ptrs in _skel and _stub, NOT TO BE USED
+ * NORMALLY. Normally, do use _internalData instead, as this is much faster
+ * than creating two d objects per MCOP implementation/stub. Handle with care.
+ */
+
+
+namespace Arts {
+/* custom dispatching functions */
+
+typedef void (*DispatchFunction)(void *object, Buffer *request, Buffer *result);
+typedef void (*OnewayDispatchFunction)(void *object, Buffer *request);
+typedef void (*DynamicDispatchFunction)(void *object, long methodID, Buffer *request, Buffer *result);
+
+class ScheduleNode;
+class Object_skel;
+class Object_stub;
+class FlowSystem;
+class MethodDef;
+class ObjectReference;
+class WeakReferenceBase;
+class Object;
+class ObjectManager;
+class DynamicSkeletonData;
+class DynamicSkeletonBase;
+
+class ARTS_EXPORT Object_base : public NotificationClient {
+private:
+ friend class DynamicRequest;
+ friend class ObjectManager;
+ bool _deleteOk; // ensure that "delete" is not called manually
+
+protected:
+ /**
+ * ObjectInternalData contains private data structures for
+ * - Object_base
+ * - Object_stub
+ * - Object_skel
+ *
+ * This is an optimization over adding each of them private data pointers,
+ * which would lead to some more bloat.
+ */
+ class ObjectInternalData *_internalData;
+
+ struct ObjectStreamInfo;
+
+ Object_base();
+ virtual ~Object_base();
+
+ /*
+ * internal management for streams
+ */
+ ScheduleNode *_scheduleNode;
+ std::list<ObjectStreamInfo *> _streamList;
+
+ virtual Object_skel *_skel();
+ virtual Object_stub *_stub();
+
+ enum ObjectLocation { objectIsLocal, objectIsRemote };
+ virtual ObjectLocation _location() const = 0;
+
+ long _objectID;
+ Connection *_connection;
+ std::string _internalObjectID; // two objects are "_isEqual" when these match
+ long _nextNotifyID;
+ long _refCnt; // reference count
+ static long _staticObjectCount;
+
+ void _destroy(); // use this instead of delete (takes care of
+ // properly removing flow system node)
+public:
+ static unsigned long _IID; // interface ID
+ /**
+ * custom messaging: these can be used to send a custom data to other
+ * objects. Warning: these are *not* usable for local objects. You may
+ * only use these functions if you know that you are talking to a remote
+ * object. Use _allocCustomMessage to allocate a message. Put the data
+ * you want to send in the Buffer. After that, call _sendCustomMessage.
+ * Don't free the buffer - this will happen automatically.
+ */
+
+ virtual Buffer *_allocCustomMessage(long handlerID);
+ virtual void _sendCustomMessage(Buffer *data);
+
+ /*
+ * generic capabilities, which allow find out what you can do with an
+ * object even if you don't know it's interface
+ */
+ virtual long _lookupMethod(const Arts::MethodDef &) = 0;
+ virtual std::string _interfaceName() = 0;
+ virtual class InterfaceDef _queryInterface(const std::string& name) = 0;
+ virtual class TypeDef _queryType(const std::string& name) = 0;
+ virtual class EnumDef _queryEnum(const std::string& name) = 0;
+ virtual std::string _toString() = 0;
+
+ /*
+ * stuff for streaming (put in a seperate interface?)
+ */
+ virtual void calculateBlock(unsigned long cycles);
+ ScheduleNode *_node();
+ virtual FlowSystem _flowSystem() = 0;
+
+ /*
+ * reference counting
+ */
+ virtual void _release() = 0;
+ virtual void _copyRemote() = 0;
+ virtual void _useRemote() = 0;
+ virtual void _releaseRemote() = 0;
+
+ // BC issue: added _cancelCopyRemote here to avoid virtual function
+ void _cancelCopyRemote();
+
+ void _addWeakReference(WeakReferenceBase *reference);
+ void _removeWeakReference(WeakReferenceBase *reference);
+
+ inline Object_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ // Default I/O info
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ // cast operation
+ virtual void *_cast(unsigned long iid);
+ void *_cast(const std::string& interface);
+
+ // Run-time type compatibility check
+ virtual bool _isCompatibleWith(const std::string& interfacename) = 0;
+
+ // Aggregation
+ virtual std::string _addChild(Arts::Object child, const std::string& name) = 0;
+ virtual bool _removeChild(const std::string& name) = 0;
+ virtual Arts::Object _getChild(const std::string& name) = 0;
+ virtual std::vector<std::string> * _queryChildren() = 0;
+
+ /*
+ * when this is true, a fatal communication error has occurred (of course
+ * only possible for remote objects) - maybe your returncode is invalid,
+ * maybe your last invocation didn't succeed...
+ */
+ virtual bool _error();
+
+ inline static long _objectCount() { return _staticObjectCount; }
+ inline long _mkNotifyID() { return _nextNotifyID++; }
+
+ // object creation
+ static Object_base *_create(const std::string& subClass = "Object");
+
+ // comparison
+ bool _isEqual(Object_base *object) const;
+
+ // static converter (from reference)
+ static Object_base *_fromString(const std::string& objectref);
+ static Object_base *_fromReference(class ObjectReference ref, bool needcopy);
+};
+
+/*
+ * Dispatching
+ */
+
+class Buffer;
+class MethodDef;
+
+
+class Object_skel_private;
+class AnyConstRef;
+class AttributeDef;
+
+class ARTS_EXPORT Object_skel : virtual public Object_base {
+private:
+ friend class Object_base;
+ friend class DynamicSkeletonData;
+ friend class DynamicSkeletonBase;
+
+ Object_skel_private *_d_skel;// do not use until there is a very big problem
+
+ // reference counting - remote object watching
+
+ long _remoteSendCount; // don't kill objects just sent to other server
+ bool _remoteSendUpdated; // timeout if they don't want the object
+ std::list<class Connection *> _remoteUsers; // who is using it?
+
+protected:
+ void _addMethod(DispatchFunction disp, void *object, const MethodDef& md);
+ void _addMethod(OnewayDispatchFunction disp, void *object,
+ const MethodDef& md);
+ void _addMethod(DynamicDispatchFunction disp, void *object,
+ const MethodDef& md);
+ void _initStream(const std::string& name, void *ptr, long flags);
+
+ /** stuff relative to attribute notifications **/
+ bool _initAttribute(const Arts::AttributeDef& attribute);
+ static bool _QueryInitStreamFunc(Object_skel *skel,const std::string& name);
+ bool _generateSlots(const std::string& name, const std::string& interface);
+
+ /** for DynamicSkeleton: **/
+ const MethodDef& _dsGetMethodDef(long methodID);
+
+protected:
+ void _defaultNotify(const Notification& notification);
+ void notify(const Notification& notification);
+ void _emit_changed(const char *stream, const AnyConstRef& value);
+
+ /**
+ * custom messaging: this is used to install a custom data handler that
+ * can be used to receive non-standard messages
+ */
+ long _addCustomMessageHandler(OnewayDispatchFunction handler, void *object);
+
+ Object_skel *_skel();
+ ObjectLocation _location() const;
+
+public:
+ Object_skel();
+ virtual ~Object_skel();
+
+ // reference counting connection drop
+ void _disconnectRemote(class Connection *connection);
+ void _referenceClean();
+
+ // synchronous & asynchronous dispatching
+ void _dispatch(Buffer *request, Buffer *result,long methodID);
+ void _dispatch(Buffer *request, long methodID);
+ long _lookupMethod(const MethodDef &);
+
+ /*
+ * standard interface for every object skeleton
+ */
+ static std::string _interfaceNameSkel();
+ virtual void _buildMethodTable();
+
+ /*
+ * reference counting
+ */
+ virtual void _release();
+ virtual void _copyRemote();
+ virtual void _useRemote();
+ virtual void _releaseRemote();
+
+ /*
+ * streaming
+ */
+ FlowSystem _flowSystem();
+
+ /*
+ * to inspect the (remote) object interface
+ */
+ virtual std::string _interfaceName();
+ InterfaceDef _queryInterface(const std::string& name);
+ TypeDef _queryType(const std::string& name);
+ EnumDef _queryEnum(const std::string& name);
+ virtual std::string _toString();
+
+ // Run-time type compatibility check
+ bool _isCompatibleWith(const std::string& interfacename);
+
+ // Aggregation
+ std::string _addChild(Arts::Object child, const std::string& name);
+ bool _removeChild(const std::string& name);
+ Arts::Object _getChild(const std::string& name);
+ std::vector<std::string> * _queryChildren();
+};
+
+class Object_stub_private;
+
+class ARTS_EXPORT Object_stub : virtual public Object_base {
+private:
+ friend class Object_base;
+
+ Object_stub_private *_d_stub;// do not use until there is a very big problem
+
+protected:
+ long _lookupCacheRandom;
+
+ Object_stub();
+ Object_stub(Connection *connection, long objectID);
+ virtual ~Object_stub();
+
+ virtual Object_stub *_stub();
+ ObjectLocation _location() const;
+
+ enum { _lookupMethodCacheSize = 337 };
+ static struct methodCacheEntry {
+ methodCacheEntry() : obj(NULL),method(NULL),ID(0) {} ;
+ Object_stub *obj;
+ const char *method;
+ long ID;
+ } *_lookupMethodCache;
+
+ long _lookupMethodFast(const char *method);
+ long _lookupMethod(const MethodDef &);
+
+public:
+ /*
+ * custom messaging
+ */
+
+ Buffer *_allocCustomMessage(long handlerID);
+ void _sendCustomMessage(Buffer *data);
+
+ /*
+ * to inspect the (remote) object interface
+ */
+ std::string _interfaceName();
+ InterfaceDef _queryInterface(const std::string& name);
+ TypeDef _queryType(const std::string& name);
+ EnumDef _queryEnum(const std::string& name);
+ std::string _toString();
+
+ /*
+ * streaming
+ */
+ FlowSystem _flowSystem();
+
+ /*
+ * reference counting
+ */
+ virtual void _release();
+ virtual void _copyRemote();
+ virtual void _useRemote();
+ virtual void _releaseRemote();
+
+ // Run-time type compatibility check
+ bool _isCompatibleWith(const std::string& interfacename);
+
+ // Aggregation
+ std::string _addChild(Arts::Object child, const std::string& name);
+ bool _removeChild(const std::string& name);
+ Arts::Object _getChild(const std::string& name);
+ std::vector<std::string> * _queryChildren();
+
+ /*
+ * communication error? this is true when your connection to the remote
+ * object is lost (e.g. when the remote server crashed) - your return
+ * values are then undefined, so check this before relying too much
+ * on some invocation
+ */
+
+ bool _error();
+
+ /*
+ * global cleanup
+ */
+ static void _cleanupMethodCache();
+};
+
+}
+#endif
diff --git a/mcop/objectmanager.cc b/mcop/objectmanager.cc
new file mode 100644
index 0000000..0617ea4
--- /dev/null
+++ b/mcop/objectmanager.cc
@@ -0,0 +1,289 @@
+ /*
+
+ Copyright (C) 2000,2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "mcoputils.h"
+#include "mcopconfig.h"
+#include "objectmanager.h"
+#include "dispatcher.h"
+#include "extensionloader.h"
+#include "debug.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+class Arts::ObjectManagerPrivate {
+public:
+ struct LoaderData {
+ LoaderData() : init(false) { }
+ bool init;
+ Loader loader;
+ };
+
+ list<ExtensionLoader *> extensions;
+ map<string, long> capabilities;
+ map<string, LoaderData> loaders;
+};
+
+Object_skel *ObjectManager::create(const string& name)
+{
+ list<Factory *>::iterator i;
+
+ /* first try: look through all factories we have */
+
+ for(i = factories.begin();i != factories.end(); i++)
+ {
+ Factory *f = *i;
+ if(f->interfaceName() == name ) return f->createInstance();
+ }
+
+ /* second try: look if there is a suitable extension we could load */
+
+ TraderQuery query;
+ query.supports("InterfaceName", name);
+ vector<TraderOffer> *offers = query.query();
+
+ vector<TraderOffer>::iterator oi;
+ for(oi = offers->begin(); oi != offers->end(); oi++)
+ {
+ /*
+ * check whether we provide everything that this
+ * implementation requires to run
+ */
+ bool requirementsOk = true;
+ vector<string> *requires = oi->getProperty("Requires");
+
+ vector<string>::iterator ri;
+ for(ri = requires->begin(); ri != requires->end(); ri++)
+ {
+ if(d->capabilities[*ri] <= 0)
+ requirementsOk = false;
+ }
+ delete requires;
+
+ vector<string> *language = oi->getProperty("Language");
+ vector<string> *libs = oi->getProperty("Library");
+
+ if(language->size() == 0 && libs->size() == 1)
+ {
+ arts_warning("ObjectManager: %s - assuming 'Language=C++' because library given",name.c_str());
+ language->push_back("C++");
+ }
+ if(language->size() != 1)
+ {
+ arts_warning("ObjectManager: %s - Language missing", name.c_str());
+ requirementsOk = false;
+ }
+ if(requirementsOk && language->front() == "C++" && libs->empty())
+ {
+ arts_warning("ObjectManager: %s - Library missing", name.c_str());
+ requirementsOk = false;
+ }
+
+ /* loading C++ components */
+ if(requirementsOk && language->front() == "C++")
+ {
+ string library = libs->front();
+
+ ExtensionLoader *e = new ExtensionLoader(library);
+ if(e->success())
+ {
+ d->extensions.push_back(e);
+ for(i = factories.begin();i != factories.end(); i++)
+ {
+ Factory *f = *i;
+ if(f->interfaceName() == name)
+ {
+ delete language;
+ delete libs;
+ delete offers;
+ return f->createInstance();
+ }
+ }
+ }
+ else
+ {
+ arts_warning("MCOP ObjectManager:"
+ " Could not load extension %s.", library.c_str());
+ delete e;
+ }
+ }
+ delete libs;
+
+ /* other languages/binary formats */
+ if(requirementsOk)
+ {
+ string lang = language->front();
+ ObjectManagerPrivate::LoaderData &ld = d->loaders[lang];
+
+ if(!ld.init)
+ {
+ TraderQuery query;
+ query.supports("Interface", "Arts::Loader");
+ query.supports("LoadLanguage", lang);
+
+ vector<TraderOffer> *loffers = query.query();
+
+ // TODO: error checking for SubClass
+ if(loffers->size() > 0)
+ {
+ ld.loader = SubClass(loffers->front().interfaceName());
+ }
+ else
+ {
+ ld.loader = Arts::Loader::null();
+ }
+
+ delete loffers;
+ }
+ ld.init = true;
+
+ if(!ld.loader.isNull())
+ {
+ /*
+ * ### change when breaking BC:
+ * it's bad that ObjectManager has to return _skel()s, but
+ * well, can't change it now
+ */
+
+ Object obj = ld.loader.loadObject(*oi);
+ delete language;
+ delete offers;
+ return obj._base()->_copy()->_skel();
+ }
+ }
+
+ delete language;
+ }
+
+ arts_warning("MCOP ObjectManager: can't find implementation for %s.",
+ name.c_str());
+
+ delete offers;
+ return 0;
+}
+
+void ObjectManager::registerFactory(Factory *factory)
+{
+ factories.push_back(factory);
+}
+
+void ObjectManager::removeFactory(Factory *factory)
+{
+ list<Factory *>::iterator i;
+
+ i = factories.begin();
+ while(i != factories.end())
+ {
+ if(*i == factory) {
+ factories.erase(i);
+ i = factories.begin();
+ }
+ else i++;
+ }
+}
+
+ObjectManager *ObjectManager::_instance = 0;
+
+ObjectManager::ObjectManager()
+{
+ assert(!_instance);
+ _instance = this;
+ d = new ObjectManagerPrivate;
+}
+
+ObjectManager::~ObjectManager()
+{
+ // they should be unloaded before this object can be deleted
+ assert(d->extensions.empty());
+ delete d;
+ assert(_instance);
+ _instance = 0;
+}
+
+ObjectManager *ObjectManager::the()
+{
+ assert(_instance);
+ return _instance;
+}
+
+void ObjectManager::shutdownExtensions()
+{
+ // give up references to the loaders
+ d->loaders.clear();
+
+ // shuts down all dynamically loaded extensions
+ list<ExtensionLoader *>::iterator i;
+ for(i=d->extensions.begin(); i != d->extensions.end(); i++)
+ (*i)->shutdown();
+}
+
+void ObjectManager::removeExtensions()
+{
+ // unloads all dynamically loaded extensions
+ list<ExtensionLoader *>::iterator i;
+ for(i=d->extensions.begin(); i != d->extensions.end(); i++)
+ delete *i;
+
+ d->extensions.clear();
+}
+
+/*
+ * global references
+ */
+
+bool ObjectManager::addGlobalReference(Object object, const string& name)
+{
+ bool result;
+
+ result = Dispatcher::the()->globalComm().put(name,object.toString());
+ if(result)
+ referenceNames.push_back(name);
+
+ return result;
+}
+
+string ObjectManager::getGlobalReference(const string& name)
+{
+ return Dispatcher::the()->globalComm().get(name);
+}
+
+void ObjectManager::removeGlobalReferences()
+{
+ list<string>::iterator i;
+
+ for(i=referenceNames.begin(); i != referenceNames.end();i++)
+ Dispatcher::the()->globalComm().erase(*i);
+}
+
+void ObjectManager::provideCapability(const string& name)
+{
+ d->capabilities[name]++;
+}
+
+void ObjectManager::removeCapability(const string& name)
+{
+ d->capabilities[name]--;
+}
diff --git a/mcop/objectmanager.h b/mcop/objectmanager.h
new file mode 100644
index 0000000..47a5c11
--- /dev/null
+++ b/mcop/objectmanager.h
@@ -0,0 +1,75 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef OBJECTMANAGER_H
+#define OBJECTMANAGER_H
+
+#include "object.h"
+#include "factory.h"
+#include <list>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): ObjectManager
+ *
+ * Keep binary compatible (since accessible via ::the()), use d ptr when
+ * changing it.
+ */
+
+namespace Arts {
+
+class Object;
+class ObjectManagerPrivate;
+
+class ARTS_EXPORT ObjectManager {
+private:
+ ObjectManagerPrivate *d;
+
+protected:
+ static ObjectManager *_instance;
+ std::list<Factory *> factories;
+ std::list<std::string> referenceNames;
+
+public:
+ ObjectManager();
+ ~ObjectManager();
+
+ static ObjectManager *the();
+ Object_skel *create(const std::string& name);
+
+ bool addGlobalReference(Object object, const std::string& name);
+ std::string getGlobalReference(const std::string& name);
+ void removeGlobalReferences();
+ void removeExtensions();
+ void shutdownExtensions();
+
+ void registerFactory(Factory *factory);
+ void removeFactory(Factory *factory);
+
+ void provideCapability(const std::string& capability);
+ void removeCapability(const std::string& capability);
+};
+
+}
+
+#endif /* OBJECTMANAGER_H */
diff --git a/mcop/pool.h b/mcop/pool.h
new file mode 100644
index 0000000..199f422
--- /dev/null
+++ b/mcop/pool.h
@@ -0,0 +1,89 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_POOL_H
+#define ARTS_POOL_H
+
+
+/*
+ * BC - Status (2002-03-08): Pool<type>
+ *
+ * Needs to be kept binary compatible by NOT TOUCHING. When you want something
+ * else, write a fresh one (used as part of Arts::Dispatcher, thus changing
+ * this breaks Arts::Dispatcher binary compatibility).
+ */
+
+
+/**
+ * A pool object of the type T keeps a pool of T* pointers, that are numbered.
+ *
+ * You allocate and release slots, and store T*'s in there. It should take
+ * about no time to find a new free slot to store the T object into and to
+ * release a slot to be reused.
+ *
+ * The pool object internally keeps track which slots are used.
+ */
+#include <stack>
+#include <vector>
+#include <list>
+
+namespace Arts {
+
+template <class T>
+class Pool {
+ std::stack<unsigned long> freeIDs;
+ std::vector<T *> storage;
+public:
+ inline T*& operator[](unsigned long n) { return storage[n]; }
+ inline void releaseSlot(unsigned long n) {
+ freeIDs.push(n);
+ storage[n] = 0;
+ }
+ unsigned long allocSlot() {
+ unsigned long slot;
+ if(freeIDs.empty())
+ {
+ unsigned long n;
+ for(n=0;n<32;n++) {
+ freeIDs.push(storage.size());
+ storage.push_back(0);
+ }
+ }
+ slot = freeIDs.top();
+ freeIDs.pop();
+ return slot;
+ }
+ std::list<T *> enumerate() {
+ std::list<T *> items;
+ //std::vector<T *>::iterator i;
+ int n,max = storage.size();
+
+ for(n=0; n < max; n++)
+ if(storage[n]) items.push_back(storage[n]);
+
+ return items;
+ }
+ unsigned long max() { return storage.size(); }
+};
+
+}
+#endif /* POOL_H */
diff --git a/mcop/reference.cc b/mcop/reference.cc
new file mode 100644
index 0000000..3f214bf
--- /dev/null
+++ b/mcop/reference.cc
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu, nicolas.brodu@free.fr
+ Stefan Westerfeld, stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "common.h"
+
+using namespace Arts;
+
+// For technical reasons, this is here too: FlowSystem isn't declared when
+// the wrapper is already needed, so we can't make this function inline,
+// unfortunately...
+FlowSystem Object::_flowSystem() const
+{
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_flowSystem();
+}
diff --git a/mcop/reference.h b/mcop/reference.h
new file mode 100644
index 0000000..ae59df6
--- /dev/null
+++ b/mcop/reference.h
@@ -0,0 +1,349 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu, nicolas.brodu@free.fr
+ Stefan Westerfeld, stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * BC - Status (2002-03-08): Reference, SubClass, Object, DynamicCast.
+ *
+ * Part of the public API. Must be kept binary compatible by NOT TOUCHING
+ * AT ALL. Interaction with generated and written code.
+ */
+
+
+#ifndef MCOP_REFERENCE_H
+#define MCOP_REFERENCE_H
+
+#include "common.h"
+#include <string>
+#include <vector>
+
+#include "arts_export.h"
+
+namespace Arts {
+
+// Acts as a string or ObjectReference, but enables a different constructor
+class ARTS_EXPORT Reference {
+private:
+ ObjectReference myref;
+ std::string mys;
+ bool strMode;
+public:
+
+ inline explicit Reference(const ObjectReference& ref) {
+ myref=ref;
+ strMode=false;
+ }
+
+ inline explicit Reference(const std::string& s) {
+ mys=s;
+ strMode=true;
+ }
+
+ inline explicit Reference(const char* c) {
+ mys=c;
+ strMode=true;
+ }
+ inline Reference& operator=(const std::string& s) {
+ mys=s;
+ strMode=true;
+ return *this;
+ }
+ inline Reference& operator=(const char*c) {
+ mys=c;
+ strMode=true;
+ return *this;
+ }
+ inline bool isString() const {return strMode;}
+// inline operator const std::string() const {return mys;}
+ inline const std::string& string() const {return mys;}
+// inline operator const ObjectReference() const {return myref;}
+ inline const ObjectReference& reference() const {return myref;}
+};
+
+// Acts as a string, but enables a different constructor
+class ARTS_EXPORT SubClass {
+private:
+ std::string mys;
+public:
+
+ inline explicit SubClass(const std::string& s) : mys(s) {}
+ inline explicit SubClass(const char* c) : mys(c) {}
+ inline SubClass& operator=(const std::string& s) {mys=s; return *this;}
+ inline SubClass& operator=(const char*c) {mys=c; return *this;}
+// inline operator const std::string() const {return mys;}
+ inline const std::string& string() const {return mys;}
+};
+
+
+class ScheduleNode;
+class FlowSystem;
+
+// Object has _no_ virtual, and must not have. That way, all the
+// wrappers can be passed as argument or return type, and there is also
+// no virtual table bloat.
+// Moreover, the virtual mechanism still works correctly thanks to the
+// _pool->base redirection.
+class ARTS_EXPORT Object {
+protected:
+ // Pool of common variables for a bunch a wrappers
+ class Pool {
+ friend class Object;
+ Object_base* (*creator)();
+ bool created;
+ int count;
+ public:
+ Object_base* base;
+ inline Pool(Object_base* b)
+ : creator(0), created(true), count(1), base(b) {}
+ inline Pool(Object_base* (*cor)())
+ : creator(cor), created(false), count(1), base(0) {}
+ inline void Inc() {count++;}
+ inline void Dec() {
+ if (--count==0) {
+ if(base) base->_release();
+ delete this;
+ }
+ }
+ inline void checkcreate() {
+ if (!created) {base = creator(); created=true;}
+ }
+ } *_pool;
+
+ inline Object(Object_base* (*cor)()) {
+ _pool = new Pool(cor);
+ }
+ inline Object(Pool* p) : _pool(p) {
+ _pool->Inc();
+ }
+ inline Object(Pool& p) : _pool(&p) {
+ _pool->Inc();
+ }
+ inline Object(Object_base* b) {
+ _pool = new Pool(b);
+ }
+public:
+ typedef Object_base _base_class;
+
+ // Dynamic cast constructor of inherited classes needs to access the _pool
+ // of a generic object if casting successful. But it could not without this
+ inline Pool* _get_pool() const {return _pool;}
+
+ inline ~Object() {
+ _pool->Dec();
+ }
+
+ // Those constructors are public, since we don't need an actual creator.
+ // They enable generic object creation (like from a subclass defined at
+ // run-time!)
+ inline Object(const SubClass& s) {
+ _pool = new Pool(Object_base::_create(s.string()));
+ }
+ inline Object(const Reference &r) {
+ _pool = new Pool(r.isString()?(Object_base::_fromString(r.string())):(Object_base::_fromReference(r.reference(),true)));
+ }
+ inline Object(const Object& target) : _pool(target._pool) {
+ _pool->Inc();
+ }
+ inline Object() { // creates a null object
+ _pool = new Pool((Object_base*)0);
+ }
+ inline Object& operator=(const Object& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _pool->Inc();
+ return *this;
+ }
+ // No problem for the creator, this class has protected constructors.
+ // So creator should give back an actual implementation
+ inline Object_base* _base() const {
+ _pool->checkcreate();
+ return _pool->base;
+ }
+
+ // null, error?
+ inline bool isNull() const {
+ _pool->checkcreate();
+ return !(_pool->base);
+ }
+ inline bool error() const {
+ _pool->checkcreate();
+ return _pool->base && _pool->base->_error();
+ }
+
+ // Comparision
+ inline bool _isEqual(const Object& other) const {
+ if(isNull() != other.isNull()) return false;
+
+ // we can assume that things are created here, as we've
+ // called isNull of both wrappers once
+ if(!isNull())
+ return _pool->base->_isEqual(other._pool->base);
+
+ // both null references
+ return true;
+ }
+
+
+// Object_base wrappers
+
+ // Custom messaging - see Object_base for comments
+ inline Buffer *_allocCustomMessage(long handlerID) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_allocCustomMessage(handlerID);
+ }
+
+ inline void _sendCustomMessage(Buffer *data) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_sendCustomMessage(data);
+ }
+
+ // generic capabilities, which allow find out what you can do with an
+ // object even if you don't know it's interface
+ inline long _lookupMethod(const MethodDef& methodDef) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_lookupMethod(methodDef);
+ }
+ inline std::string _interfaceName() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_interfaceName();
+ }
+ inline InterfaceDef _queryInterface(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryInterface(name);
+ }
+ inline TypeDef _queryType(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryType(name);
+ }
+ inline EnumDef _queryEnum(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryEnum(name);
+ }
+ // Stringification
+ inline std::string _toString() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_toString();
+ }
+ inline std::string toString() const {return _toString();}
+
+ // stuff for streaming (put in a seperate interface?)
+ inline void calculateBlock(unsigned long cycles) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->calculateBlock(cycles);
+ }
+ // Node info
+ inline ScheduleNode *_node() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_node();
+ }
+
+ // Ah! Flowsystem is not defined yet, so cannot be returned inline.
+ FlowSystem _flowSystem() const;
+
+ inline void _copyRemote() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_copyRemote();
+ }
+ inline void _useRemote() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_useRemote();
+ }
+ inline void _releaseRemote() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_releaseRemote();
+ }
+
+ // Default I/O info
+ inline std::vector<std::string> _defaultPortsIn() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_defaultPortsIn();
+ }
+ inline std::vector<std::string> _defaultPortsOut() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_defaultPortsOut();
+ }
+
+ // aggregation
+ inline std::string _addChild(Arts::Object child, const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_addChild(child, name);
+ }
+ inline bool _removeChild(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_removeChild(name);
+ }
+ inline Arts::Object _getChild(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_getChild(name);
+ }
+ inline std::vector<std::string> * _queryChildren() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryChildren();
+ }
+ // Do we really need those in the Wrapper?
+ // And would it really be sensible to make _cast wrappers?
+/* inline void _release() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_release();
+ }
+ inline Object_base *_copy() const {
+ _poo->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_copy();
+ }
+*/
+
+ // Object::null() returns a null object (and not just a reference to one)
+ inline static Object null() {return Object((Object_base*)0);}
+ inline static Object _from_base(Object_base* b) {return Object(b);}
+};
+
+// Enables a different constructor, that should do the cast
+class ARTS_EXPORT DynamicCast {
+private:
+ Object obj;
+public:
+ inline explicit DynamicCast(const Object& o) : obj(o) {}
+ inline const Object& object() const {return obj;}
+};
+
+}
+
+#endif
diff --git a/mcop/referenceclean.cc b/mcop/referenceclean.cc
new file mode 100644
index 0000000..58e7001
--- /dev/null
+++ b/mcop/referenceclean.cc
@@ -0,0 +1,87 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "referenceclean.h"
+#include "time.h"
+
+using namespace std;
+using namespace Arts;
+
+ReferenceClean::ReferenceClean(Pool<Object_skel>& objectPool)
+ :objectPool(objectPool)
+{
+ Dispatcher::the()->ioManager()->addTimer(5000, this);
+}
+
+void ReferenceClean::notifyTime()
+{
+ /*
+ * This last_notify and now check is because IOManager accumulates
+ * notifyTime() calls, so it may happen that we don't get one for ten
+ * seconds, and then two. However, this breaks the "second-chance"
+ * algorithm referenceClean is using, which depends on the fact that
+ * there is some significant time delay between two calls. So we'll
+ * verify it by hand.
+ */
+
+ static time_t last_notify = 0;
+ time_t now;
+
+ time(&now);
+ if(now-last_notify > 4)
+ {
+ clean();
+ last_notify = now;
+ }
+}
+
+void ReferenceClean::forceClean()
+{
+ /*
+ * as we're giving a second chance on reference clean, we need to
+ * clean twice to really really clean up
+ */
+ clean();
+ clean();
+}
+
+void ReferenceClean::clean()
+{
+ /*
+ * we manually iterate through the pool here, to get around the problem
+ * that if an object disappears, ten other objects might cease to exist
+ * as well (as they are dependant), which would break a list which we
+ * could obtain via enumerate() and would probably lead to a crash
+ */
+ unsigned long l;
+
+ for(l=0; l<objectPool.max(); l++)
+ {
+ Object_skel *skel = objectPool[l];
+ if(skel) skel->_referenceClean();
+ }
+}
+
+ReferenceClean::~ReferenceClean()
+{
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
diff --git a/mcop/referenceclean.h b/mcop/referenceclean.h
new file mode 100644
index 0000000..13b6ec7
--- /dev/null
+++ b/mcop/referenceclean.h
@@ -0,0 +1,60 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): ReferenceClean
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. Can be changed arbitrarily even non BC.
+ */
+
+#ifndef REFERENCECLEAN_H
+#define REFERENCECLEAN_H
+
+#include "iomanager.h"
+#include "dispatcher.h"
+
+namespace Arts {
+
+class ReferenceClean : public TimeNotify {
+ Pool<Object_skel>& objectPool;
+protected:
+ void clean();
+
+public:
+ ReferenceClean(Pool<Object_skel>& objectPool);
+
+ /**
+ * this routine forces cleaning of all tagged remote objects
+ *
+ * it will be called on dispatcher shutdown, since after this there
+ * is no remote interaction anyway, it is be used to prevent memory
+ * leaks
+ */
+ void forceClean();
+
+ void notifyTime();
+ virtual ~ReferenceClean();
+};
+
+}
+#endif
diff --git a/mcop/socketconnection.cc b/mcop/socketconnection.cc
new file mode 100644
index 0000000..f3bc3e8
--- /dev/null
+++ b/mcop/socketconnection.cc
@@ -0,0 +1,205 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "tcpconnection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#define queue cqueue
+#include <netdb.h>
+#undef queue
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#undef DEBUG_CONNECTION_DATA
+
+using namespace Arts;
+
+/*
+ * These parameters impact the performance significantly. There are two sides:
+ *
+ * when you use too large buffers for reading/writing
+ * - it may be, that each operation takes too long, so that for instance
+ * an important real time audio job drops during that time
+ * - it may be, that dealing with large buffers (allocation, cache, etc)
+ * itself causes a penalty
+ *
+ * on the other hand, small buffers lead to repeated operating system calls,
+ * which is bad especially if you even go through all the chain: check what
+ * can be written with select, invoke the corresponding object, actually
+ * read (or write), do messages, do timers, go sleep again on select.
+ */
+static const int MCOP_MAX_READ_SIZE=8192;
+static const int MCOP_MAX_WRITE_SIZE=8192;
+
+SocketConnection::SocketConnection()
+{
+}
+
+SocketConnection::SocketConnection(int _fd)
+ : fd(_fd), _broken(false)
+{
+ arts_debug("socketconnection created, fd = %d",fd);
+ Dispatcher::the()->ioManager()->watchFD(fd,
+ IOType::read|IOType::except|IOType::reentrant,this);
+ initReceive();
+}
+
+void SocketConnection::qSendBuffer(Buffer *buffer)
+{
+ if(_broken)
+ {
+ // forget it ;) - no connection there any longer
+ delete buffer;
+ return;
+ }
+ if(pending.size() == 0)
+ {
+ // if there is nothing pending already, it may be that we are lucky
+ // and can write the buffer right now without blocking
+
+ writeBuffer(buffer);
+ if(!buffer->remaining())
+ {
+ delete buffer;
+ return;
+ }
+
+ // but if it blocks, we'll need to watch for write chances to send
+ // that buffer later
+ Dispatcher::the()->ioManager()->watchFD(fd,IOType::write|IOType::reentrant,this);
+ }
+ pending.push_back(buffer);
+}
+
+#ifdef DEBUG_CONNECTION_DATA
+static void connection_hex_dump(unsigned char *buffer, long len)
+{
+ int i = 0;
+ printf("Connection: received %ld bytes:\n\n",len);
+ while (i < len)
+ {
+ unsigned int j, n, d[16];
+
+ for (n = 0; n < 16; n++)
+ if (i < len)
+ d[n] = buffer[i++];
+ else
+ break;
+ printf (" ");
+
+ for (j = 0; j < n; j++) printf ("%s %02x", j == 8 ? " " : "", d[j]);
+ for (; j < 16; j++) printf ("%s ", j == 8 ? " " : "");
+ printf (" ");
+
+ for (j = 0; j < n; j++)
+ printf ("%c", d[j] >= 32 ? d[j] : '.');
+ printf ("\n");
+ }
+}
+#endif
+
+void SocketConnection::notifyIO(int _fd, int types)
+{
+ assert(_fd == fd);
+
+ if(types & IOType::read)
+ {
+ unsigned char buffer[MCOP_MAX_READ_SIZE];
+ long n = read(fd,buffer,MCOP_MAX_READ_SIZE);
+
+#ifdef DEBUG_CONNECTION_DATA
+ connection_hex_dump(buffer,n);
+#endif
+
+ if(n > 0)
+ {
+ receive(buffer,n);
+ // warning: the object may not exist any more here!
+ return;
+ }
+ else if(n == 0 /* remote end closed connection */
+ || (n == -1 && errno != EAGAIN && errno != EINTR)) /* some error */
+ {
+ close(fd);
+ _broken = true;
+ Dispatcher::the()->ioManager()->remove(this,IOType::all);
+
+ Dispatcher::the()->handleConnectionClose(this);
+ // warning: the object may not exist any more here!
+ return;
+ }
+ }
+
+ if(types & IOType::write)
+ {
+ assert(pending.size() != 0);
+
+ Buffer *pbuffer = *pending.begin();
+ if(pbuffer->remaining()) writeBuffer(pbuffer);
+
+ // no else => it could have been sent in the if(..remaining..) above
+ if(!pbuffer->remaining())
+ {
+ delete pbuffer;
+ pending.pop_front();
+
+ if(pending.size() == 0)
+ Dispatcher::the()->ioManager()->remove(this,IOType::write);
+ }
+ }
+
+ if(types & IOType::except)
+ {
+ assert(false);
+ }
+}
+
+void SocketConnection::writeBuffer(Buffer *buffer)
+{
+ long len = MCOP_MAX_WRITE_SIZE;
+ if(buffer->remaining() < len) len = buffer->remaining();
+
+ void *data = buffer->peek(len);
+ long written = write(fd,data,len);
+
+ if(written > 0)
+ buffer->skip(len);
+}
+
+bool SocketConnection::broken()
+{
+ return _broken;
+}
+
+void SocketConnection::drop()
+{
+ if(!_broken)
+ {
+ close(fd);
+ _broken = true;
+ Dispatcher::the()->ioManager()->remove(this,IOType::all);
+ }
+}
diff --git a/mcop/socketconnection.h b/mcop/socketconnection.h
new file mode 100644
index 0000000..aaeaeb2
--- /dev/null
+++ b/mcop/socketconnection.h
@@ -0,0 +1,64 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): SocketConnection
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. No BC guaranteed.
+ */
+
+#ifndef SOCKETCONNECTION_H
+#define SOCKETCONNECTION_H
+
+#include "buffer.h"
+#include "iomanager.h"
+#include "connection.h"
+#include <list>
+#include <string>
+
+namespace Arts {
+
+class SocketConnection :public Connection, public IONotify {
+protected:
+ std::string serverID;
+ int fd;
+ bool _broken;
+
+ std::list<Buffer *> pending;
+ void writeBuffer(Buffer *buffer);
+
+ SocketConnection();
+
+public:
+ SocketConnection(int _fd);
+
+ void qSendBuffer(Buffer *buffer);
+ void notifyIO(int _fd, int types);
+
+ void drop();
+ bool broken();
+};
+
+}
+
+#endif /* SOCKETCONNECTION_H */
diff --git a/mcop/startupmanager.cc b/mcop/startupmanager.cc
new file mode 100644
index 0000000..89daf16
--- /dev/null
+++ b/mcop/startupmanager.cc
@@ -0,0 +1,150 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "startupmanager.h"
+#include "extensionloader.h"
+#include "debug.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * StartupClass implementation
+ */
+
+StartupClass::StartupClass()
+{
+ StartupManager::add(this);
+}
+
+void StartupClass::shutdown()
+{
+ // shutdown is optional, startup is mandatory
+}
+
+/*
+ * StartupManager implementation
+ */
+
+list<StartupClass *> *StartupManager::startupClasses = 0;
+ExtensionLoader *StartupManager::activeExtensionLoader = 0;
+bool StartupManager::running = false;
+
+void StartupManager::add(StartupClass *sc)
+{
+ if(activeExtensionLoader)
+ {
+ activeExtensionLoader->addStartupClass(sc);
+ }
+ else
+ {
+ if(running)
+ {
+ /*
+ * the problem with adding a StartupClass when we're already running
+ * is that we can't execute the startup() function immediately (for
+ * this might break the dependancy of the StartupClass on other
+ * globally constructed objects)
+ *
+ * so will never execute it, which is likely to break something
+ * else (i.e. implementations defined in the library the startup
+ * class is contained in can't be found)
+ *
+ * usually, this warning is triggered when an application
+ * dynamically loads a library containing StartupClasses, without
+ * libmcop knowing about it
+ */
+ arts_warning("MCOP StartupManager: adding a StartupClass after Dispatcher init will not work.");
+ }
+
+ if(!startupClasses) startupClasses = new list<StartupClass *>;
+
+ startupClasses->push_back(sc);
+ }
+}
+
+void StartupManager::setExtensionLoader(ExtensionLoader *extension)
+{
+ /*
+ * this is not reentrant: you can't load two extensions at the same time,
+ * and it is impossible that an extension loads an extension while being
+ * loaded (nothing forbids you to load another extension from an extension
+ * in a StartupClass or any time later - just don't do it while being
+ * lt_dlopen()d
+ */
+ if(activeExtensionLoader)
+ arts_assert(extension == 0);
+ else
+ arts_assert(extension != 0);
+
+ activeExtensionLoader = extension;
+}
+
+void StartupManager::startup()
+{
+ arts_return_if_fail(running == false);
+ running = true;
+
+ if(startupClasses)
+ {
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses->begin(); i != startupClasses->end(); i++)
+ (*i)->startup();
+ }
+}
+
+void StartupManager::shutdown()
+{
+ arts_return_if_fail(running == true);
+ running = false;
+
+ if(startupClasses)
+ {
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses->begin(); i != startupClasses->end(); i++)
+ (*i)->shutdown();
+ }
+}
+
+void StartupManager::internalFreeAll()
+{
+ if(startupClasses)
+ {
+ startupClasses->erase(startupClasses->begin(),startupClasses->end());
+
+ delete startupClasses;
+ startupClasses = 0;
+ }
+}
+
+namespace Arts {
+
+static class StartupManagerFree {
+public:
+ ~StartupManagerFree() { StartupManager::internalFreeAll(); }
+} The_StartupManagerFree;
+
+}
diff --git a/mcop/startupmanager.h b/mcop/startupmanager.h
new file mode 100644
index 0000000..028b421
--- /dev/null
+++ b/mcop/startupmanager.h
@@ -0,0 +1,75 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef STARTUPMANAGER_H
+#define STARTUPMANAGER_H
+
+#include "arts_export.h"
+
+#include <list>
+
+/*
+ * BC - Status (2002-03-08): StartupClass, StartupManager.
+ *
+ * The class needs to be kept BC, as the startup system bases on inheritance
+ * and virtual functions. Do not change.
+ *
+ * The manager is a collection class without nonstatic data, so no BC issues
+ * here.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT StartupClass {
+public:
+ StartupClass();
+ virtual void startup() = 0;
+ virtual void shutdown();
+};
+
+class StartupManager {
+ static std::list<StartupClass *> *startupClasses;
+ static class ExtensionLoader *activeExtensionLoader;
+ static bool running;
+public:
+ static void add(StartupClass *sc);
+ static void startup();
+ static void shutdown();
+
+ /**
+ * since extensions will register startup classes in the same global way
+ * all other classes do (with StartupManager::add(<some startup class>)),
+ * the StartupManager supports forwarding all add requests to the
+ * active extension, which will allow synchronizing the lt_dlopen
+ * lt_dlclose with the calls of startup()/shutdown() of all StartupClasses
+ * present in the extension
+ */
+ static void setExtensionLoader(class ExtensionLoader *extension);
+
+ /**
+ * to free all resources when the application terminates (internal use only)
+ */
+ static void internalFreeAll();
+};
+
+}
+#endif /* STARTUPMANAGER_H */
diff --git a/mcop/tcpconnection.cc b/mcop/tcpconnection.cc
new file mode 100644
index 0000000..e0c086e
--- /dev/null
+++ b/mcop/tcpconnection.cc
@@ -0,0 +1,152 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "tcpconnection.h"
+#include "dispatcher.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#define queue cqueue
+#include <netdb.h>
+#undef queue
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <errno.h>
+#include "debug.h"
+#include <stdlib.h>
+
+using namespace std;
+using namespace Arts;
+
+static struct sockaddr_in *parse_tcp_url(const char *url)
+{
+ static struct sockaddr_in addr;
+
+ char *work = strdup(url);
+
+ char *type = strtok(work,":");
+ if(type == 0 || strcmp(type,"tcp") != 0) {
+ free(work);
+ return 0;
+ }
+
+ char *host = strtok(NULL,":");
+ if(host == 0) {
+ free(work);
+ return 0;
+ }
+
+ char *port = strtok(NULL,":\n");
+ if(port == 0) {
+ free(work);
+ return 0;
+ }
+
+ long portno = atol(port);
+ if(portno < 1 || portno > 65535) {
+ free(work);
+ return 0;
+ }
+
+ struct hostent *server = gethostbyname(host);
+ if(server == 0)
+ {
+ arts_warning("parse_tcp_url: unknown host '%s'",host);
+ free(work);
+ return 0;
+ }
+
+ memset((void *) &addr, '\0', sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = *(u_long *)server->h_addr;
+ addr.sin_port = htons(portno);
+
+ free(work);
+ return &addr;
+}
+
+static int tcp_connect(const char *url)
+{
+ struct sockaddr_in *remote_addr = parse_tcp_url(url);
+ if(remote_addr == 0)
+ {
+ arts_warning("tcp_connect: couldn't parse url %s",url);
+ return -1;
+ }
+
+ int my_socket = socket(AF_INET,SOCK_STREAM,0);
+ if(my_socket < 0)
+ {
+ arts_warning("tcp_connect: unable to open socket for read");
+ return -1;
+ }
+
+ struct linger lin;
+ lin.l_onoff=1; /* block a closing socket for 1 second */
+ lin.l_linger=100; /* if data is waiting to be sent */
+ if ( setsockopt( my_socket, SOL_SOCKET, SO_LINGER,
+ (char*)&lin, sizeof(struct linger) ) < 0 )
+ {
+ arts_warning("tcp_connect: unable to set socket linger value to %d",
+ lin.l_linger);
+ close(my_socket);
+ return -1;
+ }
+
+#ifdef TCP_NODELAY
+ // enable TCP sending without nagle algorithm - this sends out requests
+ // faster, because they are not queued in the hope that more data will
+ // need to be sent soon
+ int on = 1;
+ if(setsockopt(my_socket, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&on, sizeof(on)) < 0)
+ {
+ arts_debug("couldn't set TCP_NODELAY on socket %d\n", my_socket);
+ }
+#endif
+
+ int rc;
+ rc=connect(my_socket,(struct sockaddr *)remote_addr, sizeof(*remote_addr));
+ if(rc != 0)
+ {
+ arts_warning("tcp_connect: can't connect to server (%s)", url);
+ close(my_socket);
+ return -1;
+ }
+
+ return my_socket;
+}
+
+TCPConnection::TCPConnection(const string& url)
+{
+ fd = tcp_connect(url.c_str());
+ _broken = (fd == -1);
+
+ if(!_broken)
+ {
+ Dispatcher::the()->ioManager()->watchFD(fd,
+ IOType::read|IOType::except|IOType::reentrant,this);
+ initReceive();
+ }
+}
diff --git a/mcop/tcpconnection.h b/mcop/tcpconnection.h
new file mode 100644
index 0000000..654bfe2
--- /dev/null
+++ b/mcop/tcpconnection.h
@@ -0,0 +1,43 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): TCPConnection
+ *
+ * Not part of the public API. Do NOT use it in your apps. Binary incompatible
+ * changes allowed.
+ */
+
+#ifndef TCPCONNECTION_H
+#define TCPCONNECTION_H
+
+#include "socketconnection.h"
+
+namespace Arts {
+
+class TCPConnection :public SocketConnection {
+public:
+ TCPConnection(const std::string& url);
+};
+
+}
+#endif /* TCPCONNECTION_H */
diff --git a/mcop/tcpserver.cc b/mcop/tcpserver.cc
new file mode 100644
index 0000000..d62e28c
--- /dev/null
+++ b/mcop/tcpserver.cc
@@ -0,0 +1,193 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "tcpserver.h"
+#include "socketconnection.h"
+#include "dispatcher.h"
+#define queue cqueue
+#include <arpa/inet.h>
+#undef queue
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "mcoputils.h"
+#include "debug.h"
+
+using namespace std;
+using namespace Arts;
+
+bool TCPServer::running()
+{
+ return socketOk;
+}
+
+TCPServer::TCPServer(Dispatcher *dispatcher)
+{
+ this->dispatcher = dispatcher;
+
+ socketOk = initSocket();
+ if(socketOk) {
+ IOManager *iom = dispatcher->ioManager();
+ iom->watchFD(theSocket,IOType::read|IOType::except,this);
+ }
+}
+
+TCPServer::~TCPServer()
+{
+ if(socketOk)
+ {
+ IOManager *iom = dispatcher->ioManager();
+ iom->remove(this,IOType::read|IOType::except);
+ close(theSocket);
+ }
+}
+
+static int TCPServerPort = 0;
+
+void TCPServer::setPort(int port)
+{
+ TCPServerPort = port;
+}
+
+bool TCPServer::initSocket()
+{
+ struct sockaddr_in socket_addr;
+
+ theSocket = socket(PF_INET,SOCK_STREAM,0);
+ if(theSocket < 0)
+ {
+ arts_warning("MCOP TCPServer: can't create a socket");
+ return false;
+ }
+
+ if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0)
+ {
+ arts_warning("MCOP TCPServer: can't initialize non blocking I/O");
+ close(theSocket);
+ return false;
+ }
+
+ if (TCPServerPort)
+ {
+ int optval = 1;
+ if(setsockopt (theSocket, SOL_SOCKET, SO_REUSEADDR,
+ (const char *)&optval, sizeof (optval)) < 0)
+ {
+ arts_warning("MCOP TCPServer: can't set address reuse");
+ close(theSocket);
+ return false;
+ }
+ }
+
+#ifdef TCP_NODELAY
+ // enable TCP sending without nagle algorithm - this sends out requests
+ // faster, because they are not queued in the hope that more data will
+ // need to be sent soon
+ int on = 1;
+ if(setsockopt(theSocket, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&on, sizeof(on)) < 0)
+ {
+ arts_debug("couldn't set TCP_NODELAY on socket %d\n", theSocket);
+ }
+#endif
+
+ socket_addr.sin_family = AF_INET;
+ socket_addr.sin_port = htons( TCPServerPort ); // 0 = choose port freely
+ socket_addr.sin_addr.s_addr = htonl( inet_addr("0.0.0.0") );
+ if ( bind( theSocket, (struct sockaddr *) &socket_addr,
+ sizeof(struct sockaddr_in) ) < 0 )
+ {
+ arts_warning("MCOP TCPServer: can't bind to port/address");
+ close(theSocket);
+ return false;
+ }
+
+ socklen_t sz = sizeof(struct sockaddr_in);
+ int r = getsockname (theSocket,(struct sockaddr *)&socket_addr, &sz);
+ if(r == 0) {
+ thePort = ntohs(socket_addr.sin_port);
+ }
+ else
+ {
+ arts_warning("MCOP TCPServer: getsockname failed");
+ close(theSocket);
+ return false;
+ }
+
+ if(listen(theSocket,16) < 0)
+ {
+ arts_warning("MCOP TCPServer: can't listen on the socket");
+ close(theSocket);
+ return false;
+ }
+
+ arts_debug("TCPServer: listening on '%s'", url().c_str());
+ return true;
+}
+
+string TCPServer::url()
+{
+ char xport[200];
+ sprintf(xport,"%d",thePort);
+
+ return "tcp:"+MCOPUtils::getFullHostname()+":"+xport;
+}
+
+void TCPServer::notifyIO(int fd, int types)
+{
+ assert(fd == theSocket);
+ assert(socketOk);
+
+ arts_debug("TCPManager: got notifyIO");
+ if(types & IOType::read)
+ {
+ int clientfd;
+ struct sockaddr_in incoming;
+ socklen_t size_in = sizeof(struct sockaddr_in);
+
+ clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in );
+ if(clientfd > 0)
+ {
+ // non blocking I/O
+ int flags = fcntl (fd, F_GETFL, 0);
+ assert (flags != -1);
+
+ int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+ assert(nbl_result >= 0);
+
+ Dispatcher::the()->initiateConnection(
+ new SocketConnection(clientfd));
+ }
+ }
+ arts_assert((types & IOType::write) == 0);
+ arts_assert((types & IOType::except) == 0);
+}
+
+// vim: sw=4 ts=4
diff --git a/mcop/tcpserver.h b/mcop/tcpserver.h
new file mode 100644
index 0000000..93cecca
--- /dev/null
+++ b/mcop/tcpserver.h
@@ -0,0 +1,61 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef TCPSERVER_H
+#define TCPSERVER_H
+
+#include <string>
+#include "arts_export.h"
+#include "iomanager.h"
+/*
+ * BC - Status (2002-03-08): TCPServer
+ *
+ * Not part of the public API. Do NOT use it in your apps. Binary incompatible
+ * changes allowed.
+ */
+
+namespace Arts {
+
+class Dispatcher;
+
+class ARTS_EXPORT TCPServer :public IONotify {
+protected:
+ Dispatcher *dispatcher;
+
+ int theSocket;
+ int thePort;
+ bool socketOk;
+ bool initSocket();
+
+public:
+ TCPServer(Dispatcher *dispatcher);
+ virtual ~TCPServer();
+ bool running();
+ std::string url();
+ static void setPort(int port);
+
+ void notifyIO(int fd, int types);
+};
+
+}
+
+#endif /* TCPSERVER_H */
diff --git a/mcop/thread.cc b/mcop/thread.cc
new file mode 100644
index 0000000..2d81118
--- /dev/null
+++ b/mcop/thread.cc
@@ -0,0 +1,169 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "thread.h"
+#include <string.h>
+
+using namespace Arts;
+
+// Thread:
+Thread::~Thread()
+{
+ delete impl;
+}
+
+Thread_impl::~Thread_impl()
+{
+}
+
+// Mutex:
+Mutex::~Mutex()
+{
+ delete impl;
+}
+
+Mutex_impl::~Mutex_impl()
+{
+}
+
+// ThreadCondition:
+
+ThreadCondition::~ThreadCondition()
+{
+ delete impl;
+}
+
+ThreadCondition_impl::~ThreadCondition_impl()
+{
+}
+
+// Semaphore
+Semaphore::~Semaphore()
+{
+ delete impl;
+}
+
+Semaphore_impl::~Semaphore_impl()
+{
+}
+
+// No threading:
+
+namespace Arts {
+
+class SystemThreadsNoMutex_impl : public Mutex_impl {
+public:
+ void lock() {};
+ bool tryLock() { return true; };
+ void unlock() {};
+};
+
+static Thread *systemThreadsNoneCurrent = 0;
+
+class SystemThreadsNoThread_impl : public Thread_impl {
+private:
+ Thread *thread;
+public:
+ SystemThreadsNoThread_impl(Thread *thread) : thread(thread) {}
+ void setPriority(int) {}
+ void start() {
+ Thread *oldCurrent = systemThreadsNoneCurrent;
+
+ systemThreadsNoneCurrent = thread;
+ thread->run();
+ systemThreadsNoneCurrent = oldCurrent;
+ }
+ void waitDone() {}
+};
+
+class SystemThreadsNoThreadCondition_impl : public ThreadCondition_impl {
+public:
+ void wakeOne() {};
+ void wakeAll() {};
+ void wait(Mutex_impl *) {};
+};
+
+class SystemThreadsNoSemaphore_impl : public Semaphore_impl {
+public:
+ void wait() {}
+ int tryWait() { return 0; }
+ void post() {}
+ int getValue() { return 0; }
+};
+
+class SystemThreadsNone : public SystemThreads {
+public:
+ bool isMainThread() {
+ return (systemThreadsNoneCurrent == 0);
+ }
+ Mutex_impl *createMutex_impl() {
+ return new SystemThreadsNoMutex_impl();
+ }
+ Mutex_impl *createRecMutex_impl() {
+ return new SystemThreadsNoMutex_impl();
+ }
+ Thread_impl *createThread_impl(Thread *thread) {
+ return new SystemThreadsNoThread_impl(thread);
+ }
+ ThreadCondition_impl *createThreadCondition_impl() {
+ return new SystemThreadsNoThreadCondition_impl();
+ }
+ Thread *getCurrentThread() {
+ return systemThreadsNoneCurrent;
+ }
+ Semaphore_impl *createSemaphore_impl(int, int) {
+ return new SystemThreadsNoSemaphore_impl();
+ }
+};
+
+}
+
+static SystemThreadsNone systemThreadsNone;
+static SystemThreads *SystemThreads_the = 0;
+
+SystemThreads *SystemThreads::the()
+{
+ if(!SystemThreads_the) return &systemThreadsNone;
+ return SystemThreads_the;
+}
+
+bool SystemThreads::init(SystemThreads *the)
+{
+ if(SystemThreads_the)
+ return false;
+ else
+ {
+ SystemThreads_the = the;
+ return true;
+ }
+}
+
+bool SystemThreads::supported()
+{
+ return (SystemThreads_the != 0);
+}
+
+SystemThreads::~SystemThreads()
+{
+}
+
+namespace Arts { void ARTS_EXPORT *gslGlobalMutexTable = 0; }
diff --git a/mcop/thread.h b/mcop/thread.h
new file mode 100644
index 0000000..882e596
--- /dev/null
+++ b/mcop/thread.h
@@ -0,0 +1,375 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_MCOP_THREAD_H
+#define ARTS_MCOP_THREAD_H
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): SystemThreads, Thread, Mutex, ThreadCondition,
+ * Semaphore
+ *
+ * These classes are kept binary compatible. As the threading implementation
+ * can be changed, also
+ *
+ * Thread_impl, Mutex_impl, ThreadCondition_impl and Semaphore_impl need
+ * to remain as they are. The implementation of these depends on what thread
+ * system is used, and can attach the required data as necessary to the
+ * base classes. So i.e. a posix mutex can contain the pthread_mutex_t in
+ * the PosixMutex_impl.
+ */
+
+namespace Arts {
+
+class Mutex_impl;
+class Thread_impl;
+class ThreadCondition_impl;
+class Thread;
+class Semaphore_impl;
+
+/**
+ * Encapsulates the operating system threading facilities
+ */
+class ARTS_EXPORT SystemThreads {
+public:
+ static SystemThreads *the();
+ static bool init(SystemThreads *the);
+
+ /**
+ * Check whether there is threading support available
+ *
+ * If there is no real threading support, the Threading classes try to
+ * gracefully degrade the performance. For instance, locking a mutex will
+ * do * nothing, and calling the start() function of a Thread will execute
+ * it's run function.
+ *
+ * @returns true if there are real threads
+ */
+ static bool supported();
+
+ /**
+ * Check wether the current thread is the main thread
+ *
+ * The main thread is the thread that the application's main() was
+ * executed in. The IOManager event loop will only run in the main
+ * thread.
+ */
+ virtual bool isMainThread() = 0;
+
+ virtual Mutex_impl *createMutex_impl() = 0;
+ virtual Mutex_impl *createRecMutex_impl() = 0;
+ virtual Thread_impl *createThread_impl(Thread *thread) = 0;
+ virtual ThreadCondition_impl *createThreadCondition_impl() = 0;
+ virtual Semaphore_impl *createSemaphore_impl(int, int) = 0;
+ virtual ~SystemThreads();
+
+ /**
+ * Returns a pointer to the current thread, or a null pointer if
+ * we're the main thread (isMainThread() is true).
+ */
+ virtual Thread *getCurrentThread() = 0;
+};
+
+/**
+ * Base class for platform specific thread code
+ */
+class ARTS_EXPORT Thread_impl
+{
+public:
+ virtual void setPriority(int) =0;
+ virtual void start() = 0;
+ virtual void waitDone() = 0;
+ virtual ~Thread_impl();
+};
+
+/**
+ * Base class for platform specific mutex code
+ */
+class ARTS_EXPORT Mutex_impl {
+public:
+ virtual void lock() = 0;
+ virtual bool tryLock() = 0;
+ virtual void unlock() = 0;
+ virtual ~Mutex_impl();
+};
+
+/**
+ * Base class for platform specific thread condition code
+ */
+class ARTS_EXPORT ThreadCondition_impl {
+public:
+ virtual void wakeOne() = 0;
+ virtual void wakeAll() = 0;
+ virtual void wait(Mutex_impl *impl) = 0;
+ virtual ~ThreadCondition_impl();
+};
+
+class ARTS_EXPORT Semaphore_impl {
+public:
+ virtual void wait() = 0;
+ virtual int tryWait() = 0;
+ virtual void post() = 0;
+ virtual int getValue() = 0;
+ virtual ~Semaphore_impl();
+};
+
+/**
+ * A thread of execution
+ *
+ * Example for implementing a thread:
+ *
+ * <pre>
+ * class Counter : public Arts::Thread
+ * {
+ * public:
+ * void run() {
+ * for(int i = 0;i < 10;i++)
+ * {
+ * printf("%d\n",i+1);
+ * sleep(1);
+ * }
+ * }
+ * }; // start the thread with Counter c; c.start();
+ * </pre>
+ */
+class ARTS_EXPORT Thread {
+private:
+ Thread_impl *impl;
+
+public:
+ Thread() : impl(SystemThreads::the()->createThread_impl(this))
+ {
+ }
+
+ virtual ~Thread();
+
+ /**
+ * set the priority parameters for the thread
+ *
+ * FIXME: what should be minimum, maximum, recommended?
+ */
+ inline void setPriority(int priority) {
+ impl->setPriority(priority);
+ }
+
+ /**
+ * starts the run() method in a thread
+ */
+ inline void start()
+ {
+ impl->start();
+ }
+
+ /**
+ * waits until the thread is executed completely
+ */
+ inline void waitDone()
+ {
+ impl->waitDone();
+ }
+
+ /**
+ * implement this method, if you want to create an own thread - then
+ * you can simply call thread.start() to start execution of run() in
+ * a seperate thread
+ */
+ virtual void run() = 0;
+};
+
+/**
+ * A mutex
+ *
+ * To protect a critical section, you can use a mutex, which will ensure that
+ * only one thread at a time can lock it. Here is an example for a thread-safe
+ * random number generator:
+ *
+ * <pre>
+ * class RandomGenerator {
+ * Arts::Mutex mutex;
+ * long seed;
+ * public:
+ * long get() {
+ * mutex.lock();
+ * // do complicated calculation with seed here
+ * mutex.unlock();
+ * return seed;
+ * }
+ * };
+ * </pre>
+ */
+class ARTS_EXPORT Mutex {
+private:
+ Mutex_impl *impl;
+ friend class ThreadCondition;
+
+public:
+ /**
+ * constructor
+ *
+ * @param recursive whether to create a recursive mutex (may be locked by
+ * the same thread more than once), or a normal mutex
+ */
+ inline Mutex(bool recursive = false)
+ : impl(recursive?SystemThreads::the()->createRecMutex_impl()
+ :SystemThreads::the()->createMutex_impl())
+ {
+ }
+
+ /**
+ * destructor
+ */
+ virtual ~Mutex();
+
+ /**
+ * locks the mutex
+ */
+ inline void lock() {
+ impl->lock();
+ }
+
+ /**
+ * tries to lock the mutex, returning immediately in any case (even if
+ * mutex is locked by another thread)
+ *
+ * @returns true if successful (mutex locked), false otherwise
+ */
+ inline bool tryLock() {
+ return impl->tryLock();
+ }
+
+ /**
+ * unlocks the mutex
+ */
+ inline void unlock() {
+ impl->unlock();
+ }
+};
+
+/**
+ * A thread condition
+ *
+ * Thread conditions are used to let a different thread know that a certain
+ * condition might have changed. For instance, if you have a thread that
+ * waits until a counter exceeds a limit, the thread would look like this:
+ *
+ * <pre>
+ * class WaitCounter : public Arts::Thread
+ * {
+ * int counter;
+ * Arts::Mutex mutex;
+ * Arts::ThreadCondition cond;
+ *
+ * public:
+ * WaitCounter() : counter(0) {}
+ *
+ * void run() { // run will terminate once the counter reaches 20
+ * mutex.lock();
+ * while(counter < 20)
+ * cond.wait(mutex);
+ * mutex.unlock();
+ * }
+ *
+ * void inc() { // inc will increment the counter and indicate the change
+ * mutex.lock();
+ * counter++;
+ * cond.wakeOne();
+ * mutex.unlock();
+ * }
+ * };
+ * </pre>
+ */
+class ARTS_EXPORT ThreadCondition {
+private:
+ ThreadCondition_impl *impl;
+
+public:
+ ThreadCondition()
+ : impl(SystemThreads::the()->createThreadCondition_impl())
+ {
+ }
+
+ virtual ~ThreadCondition();
+
+ /**
+ * wakes one waiting thread
+ */
+ inline void wakeOne()
+ {
+ impl->wakeOne();
+ }
+
+ /**
+ * wakes all waiting threads
+ */
+ inline void wakeAll()
+ {
+ impl->wakeAll();
+ }
+
+ /**
+ * Waits until the condition changes. You will need to lock the mutex
+ * before calling this. Internally it will unlock the mutex (to let
+ * others change the condition), and relock it once the wait succeeds.
+ */
+ inline void wait(Mutex& mutex)
+ {
+ impl->wait(mutex.impl);
+ }
+};
+
+class ARTS_EXPORT Semaphore {
+private:
+ Semaphore_impl *impl;
+
+public:
+ Semaphore(int shared=0, int count=0)
+ {
+ impl = SystemThreads::the()->createSemaphore_impl(shared, count);
+ }
+
+ virtual ~Semaphore();
+
+ inline void wait()
+ {
+ impl->wait();
+ }
+
+ inline int tryWait()
+ {
+ return impl->tryWait();
+ }
+
+ inline void post()
+ {
+ impl->post();
+ }
+
+ inline int getValue()
+ {
+ return impl->getValue();
+ }
+};
+
+}
+
+#endif /* ARTS_MCOP_THREAD_H */
diff --git a/mcop/tmpglobalcomm.cc b/mcop/tmpglobalcomm.cc
new file mode 100644
index 0000000..9332bce
--- /dev/null
+++ b/mcop/tmpglobalcomm.cc
@@ -0,0 +1,82 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "common.h"
+#include "mcoputils.h"
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class TmpGlobalComm_impl : virtual public TmpGlobalComm_skel {
+public:
+ bool put(const string& variable, const string& value)
+ {
+ string filename = MCOPUtils::createFilePath(variable);
+
+ int fd = open(filename.c_str(),O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR);
+ if(fd != -1)
+ {
+ int result = write(fd,value.c_str(),value.size());
+
+ assert(result == (int)value.size());
+ close(fd);
+ return true;
+ }
+
+ return false;
+ }
+
+ string get(const string& variable)
+ {
+ string result = "";
+ string filename = MCOPUtils::createFilePath(variable);
+
+ int fd = open(filename.c_str(),O_RDONLY);
+ if(fd != -1)
+ {
+ char buffer[8192];
+ int size = read(fd,buffer,8192);
+ if(size > 0 && size < 8192) {
+ buffer[size] = 0;
+ result = buffer;
+ }
+
+ close(fd);
+ }
+ return result;
+ }
+
+ void erase(const string& variable)
+ {
+ string filename = MCOPUtils::createFilePath(variable);
+ unlink(filename.c_str());
+ }
+};
+
+REGISTER_IMPLEMENTATION(TmpGlobalComm_impl);
+
+}
diff --git a/mcop/trader_impl.cc b/mcop/trader_impl.cc
new file mode 100644
index 0000000..6dd84bd
--- /dev/null
+++ b/mcop/trader_impl.cc
@@ -0,0 +1,345 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "common.h"
+#include "debug.h"
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <cstring>
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+
+// TraderRestriction
+struct TraderRestriction {
+ TraderRestriction(const string& key, const string& value)
+ :key(key), value(value) { }
+
+ string key;
+ string value;
+};
+
+// TraderHelper (internal, no public interface)
+class TraderHelper {
+private:
+ vector<class TraderOffer_impl *> allOffers;
+ static TraderHelper *_instance;
+
+protected:
+ TraderHelper();
+ ~TraderHelper();
+ void addDirectory(const string& directory, const string& iface = "",
+ map< pair<dev_t,ino_t>, bool > *dirsDone = 0);
+
+public:
+ vector<TraderOffer> *doQuery(const vector<TraderRestriction>& query);
+ void load();
+ void unload();
+ static TraderHelper *the();
+ static void shutdown();
+};
+
+// TraderQuery
+class TraderQuery_impl : virtual public TraderQuery_skel {
+private:
+ vector<TraderRestriction> restrictions;
+public:
+ void supports(const string& property, const string& value);
+ vector<TraderOffer> *query();
+};
+
+REGISTER_IMPLEMENTATION(TraderQuery_impl);
+
+// TraderOffer
+class TraderOffer_impl : virtual public TraderOffer_skel {
+private:
+ string _interfaceName;
+ map<string, vector<string> > property;
+
+public:
+ TraderOffer_impl(const string& interfaceName, const string& filename);
+
+ bool match(const vector<TraderRestriction>& restrictions);
+
+ // IDL
+ string interfaceName();
+ vector<string>* getProperty(const string& name);
+};
+
+}
+
+// TraderQuery
+//----------------------------------------------------------------------------
+void TraderQuery_impl::supports(const string& property, const string& value)
+{
+ restrictions.push_back(TraderRestriction(property,value));
+}
+
+vector<TraderOffer> *TraderQuery_impl::query()
+{
+ return TraderHelper::the()->doQuery(restrictions);
+}
+
+// TraderOffer
+//----------------------------------------------------------------------------
+TraderOffer_impl::TraderOffer_impl(const string& interfaceName,
+ const string& filename)
+ :_interfaceName(interfaceName)
+{
+ ifstream file(filename.c_str());
+ string line;
+
+ while(getline(file,line))
+ {
+ string key;
+ vector<string> values;
+
+ if(MCOPUtils::tokenize(line,key,values))
+ property[key] = values;
+ }
+
+ vector<string>& iname = property["InterfaceName"];
+ if(iname.empty())
+ iname.push_back(interfaceName);
+}
+
+bool TraderOffer_impl::match(const vector<TraderRestriction>& restrictions)
+{
+ vector<TraderRestriction>::const_iterator i;
+
+ for(i = restrictions.begin(); i != restrictions.end();i++)
+ {
+ const TraderRestriction& res = *i;
+ const vector<string>& myvalues = property[res.key];
+ bool okay = false;
+
+ vector<string>::const_iterator offerIt = myvalues.begin();
+ while(!okay && offerIt != myvalues.end())
+ {
+ if(res.value == *offerIt)
+ okay = true;
+ else
+ offerIt++;
+ }
+
+ if(!okay) return false;
+ }
+ return true;
+}
+
+string TraderOffer_impl::interfaceName()
+{
+ return _interfaceName;
+}
+
+vector<string>* TraderOffer_impl::getProperty(const string& name)
+{
+ return new vector<string>(property[name]);
+}
+
+// TraderHelper
+//----------------------------------------------------------------------------
+
+TraderHelper::TraderHelper()
+{
+ load();
+}
+
+TraderHelper::~TraderHelper()
+{
+ unload();
+}
+
+void TraderHelper::load()
+{
+ const vector<string> *path = MCOPUtils::traderPath();
+
+ vector<string>::const_iterator pi;
+ for(pi = path->begin(); pi != path->end(); pi++) addDirectory(*pi);
+}
+
+void TraderHelper::unload()
+{
+ vector<TraderOffer_impl *>::iterator i;
+
+ for(i = allOffers.begin(); i != allOffers.end(); i++)
+ {
+ TraderOffer_impl *offer = *i;
+ offer->_release();
+ }
+ allOffers.clear();
+}
+
+void TraderHelper::addDirectory(const string& directory, const string& iface,
+ map< pair<dev_t,ino_t>, bool > *dirsDone)
+{
+ bool created_dirs_done = false;
+ arts_debug("addDirectory(%s,%s)", directory.c_str(), iface.c_str());
+
+ if(!dirsDone)
+ {
+ /* map to prevent doing directories again due to symlinks */
+ dirsDone = new map< pair<dev_t,ino_t>, bool >;
+
+ struct stat st;
+ stat(directory.c_str(), &st);
+ (*dirsDone)[make_pair(st.st_dev, st.st_ino)] = true;
+ created_dirs_done = true;
+ }
+
+ DIR *dir = opendir(directory.c_str());
+ if(!dir) return;
+
+ struct dirent *de;
+ while((de = readdir(dir)) != 0)
+ {
+ string currentEntry = directory + "/" + de->d_name;
+
+ string currentIface = iface;
+ if(!iface.empty()) currentIface += "::";
+ currentIface += de->d_name;
+
+ struct stat st;
+ stat(currentEntry.c_str(),&st);
+
+ // recurse into subdirectories
+ if(S_ISDIR(st.st_mode))
+ {
+ bool& done = (*dirsDone)[make_pair(st.st_dev, st.st_ino)];
+ if(strcmp(de->d_name,".") && strcmp(de->d_name,"..") && !done)
+ {
+ done = true;
+ addDirectory(currentEntry,currentIface,dirsDone);
+ }
+ }
+ else if(S_ISREG(st.st_mode))
+ {
+ if(strlen(de->d_name) > 10 &&
+ strncmp(&de->d_name[strlen(de->d_name)-10],".mcopclass",10) == 0)
+ {
+ // cut .mcopclass for currentIface;
+ currentIface = currentIface.substr(0, currentIface.size()-10);
+ allOffers.push_back(
+ new TraderOffer_impl(currentIface,currentEntry) );
+ }
+ }
+ }
+
+ if (created_dirs_done)
+ delete dirsDone;
+
+ closedir(dir);
+}
+
+static inline int getOfferPreference(TraderOffer offer)
+{
+ int result = 0;
+
+ vector<string> *p = offer.getProperty("Preference");
+ if(!p->empty())
+ result = atoi(p->front().c_str());
+ delete p;
+
+ return result;
+}
+
+static bool traderOfferCmp(TraderOffer offer1, TraderOffer offer2)
+{
+ int p1 = getOfferPreference(offer1);
+ int p2 = getOfferPreference(offer2);
+
+ if(p1 > p2)
+ return true;
+ if(p1 < p2)
+ return false;
+
+ /* if the Preference= entry doesn't indicate which offer is better,
+ * sort the offers by name to make the trader results at least
+ * independant from the order they are read from the file system */
+ return offer1.interfaceName() < offer2.interfaceName();
+}
+
+vector<TraderOffer> *TraderHelper::doQuery(const
+ vector<TraderRestriction>& query)
+{
+ vector<TraderOffer> *result = new vector<TraderOffer>;
+
+ vector<TraderOffer_impl *>::iterator i;
+ for(i = allOffers.begin(); i != allOffers.end(); i++)
+ {
+ TraderOffer_impl *offer = *i;
+
+ if(offer->match(query))
+ {
+ result->push_back(TraderOffer::_from_base(offer->_copy()));
+ }
+ }
+
+ /* sort trader query result by Preference= line for more than one result */
+ if(result->size() > 1)
+ sort(result->begin(), result->end(), traderOfferCmp);
+ return result;
+}
+
+TraderHelper *TraderHelper::_instance = 0;
+TraderHelper *TraderHelper::the()
+{
+ if(!_instance) _instance = new TraderHelper();
+ return _instance;
+}
+
+void TraderHelper::shutdown()
+{
+ if(_instance)
+ {
+ delete _instance;
+ _instance = 0;
+ }
+}
+
+namespace Arts {
+
+// trader shutdown
+class TraderShutdown :public StartupClass
+{
+public:
+ void startup() { };
+ void shutdown() { TraderHelper::shutdown(); };
+};
+
+static TraderShutdown traderShutdown;
+
+}
+
+// Dispatcher function for reloading the trader data:
+void Dispatcher::reloadTraderData()
+{
+ TraderHelper::the()->unload();
+ TraderHelper::the()->load();
+}
diff --git a/mcop/type.cc b/mcop/type.cc
new file mode 100644
index 0000000..541876b
--- /dev/null
+++ b/mcop/type.cc
@@ -0,0 +1,31 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "type.h"
+#include <assert.h>
+
+long Arts::Type::_staticTypeCount = 0;
+
+Arts::Type::~Type()
+{
+ _staticTypeCount--;
+}
diff --git a/mcop/type.h b/mcop/type.h
new file mode 100644
index 0000000..2f95d20
--- /dev/null
+++ b/mcop/type.h
@@ -0,0 +1,85 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef TYPE_H
+#define TYPE_H
+
+#include "arts_export.h"
+#include "buffer.h"
+
+/*
+ * BC - Status (2002-03-08): Type
+ *
+ * Keep binary compatible. DO NOT TOUCH, DO NOT CHANGE.
+ */
+
+namespace Arts {
+
+/**
+ * Base class for the IDL mapping of struct-like types
+ */
+class ARTS_EXPORT Type {
+private:
+ static long _staticTypeCount;
+
+public:
+ inline static long _typeCount() { return _staticTypeCount; }
+ /**
+ * constructor
+ */
+ inline Type()
+ {
+ _staticTypeCount++;
+ }
+
+ /**
+ * copy constructor
+ */
+ inline Type(const Type&)
+ {
+ _staticTypeCount++;
+ }
+
+ /**
+ * virtual destructor (since we have virtual functions and this stuff
+ */
+ virtual ~Type();
+
+ /**
+ * read the type from a stream
+ */
+ virtual void readType(Buffer& stream) = 0;
+
+ /**
+ * write the type to a stream
+ */
+ virtual void writeType(Buffer& stream) const = 0;
+
+ /**
+ * type name
+ */
+ virtual std::string _typeName() const = 0;
+};
+
+}
+
+#endif
diff --git a/mcop/unixconnection.cc b/mcop/unixconnection.cc
new file mode 100644
index 0000000..adda10d
--- /dev/null
+++ b/mcop/unixconnection.cc
@@ -0,0 +1,114 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "unixconnection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdlib.h>
+
+using namespace std;
+using namespace Arts;
+
+static struct sockaddr_un *parse_unix_url(const char *url)
+{
+ static struct sockaddr_un addr;
+
+ char *work = strdup(url);
+
+ char *type = strtok(work,":");
+ if(type == 0 || strcmp(type,"unix") != 0) {
+ free(work);
+ return 0;
+ }
+
+ char *path = strtok(NULL,":\n");
+ if(path == 0) {
+ free(work);
+ return 0;
+ }
+
+ int maxlen = sizeof(addr.sun_path);
+ memset((void *) &addr, '\0', sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path,path,maxlen);
+ addr.sun_path[maxlen-1] = 0;
+ free(work);
+ return &addr;
+}
+
+static int unix_connect(const char *url)
+{
+ struct sockaddr_un *remote_addr = parse_unix_url(url);
+ if(remote_addr == 0)
+ {
+ arts_warning("unix_connect: couldn't parse url %s",url);
+ return -1;
+ }
+
+ int my_socket = socket(AF_UNIX,SOCK_STREAM,0);
+ if(my_socket < 0)
+ {
+ arts_warning("unix_connect: unable to open socket for read");
+ return -1;
+ }
+
+ struct linger lin;
+ lin.l_onoff=1; /* block a closing socket for 1 second */
+ lin.l_linger=100; /* if data is waiting to be sent */
+ if ( setsockopt( my_socket, SOL_SOCKET, SO_LINGER,
+ (char*)&lin, sizeof(struct linger) ) < 0 )
+ {
+ arts_warning("unix_connect: unable to set socket linger value to %d",
+ lin.l_linger);
+ close(my_socket);
+ return -1;
+ }
+
+ int rc;
+ rc=connect(my_socket,(struct sockaddr *)remote_addr, sizeof(*remote_addr));
+ if(rc != 0)
+ {
+ arts_warning("unix_connect: can't connect to server (%s)",url);
+ close(my_socket);
+ return -1;
+ }
+
+ return my_socket;
+}
+
+UnixConnection::UnixConnection(const string& url)
+{
+ fd = unix_connect(url.c_str());
+ _broken = (fd == -1);
+
+ if(!_broken)
+ {
+ Dispatcher::the()->ioManager()->watchFD(fd,
+ IOType::read|IOType::except|IOType::reentrant,this);
+ initReceive();
+ }
+}
diff --git a/mcop/unixconnection.h b/mcop/unixconnection.h
new file mode 100644
index 0000000..54a5643
--- /dev/null
+++ b/mcop/unixconnection.h
@@ -0,0 +1,43 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): UnixConnection
+ *
+ * Not part of the public API. Do NOT use it in your apps. Can change, even
+ * binary incompatible.
+ */
+
+#ifndef UNIXCONNECTION_H
+#define UNIXCONNECTION_H
+
+#include "socketconnection.h"
+
+namespace Arts {
+
+class UnixConnection :public SocketConnection {
+public:
+ UnixConnection(const std::string& url);
+};
+
+}
+#endif /* UNIXCONNECTION_H */
diff --git a/mcop/unixserver.cc b/mcop/unixserver.cc
new file mode 100644
index 0000000..65cfa76
--- /dev/null
+++ b/mcop/unixserver.cc
@@ -0,0 +1,151 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "mcoputils.h"
+#include "unixserver.h"
+#include "socketconnection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#define queue cqueue
+#include <arpa/inet.h>
+#undef queue
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+using namespace std;
+using namespace Arts;
+
+bool UnixServer::running()
+{
+ return socketOk;
+}
+
+UnixServer::UnixServer(Dispatcher *dispatcher, const string& serverID)
+{
+ this->dispatcher = dispatcher;
+
+ socketOk = initSocket(serverID);
+ if(socketOk) {
+ IOManager *iom = dispatcher->ioManager();
+ iom->watchFD(theSocket,IOType::read|IOType::except,this);
+ }
+}
+
+UnixServer::~UnixServer()
+{
+ if(socketOk) {
+ IOManager *iom = dispatcher->ioManager();
+ iom->remove(this,IOType::read|IOType::except);
+ close(theSocket);
+ unlink(xserverpath.c_str());
+ }
+}
+
+bool UnixServer::initSocket(const string& serverID)
+{
+ struct sockaddr_un socket_addr;
+
+ theSocket = socket(PF_UNIX,SOCK_STREAM,0);
+ if(theSocket < 0)
+ {
+ arts_warning("MCOP UnixServer: can't create a socket");
+ return false;
+ }
+
+ if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0)
+ {
+ arts_warning("MCOP UnixServer: can't initialize non blocking I/O");
+ close(theSocket);
+ return false;
+ }
+
+ int maxlen = sizeof(socket_addr.sun_path);
+ string pathname = MCOPUtils::createFilePath(serverID);
+
+ socket_addr.sun_family = AF_UNIX;
+ strncpy(socket_addr.sun_path,pathname.c_str(),maxlen);
+ socket_addr.sun_path[maxlen-1] = 0;
+
+ xserverpath = socket_addr.sun_path;
+
+ if ( bind( theSocket, (struct sockaddr *) &socket_addr,
+ sizeof(struct sockaddr_un) ) < 0 )
+ {
+ arts_warning("MCOP UnixServer: can't bind to file \"%s\"",
+ pathname.c_str());
+ close(theSocket);
+ return false;
+ }
+
+ if(listen(theSocket,16) < 0)
+ {
+ arts_warning("MCOP UnixServer: can't listen on the socket");
+ close(theSocket);
+ return false;
+ }
+ return true;
+}
+
+string UnixServer::url()
+{
+ return string("unix:") + xserverpath;
+}
+
+void UnixServer::notifyIO(int fd, int types)
+{
+ assert(fd == theSocket);
+ assert(socketOk);
+
+ arts_debug("UnixManager: got notifyIO");
+ if(types & IOType::read)
+ {
+ int clientfd;
+ struct sockaddr_un incoming;
+ socklen_t size_in = sizeof(struct sockaddr_un);
+
+ clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in );
+ if(clientfd > 0)
+ {
+ // non blocking I/O
+ int flags = fcntl (fd, F_GETFL, 0);
+ assert (flags != -1);
+
+ int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+ assert(nbl_result >= 0);
+
+ Dispatcher::the()->initiateConnection(
+ new SocketConnection(clientfd));
+ }
+ }
+ arts_assert((types & IOType::write) == 0);
+ arts_assert((types & IOType::except) == 0);
+}
diff --git a/mcop/unixserver.h b/mcop/unixserver.h
new file mode 100644
index 0000000..b492e39
--- /dev/null
+++ b/mcop/unixserver.h
@@ -0,0 +1,59 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): UnixServer
+ *
+ * Not part of the public API. Do NOT use it in your apps. Can change, even
+ * binary incompatible.
+ */
+
+#ifndef UNIXSERVER_H
+#define UNIXSERVER_H
+
+#include <string>
+#include "iomanager.h"
+
+namespace Arts {
+
+class Dispatcher;
+
+class UnixServer :public IONotify {
+protected:
+ Dispatcher *dispatcher;
+
+ std::string xserverpath;
+ int theSocket;
+ bool socketOk;
+ bool initSocket(const std::string& serverID);
+
+public:
+ UnixServer(Dispatcher *dispatcher, const std::string& serverID);
+ virtual ~UnixServer();
+ bool running();
+ std::string url();
+
+ void notifyIO(int fd, int types);
+};
+
+}
+#endif /* UNIXSERVER_H */
diff --git a/mcop/weakreference.h b/mcop/weakreference.h
new file mode 100644
index 0000000..76bb381
--- /dev/null
+++ b/mcop/weakreference.h
@@ -0,0 +1,131 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): WeakReference(Base)
+ *
+ * Has to be kept binary compatible by not touching it. Add a new class if
+ * you need something else.
+ */
+
+#ifndef MCOP_WEAKREFERENCE_H
+#define MCOP_WEAKREFERENCE_H
+
+#include "arts_export.h"
+
+namespace Arts {
+
+class ARTS_EXPORT WeakReferenceBase {
+public:
+ virtual void release() = 0;
+};
+
+/**
+ * The WeakReference class can be used to safely store an object, without
+ * disallowing that it gets destroyed. A typical situation where you may want
+ * to use this is when you implement a datastructure, where A refers B, and
+ * B refers A. Using "normal" references, this structure would never get
+ * freed.
+ *
+ * Usage example:
+ *
+ * Synth_WAVE_SIN sin;
+ * WeakReference<Synth_PLAY_WAV> weak_sin;
+ *
+ * {
+ * Synth_WAVE_SIN test = weak_sin;
+ * if(test.isNull())
+ * printf("#1 missing object\n");
+ * else
+ * test.start();
+ * }
+ *
+ * // now, the strong reference leaves
+ * sin = Synth_WAVE_SIN::null();
+ *
+ * {
+ * Synth_WAVE_SIN test = weak_sin;
+ * if(test.isNull())
+ * printf("#2 missing object\n");
+ * else
+ * test.stop();
+ *
+ * This would output "#2 missing object".
+ *
+ */
+
+template<class SmartWrapper>
+class WeakReference : public WeakReferenceBase
+{
+private:
+ typename SmartWrapper::_base_class *content;
+
+public:
+ WeakReference()
+ {
+ content = 0;
+ }
+ WeakReference(const WeakReference<SmartWrapper>& source)
+ :WeakReferenceBase(source), content(source.content)
+ {
+ if(content)
+ content->_addWeakReference(this);
+ }
+ WeakReference(SmartWrapper& source)
+ {
+ content = source._base();
+ if(content)
+ content->_addWeakReference(this);
+ }
+ inline WeakReference<SmartWrapper>& operator=(const
+ WeakReference<SmartWrapper>& source)
+ {
+ release();
+ content = source.content;
+ if(content)
+ content->_addWeakReference(this);
+ return *this;
+ }
+ virtual ~WeakReference()
+ {
+ release();
+ }
+ void release()
+ {
+ if(content)
+ {
+ content->_removeWeakReference(this);
+ content = 0;
+ }
+ }
+ inline operator SmartWrapper() const
+ {
+ if(content)
+ return SmartWrapper::_from_base(content->_copy());
+ else
+ return SmartWrapper::null();
+ }
+};
+
+}
+
+#endif /* MCOP_WEAKREFERENCE_H */