00001 //# QtDBusXmlApp.qo.h: Abstract parent to use the CASA DBus server. 00002 //# Copyright (C) 2009 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: $ 00027 #ifndef QTDBUSXMLAPP_QO_H_ 00028 #define QTDBUSXMLAPP_QO_H_ 00029 00030 #include <casaqt/QtUtilities/QtDBusApp.h> 00031 #include <casaqt/QtUtilities/QtDBusXML.h> 00032 00033 #include <QDBusAbstractAdaptor> 00034 #include <QDBusConnection> 00035 00036 namespace casa { 00037 00038 //# Forward Declarations. 00039 class QtDBusXmlAppAdaptor; 00040 00041 00042 // Abstract parent of classes that want to register themselves with CASA's 00043 // DBus server. The class also provides public static methods for other code 00044 // to send DBus messages without needing to subclass and register. This class 00045 // hides the details of how the DBus communication happens behind the scenes 00046 // and presents an interface using CASA objects like Records. Applications 00047 // that want to use this DBus communication layer need to know about the 00048 // following for each method call: 00049 // * The object name. Each object that registers with CASA's DBus server must 00050 // do so with a unique name. Outside objects then can send messages to that 00051 // object by using its name. Names have some restrictions; see 00052 // dbusRegisterSelf(). You can check if a certain name is currently 00053 // registered using dbusNameIsRegistered(). 00054 // * The method name. Each object keeps track of what methods it supports, and 00055 // this process happens dynamically on a per-message basis. 00056 // * Whether to call asynchronously or not. See dbusXmlCallNoRet(). 00057 // * The method parameters. The parameters are set using name/value pairs in a 00058 // Record. Like the method name, this is on a dynamic, per-object basis. 00059 // IMPORTANT: not all types are currently supported; see QtDBusXML 00060 // documentation to see what is currently implemented. 00061 // * The method return value. IMPORTANT: not all types are currently 00062 // supported; see QtDBusXML documentation to see what is currently 00063 // implemented. 00064 // 00065 // If a class wants to receive DBus communications, it must take the following 00066 // steps: 00067 // 1) Subclass QtDBusXmlApp. 00068 // 2) Implement the dbusRunXmlMethod() method, which is called when a DBus method 00069 // call is received. For a discussion of the parameters to this method, see 00070 // above. 00071 // 3) Call dbusRegisterSelf() with a unique name. 00072 // 00073 // Classes that wish to send but not receive messages do NOT need to subclass 00074 // QtDBusXmlApp and can just use the public static methods to call methods on 00075 // DBus-registered objects. For a discussion of the parameters to these 00076 // static methods, see above. 00077 class QtDBusXmlApp : public QtDBusApp { 00078 00079 //# Friend class declarations. 00080 friend class QtDBusXmlAppAdaptor; 00081 00082 public: 00083 00084 // Calls the given method on the object with the given name that is 00085 // registered with CASA's DBus server, using the given parameters. The 00086 // given from name is sent to the remote object, but not used otherwise. If 00087 // isAsync is true, then the remote method runs asynchronously, which means 00088 // that control returns immediately after sending the message. This method 00089 // does NOT give a return value, even if the remote method does. Returns 00090 // true for success, false for failure. Will fail if the given object 00091 // name is not registered with CASA's DBus server. 00092 static bool dbusXmlCallNoRet(const String& fromName, 00093 const String& objectName, const String& methodName, 00094 const Record& parameters, bool isAsync = false); 00095 00096 // Like dbusXmlCallNoRet(), except that if the remote method has a 00097 // return value of the given type, then the value is set accordingly. If 00098 // there is no return value or it is a different type, the value is not 00099 // set. If retValueSet is given, it will be set to true if the return 00100 // value was set and false otherwise. 00101 // <group> 00102 static bool dbusXmlCall(const String& fromName, 00103 const String& objectName, const String& methodName, 00104 const Record& parameters, bool& retValue, 00105 bool* retValueSet = NULL); 00106 static bool dbusXmlCall(const String& fromName, 00107 const String& objectName, const String& methodName, 00108 const Record& parameters, int& retValue, 00109 bool* retValueSet = NULL); 00110 static bool dbusXmlCall(const String& fromName, 00111 const String& objectName, const String& methodName, 00112 const Record& parameters, uInt& retValue, 00113 bool* retValueSet = NULL); 00114 static bool dbusXmlCall(const String& fromName, 00115 const String& objectName, const String& methodName, 00116 const Record& parameters, double& retValue, 00117 bool* retValueSet = NULL); 00118 static bool dbusXmlCall(const String& fromName, 00119 const String& objectName, const String& methodName, 00120 const Record& parameters, String& retValue, 00121 bool* retValueSet = NULL); 00122 static bool dbusXmlCall(const String& fromName, 00123 const String& objectName, const String& methodName, 00124 const Record& parameters, Record& retValue, 00125 bool* retValueSet = NULL); 00126 static bool dbusXmlCall(const String& fromName, 00127 const String& objectName, const String& methodName, 00128 const Record& parameters, Array<Bool>& retValue, 00129 bool* retValueSet = NULL); 00130 static bool dbusXmlCall(const String& fromName, 00131 const String& objectName, const String& methodName, 00132 const Record& parameters, Array<Int>& retValue, 00133 bool* retValueSet = NULL); 00134 // </group> 00135 00136 protected: 00137 // Constructor. 00138 QtDBusXmlApp(); 00139 00140 // Destructor. Unregisters from the CASA DBus server if needed. 00141 virtual ~QtDBusXmlApp(); 00142 00143 00144 // ABSTRACT METHODS // 00145 00146 // Runs the method with the specified name using the given parameters and 00147 // placing the return value, if any, into the given retValue record. NOTE: 00148 // when defining the return value, the name doesn't matter because the 00149 // first entry is used. The caller name, and whether this is an 00150 // asynchronous call or not, are also provided but do not need to be used. 00151 // Note, however, that asynchronous method calls will NOT use a return 00152 // value even if one is set. 00153 virtual void dbusRunXmlMethod(const String& methodName, 00154 const Record& parameters, Record& retValue, 00155 const String& callerName, bool isAsync) = 0; 00156 00157 00158 // VIRTUAL METHODS // 00159 00160 // Method that can be overridden if the subclass wants to be informed 00161 // whenever ANY dbus message is received, even if this object is not the 00162 // intended recipient. Note that most applications won't need to do this 00163 // (and probably shouldn't) since dbusRunXmlMethod() will be called with the 00164 // appropriate parameters if this object is the intended recipient. 00165 virtual void dbusXmlReceived(const QtDBusXML& xml) { (void)xml; } 00166 00167 00168 // IMPLEMENTED METHODS // 00169 00170 // Registers this object with CASA's DBus server, if it is not already, 00171 // with the given name and returns whether or not the registration 00172 // succeeded. If the name is blank, then the last set name is used, UNLESS 00173 // this is the first time registering in which case the registration will 00174 // fail. The registration name MUST contain only numbers, letters, and 00175 // underscores, and MUST be unique for the DBus server; trying to register 00176 // with a name that is already in use will result in registration failure. 00177 // (Note, however, that the name needs ONLY to be unique within the CASA 00178 // DBus application names rather than all system-wide DBus application 00179 // names.) Trying to register when already registered (see 00180 // dbusSelfIsRegistered()) will result in registration failure; to change 00181 // names, you must unregister and then reregister with the new name. 00182 bool dbusRegisterSelf(const String& name = ""); 00183 00184 // Unregisters this object with CASA's DBus server, if it is registered. 00185 void dbusUnregisterSelf(); 00186 00187 // Returns true if this object is currently registered with CASA's DBus 00188 // server, false otherwise. 00189 bool dbusSelfIsRegistered() const; 00190 00191 // Returns the name that this object is registered with with CASA's DBus 00192 // server, or an empty String if this application is not currently 00193 // registered. 00194 String dbusSelfRegisteredName() const; 00195 00196 // Calls the static version of the method with this application's name. 00197 // <group> 00198 bool dbusXmlCallNoRet(const String& objectName, 00199 const String& methodName, const Record& parameters, 00200 bool isAsync = false) { 00201 return dbusXmlCallNoRet(dbusSelfRegisteredName(), objectName, 00202 methodName, parameters, isAsync); } 00203 bool dbusXmlCall(const String& objectName, const String& methodName, 00204 const Record& parameters, bool& retValue, 00205 bool* retValueSet = NULL) { 00206 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00207 parameters, retValue, retValueSet); } 00208 bool dbusXmlCall(const String& objectName, const String& methodName, 00209 const Record& parameters, int& retValue, 00210 bool* retValueSet = NULL) { 00211 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00212 parameters, retValue, retValueSet); } 00213 bool dbusXmlCall(const String& objectName, const String& methodName, 00214 const Record& parameters, uInt& retValue, 00215 bool* retValueSet = NULL) { 00216 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00217 parameters, retValue, retValueSet); } 00218 bool dbusXmlCall(const String& objectName, const String& methodName, 00219 const Record& parameters, double& retValue, 00220 bool* retValueSet = NULL) { 00221 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00222 parameters, retValue, retValueSet); } 00223 bool dbusXmlCall(const String& objectName, const String& methodName, 00224 const Record& parameters, String& retValue, 00225 bool* retValueSet = NULL) { 00226 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00227 parameters, retValue, retValueSet); } 00228 bool dbusXmlCall(const String& objectName, const String& methodName, 00229 const Record& parameters, Record& retValue, 00230 bool* retValueSet = NULL) { 00231 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00232 parameters, retValue, retValueSet); } 00233 bool dbusXmlCall(const String& objectName, const String& methodName, 00234 const Record& parameters, Array<Bool>& retValue, 00235 bool* retValueSet = NULL) { 00236 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00237 parameters, retValue, retValueSet); } 00238 bool dbusXmlCall(const String& objectName, const String& methodName, 00239 const Record& parameters, Array<Int>& retValue, 00240 bool* retValueSet = NULL) { 00241 return dbusXmlCall(dbusSelfRegisteredName(), objectName, methodName, 00242 parameters, retValue, retValueSet); } 00243 // </group> 00244 00245 private: 00246 00247 // Flag for whether the application is currently registered or not. 00248 bool dbusRegistered_; 00249 00250 // Name that the application is registered with. 00251 QString dbusName_; 00252 00253 // DBus adaptor. 00254 QtDBusXmlAppAdaptor* dbusAdaptor_; 00255 00256 00257 // Method for when one of the slots in the adaptor is activated. First 00258 // sends to dbusXmlReceived(), then to dbusRunXmlMethod(). 00259 void dbusSlot(QtDBusXML& xml); 00260 00261 00262 // Private Static Methods // 00263 00264 // Helper method for calling remote methods. 00265 static bool dbusXmlCall(const String& from, const String& to, 00266 const String& methodName, bool methodIsAsync, 00267 const Record& parameters, Record* retValue); 00268 }; 00269 00270 00271 // Subclass of QDBusAbstractAdaptor for use with CASA's QtDBusXmlApp class. This 00272 // class is a very thin layer on top of QtDBusXmlApp. 00273 class QtDBusXmlAppAdaptor : public QDBusAbstractAdaptor { 00274 Q_OBJECT 00275 00276 // Interface name definition. 00277 // <group> 00278 #define CASA_DBUS_XML_INTERFACE "edu.nrao.casa.QtDBusXmlApp" 00279 Q_CLASSINFO("D-Bus Interface", "edu.nrao.casa.QtDBusXmlApp") 00280 // </group> 00281 00282 //# Friend class declarations. 00283 friend class QtDBusXmlApp; 00284 00285 public slots: 00286 // Slot for receiving messages. If its name is changed, 00287 // QtDBusXmlApp::DBUS_MESSAGE_SLOT must be updated. 00288 QString xmlSlot(const QString& xml); 00289 00290 private: 00291 // Constructor which takes the application. 00292 QtDBusXmlAppAdaptor(QtDBusXmlApp& app); 00293 00294 // Destructor. 00295 ~QtDBusXmlAppAdaptor(); 00296 00297 00298 // Application. 00299 QtDBusXmlApp& itsApp_; 00300 00301 // Dummy object. 00302 QObject* itsObject_; 00303 }; 00304 00305 } 00306 00307 #endif /* QTDBUSAPP_QO_H_ */