Back to index

nordugrid-arc-nox  1.1.0~rc6
javawrapper.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <iostream>
00006 #include <arc/message/SOAPMessage.h>
00007 #include <arc/message/PayloadSOAP.h>
00008 #include "javawrapper.h"
00009 
00010 static Arc::Plugin* get_service(Arc::PluginArgument* arg) {
00011     Arc::ServicePluginArgument* srvarg =
00012             arg?dynamic_cast<Arc::ServicePluginArgument*>(arg):NULL;
00013     if(!srvarg) return NULL;
00014     return new Arc::Service_JavaWrapper((Arc::Config*)(*srvarg));
00015 }
00016 
00017 Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = {
00018     { "arcservice_javawrapper", "HED:SERVICE", 0, &get_service },
00019     { NULL, NULL, 0, NULL }
00020 };
00021 
00022 namespace Arc {
00023 
00024 Arc::Logger Service_JavaWrapper::logger(Service::logger, "JavaWrapper");
00025 
00026 Service_JavaWrapper::Service_JavaWrapper(Arc::Config *cfg)
00027   : Service(cfg),
00028     libjvm(NULL),
00029     jvm(NULL),
00030     classPath(NULL) {
00031     std::string path = "-Djava.class.path=" + (std::string)((*cfg)["ClassPath"]);
00032     std::string class_name = (std::string)(*cfg)["ClassName"];
00033     logger.msg(Arc::VERBOSE, "config: %s, class name: %s", path, class_name);
00034     JNIEnv *jenv = NULL;
00035     JavaVMInitArgs jvm_args;
00036     JavaVMOption options[1];
00037     /* Initiliaze java engine */
00038     Glib::ModuleFlags flags = Glib::ModuleFlags(0);
00039     libjvm = new Glib::Module("libjvm.so", flags);
00040     if (!*libjvm) {
00041         logger.msg(Arc::ERROR,
00042                  "libjvm.so not loadable - check your LD_LIBRARY_PATH");
00043        return;
00044     }
00045     void* myJNI_GetDefaultJavaVMInitArgs;
00046     libjvm->get_symbol("JNI_GetDefaultJavaVMInitArgs",
00047                      myJNI_GetDefaultJavaVMInitArgs);
00048     void* myJNI_CreateJavaVM;
00049     libjvm->get_symbol("JNI_CreateJavaVM", myJNI_CreateJavaVM);
00050     if (myJNI_GetDefaultJavaVMInitArgs == NULL || myJNI_CreateJavaVM == NULL) {
00051         logger.msg(Arc::ERROR,
00052                  "libjvm.so does not contain the expected symbols");
00053        return;
00054     }
00055     ((jint(*)(void*))myJNI_GetDefaultJavaVMInitArgs)(&jvm_args);
00056     jvm_args.version = JNI_VERSION_1_2;
00057     jvm_args.nOptions = 1;
00058     classPath = strdup(path.c_str());
00059     options[0].optionString = classPath;
00060     options[0].extraInfo = NULL;
00061     // "-Djava.class.path=.:/home/szferi/arc1/src/services/echo_java/:/home/szferi/arc1/java/arc.jar";
00062     jvm_args.options = options;
00063     jvm_args.ignoreUnrecognized = JNI_FALSE;
00064     ((jint(*)(JavaVM**, void**, void*))myJNI_CreateJavaVM)(&jvm, (void **)&jenv,
00065                                                     &jvm_args);
00066     logger.msg(Arc::VERBOSE, "JVM started");
00067     
00068     /* Find and construct class */
00069     serviceClass = jenv->FindClass(class_name.c_str());
00070     if (serviceClass == NULL) {
00071         logger.msg(Arc::ERROR, "There is no service: %s in your java class search path", class_name);
00072         if (jenv->ExceptionOccurred()) {
00073             jenv->ExceptionDescribe();
00074         }
00075         return;
00076     }
00077     jmethodID constructorID = jenv->GetMethodID(serviceClass, "<init>", "()V");
00078     if (constructorID == NULL) {
00079         logger.msg(Arc::ERROR, "There is no constructor function");
00080         if (jenv->ExceptionOccurred()) {
00081             jenv->ExceptionDescribe();
00082         }
00083         return;
00084     }
00085     serviceObj = jenv->NewObject(serviceClass, constructorID);
00086     logger.msg(Arc::VERBOSE, "%s constructed", class_name);
00087 }
00088 
00089 Service_JavaWrapper::~Service_JavaWrapper(void) {
00090     logger.msg(Arc::VERBOSE, "Destroy jvm"); 
00091     if (jvm)
00092         jvm->DestroyJavaVM();
00093     if (libjvm)
00094         delete libjvm;
00095     if (classPath)
00096         free(classPath);
00097 }
00098 
00099 Arc::MCC_Status Service_JavaWrapper::make_fault(Arc::Message& outmsg) 
00100 {
00101     Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(Arc::NS(),true);
00102     Arc::SOAPFault* fault = outpayload->Fault();
00103     if(fault) {
00104         fault->Code(Arc::SOAPFault::Sender);
00105         fault->Reason("Failed processing request");
00106     };
00107     outmsg.Payload(outpayload);
00108     return Arc::MCC_Status();
00109 }
00110 
00111 Arc::MCC_Status Service_JavaWrapper::java_error(JNIEnv *jenv, const char *str) {
00112     std::cerr << str << std::endl;
00113     if (jenv->ExceptionOccurred()) {
00114         jenv->ExceptionDescribe();
00115     }
00116     /* Cleanup */
00117     jvm->DetachCurrentThread();
00118     return Arc::MCC_Status(Arc::GENERIC_ERROR);
00119 }
00120 
00121 Arc::MCC_Status Service_JavaWrapper::process(Arc::Message& inmsg, Arc::Message& outmsg) 
00122 {
00123     JNIEnv *jenv = NULL;
00124     
00125     /* Attach to the current java engine thread */
00126     jvm->AttachCurrentThread((void **)&jenv, NULL);
00127     /* Get the process function of service */
00128     jmethodID processID = jenv->GetMethodID(serviceClass, "process", "(Lnordugrid/arc/SOAPMessage;Lnordugrid/arc/SOAPMessage;)Lnordugrid/arc/MCC_Status;");
00129     if (processID == NULL) {
00130         return java_error(jenv, "Cannot find process method of java class");
00131     }
00132     /* convert inmsg and outmsg to java objects */
00133     Arc::SOAPMessage *inmsg_ptr = NULL;
00134     Arc::SOAPMessage *outmsg_ptr = NULL;
00135     try {
00136         inmsg_ptr = new Arc::SOAPMessage(inmsg);
00137         outmsg_ptr = new Arc::SOAPMessage(outmsg);
00138     } catch(std::exception& e) { };
00139     if(!inmsg_ptr) {
00140         logger.msg(Arc::ERROR, "input is not SOAP");
00141         return make_fault(outmsg);
00142     };
00143     if(!outmsg_ptr) {
00144         logger.msg(Arc::ERROR, "output is not SOAP");
00145         return make_fault(outmsg);
00146     };
00147 
00148     jclass JSOAPMessageClass = jenv->FindClass("nordugrid/arc/SOAPMessage");
00149     if (JSOAPMessageClass == NULL) {
00150         return java_error(jenv, "Cannot find SOAPMessage object");
00151     }
00152     /* Get the constructor of java object */
00153     jmethodID constructorID = jenv->GetMethodID(JSOAPMessageClass, "<init>", "(I)V");
00154     if (constructorID == NULL) {
00155         return java_error(jenv, "Cannot find constructor function of message");
00156     }
00157     /* Convert C++ object to Java objects */
00158     jobject jinmsg = jenv->NewObject(JSOAPMessageClass, constructorID, (jlong)((long int)inmsg_ptr));
00159     if (jinmsg == NULL) {
00160         return java_error(jenv, "Cannot convert input message to java object");
00161     }
00162     jobject joutmsg = jenv->NewObject(JSOAPMessageClass, constructorID, (jlong)((long int)outmsg_ptr));
00163     if (jinmsg == NULL) {
00164         return java_error(jenv, "Cannot convert output message to java object");
00165     }
00166     /* Create arguments for java process function */
00167     jvalue args[2];
00168     args[0].l = jinmsg;
00169     args[1].l = joutmsg;
00170     /* Call the process method of Java object */
00171     jobject jmcc_status = jenv->CallObjectMethodA(serviceObj, processID, args);
00172     if (jmcc_status == NULL) {
00173         return java_error(jenv, "Error in call process function of java object");
00174     }
00175     /* Get SWIG specific getCPtr function of Message class */
00176     jmethodID msg_getCPtrID = jenv->GetStaticMethodID(JSOAPMessageClass, "getCPtr", "(Lnordugrid/arc/SOAPMessage;)J");
00177     if (msg_getCPtrID == NULL) {
00178         return java_error(jenv, "Cannot find getCPtr method of java Message class");
00179     }
00180     /* Get Java MCC_Status class */
00181     jclass JMCC_StatusClass = jenv->FindClass("nordugrid/arc/MCC_Status");
00182     if (JMCC_StatusClass == NULL) {
00183         logger.msg(Arc::ERROR, "Cannot find MCC_Status object");
00184         /* Cleanup */
00185         jvm->DetachCurrentThread();
00186         return Arc::MCC_Status(Arc::GENERIC_ERROR);
00187     }
00188     /* Get SWIG specific getCPtr function of MCC_Status class */
00189     jmethodID mcc_status_getCPtrID = jenv->GetStaticMethodID(JMCC_StatusClass, "getCPtr", "(Lnordugrid/arc/MCC_Status;)J");
00190     if (mcc_status_getCPtrID == NULL) {
00191         return java_error(jenv, "Cannot find getCPtr method of java MCC_Status class");
00192     }
00193     
00194     /* Convert Java status object to C++ class */
00195     jlong mcc_status_addr = jenv->CallStaticLongMethod(JMCC_StatusClass, mcc_status_getCPtrID, jmcc_status);
00196     if (!mcc_status_addr) {
00197         logger.msg(ERROR, "Java object returned NULL status");
00198         return MCC_Status(GENERIC_ERROR);
00199     }
00200     Arc::MCC_Status status(*((Arc::MCC_Status *)(long)mcc_status_addr));
00201     /* Convert Java output message object to C++ class */
00202     jlong outmsg_addr = jenv->CallStaticLongMethod(JSOAPMessageClass, msg_getCPtrID, joutmsg);
00203      
00204     Arc::SOAPMessage *outmsg_ptr2 = (Arc::SOAPMessage *)(long)outmsg_addr;
00205     /* std::string xml;
00206     outmsg_ptr2->Payload()->GetXML(xml);   
00207     std::cout << xml << std::endl; */
00208     Arc::PayloadSOAP *pl = new Arc::PayloadSOAP(*(outmsg_ptr2->Payload()));
00209     outmsg.Payload((MessagePayload *)pl);
00210     // XXX: how to handle error?
00211     /* Detach from the Java engine */
00212     jvm->DetachCurrentThread();
00213     return status;
00214 }
00215 
00216 } // namespace Arc