#include "XPathProcessor.h" #include "XdmValue.h" #include "XdmItem.h" #include "XdmNode.h" #include "XdmAtomicValue.h" XPathProcessor::XPathProcessor() { SaxonProcessor *p = new SaxonProcessor(false); XPathProcessor(p, ""); } XPathProcessor::XPathProcessor(SaxonProcessor* p, std::string curr) { proc = p; /* * Look for class. */ cppClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/option/cpp/XPathProcessor"); if ((proc->proc) == NULL) { std::cerr << "Processor is NULL" << std::endl; } cppXP = createSaxonProcessor2(SaxonProcessor::sxn_environ->env, cppClass, "(Lnet/sf/saxon/s9api/Processor;)V", proc->proc); #ifdef DEBUG jmethodID debugMID = SaxonProcessor::sxn_environ->env->GetStaticMethodID(cppClass, "setDebugMode", "(Z)V"); SaxonProcessor::sxn_environ->env->CallStaticVoidMethod(cppClass, debugMID, (jboolean)true); #endif proc->exception = NULL; if(!(proc->cwd.empty()) && curr.empty()){ cwdXP = proc->cwd; } else { cwdXP = curr; } } XdmValue * XPathProcessor::evaluate(const char * xpathStr) { if (xpathStr == NULL) { std::cerr << "Error:: XPath string cannot be empty or NULL" << std::endl; return NULL; } setProperty("resources", proc->getResourcesDirectory()); jmethodID mID = (jmethodID) SaxonProcessor::sxn_environ->env->GetMethodID(cppClass, "evaluate", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;)[Lnet/sf/saxon/s9api/XdmValue;"); if (!mID) { std::cerr << "Error: "<env, "java/lang/Object"); jclass stringClass = lookForClass(SaxonProcessor::sxn_environ->env, "java/lang/String"); int size = parameters.size() + properties.size(); if (size > 0) { objectArray = SaxonProcessor::sxn_environ->env->NewObjectArray((jint) size, objectClass, 0); stringArray = SaxonProcessor::sxn_environ->env->NewObjectArray((jint) size, stringClass, 0); int i = 0; for (std::map::iterator iter = parameters.begin(); iter != parameters.end(); ++iter, i++) { SaxonProcessor::sxn_environ->env->SetObjectArrayElement(stringArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->first).c_str())); SaxonProcessor::sxn_environ->env->SetObjectArrayElement(objectArray, i, (iter->second)->getUnderlyingValue()); } for (std::map::iterator iter = properties.begin(); iter != properties.end(); ++iter, i++) { SaxonProcessor::sxn_environ->env->SetObjectArrayElement(stringArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->first).c_str())); SaxonProcessor::sxn_environ->env->SetObjectArrayElement(objectArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->second).c_str())); } } jobjectArray results = (jobjectArray)( SaxonProcessor::sxn_environ->env->CallObjectMethod(cppXP, mID, SaxonProcessor::sxn_environ->env->NewStringUTF(cwdXP.c_str()), SaxonProcessor::sxn_environ->env->NewStringUTF(xpathStr), stringArray, objectArray)); if(!results) { proc->checkAndCreateException(cppClass); return NULL; } int sizex = SaxonProcessor::sxn_environ->env->GetArrayLength(results); if (size > 0) { SaxonProcessor::sxn_environ->env->DeleteLocalRef(stringArray); SaxonProcessor::sxn_environ->env->DeleteLocalRef(objectArray); } if (sizex>0) { jclass atomicValueClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/s9api/XdmAtomicValue"); jclass nodeClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/s9api/XdmNode"); jclass functionItemClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/s9api/XdmFunctionItem"); XdmValue * value = new XdmValue(); XdmItem * xdmItem = NULL; for (int p=0; p < sizex; ++p) { jobject resulti = SaxonProcessor::sxn_environ->env->GetObjectArrayElement(results, p); //value->addUnderlyingValue(resulti); if(SaxonProcessor::sxn_environ->env->IsInstanceOf(resulti, atomicValueClass) == JNI_TRUE) { xdmItem = new XdmAtomicValue(resulti); } else if(SaxonProcessor::sxn_environ->env->IsInstanceOf(resulti, nodeClass) == JNI_TRUE) { xdmItem = new XdmNode(resulti); } else if (SaxonProcessor::sxn_environ->env->IsInstanceOf(resulti, functionItemClass) == JNI_TRUE) { continue; } xdmItem->setProcessor(proc); if(sizex == 1) { value->decrementRefCount(); delete value; SaxonProcessor::sxn_environ->env->DeleteLocalRef(results); return xdmItem; } value->addXdmItem(xdmItem); } value->setProcessor(proc); SaxonProcessor::sxn_environ->env->DeleteLocalRef(results); return value; } } return NULL; } XdmItem * XPathProcessor::evaluateSingle(const char * xpathStr) { if (xpathStr == NULL) { std::cerr << "Error:: XPath string cannot be empty or NULL" << std::endl; return NULL; } setProperty("resources", proc->getResourcesDirectory()); jmethodID mID = (jmethodID) SaxonProcessor::sxn_environ->env->GetMethodID(cppClass, "evaluateSingle", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;)Lnet/sf/saxon/s9api/XdmItem;"); if (!mID) { std::cerr << "Error: MyClassInDll." << "evaluateSingle" << " not found\n" << std::endl; } else { jobjectArray stringArray = NULL; jobjectArray objectArray = NULL; jclass objectClass = lookForClass(SaxonProcessor::sxn_environ->env, "java/lang/Object"); jclass stringClass = lookForClass(SaxonProcessor::sxn_environ->env, "java/lang/String"); int size = parameters.size() + properties.size(); #ifdef DEBUG std::cerr<<"Properties size: "< 0) { objectArray = SaxonProcessor::sxn_environ->env->NewObjectArray((jint) size, objectClass, 0); stringArray = SaxonProcessor::sxn_environ->env->NewObjectArray((jint) size, stringClass, 0); int i = 0; for (std::map::iterator iter = parameters.begin(); iter != parameters.end(); ++iter, i++) { SaxonProcessor::sxn_environ->env->SetObjectArrayElement(stringArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->first).c_str())); SaxonProcessor::sxn_environ->env->SetObjectArrayElement(objectArray, i, (iter->second)->getUnderlyingValue()); #ifdef DEBUG std::string s1 = typeid(iter->second).name(); std::cerr<<"Type of itr:"<second)->getUnderlyingValue(); if(xx == NULL) { std::cerr<<"value failed"<second)->getUnderlyingValue() == NULL) { std::cerr<<"(iter->second)->getUnderlyingValue() is NULL"<::iterator iter = properties.begin(); iter != properties.end(); ++iter, i++) { SaxonProcessor::sxn_environ->env->SetObjectArrayElement(stringArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->first).c_str())); SaxonProcessor::sxn_environ->env->SetObjectArrayElement(objectArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->second).c_str())); } } jobject result = (jobject)( SaxonProcessor::sxn_environ->env->CallObjectMethod(cppXP, mID, SaxonProcessor::sxn_environ->env->NewStringUTF(cwdXP.c_str()), SaxonProcessor::sxn_environ->env->NewStringUTF(xpathStr), stringArray, objectArray)); if (size > 0) { SaxonProcessor::sxn_environ->env->DeleteLocalRef(stringArray); SaxonProcessor::sxn_environ->env->DeleteLocalRef(objectArray); } if (result) { jclass atomicValueClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/s9api/XdmAtomicValue"); jclass nodeClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/s9api/XdmNode"); jclass functionItemClass = lookForClass(SaxonProcessor::sxn_environ->env, "net/sf/saxon/s9api/XdmFunctionItem"); XdmItem * xdmItem = NULL; if(SaxonProcessor::sxn_environ->env->IsInstanceOf(result, atomicValueClass) == JNI_TRUE) { xdmItem = new XdmAtomicValue(result); } else if(SaxonProcessor::sxn_environ->env->IsInstanceOf(result, nodeClass) == JNI_TRUE) { xdmItem = new XdmNode(result); } else if (SaxonProcessor::sxn_environ->env->IsInstanceOf(result, functionItemClass) == JNI_TRUE) { return NULL; } xdmItem->setProcessor(proc); //SaxonProcessor::sxn_environ->env->DeleteLocalRef(result); return xdmItem; } else { proc->checkAndCreateException(cppClass); } } return NULL; } void XPathProcessor::setContextItem(XdmItem * item) { contextItem = item; if(item != NULL){ parameters["node"] = (XdmValue *)item; } } void XPathProcessor::setContextFile(const char * filename) { if (filename != NULL) { setProperty("s", filename); } } /* Fix for bug #4513: https://saxonica.plan.io/issues/4513 */ void XPathProcessor::declareNamespace(const char *prefix, const char * uri){ if (prefix == NULL || uri == NULL) { return; } jmethodID mID = /*(jmethodID) SaxonProcessor::sxn_environ->env->GetMethodID(cppClass, "declareNamespace", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");*/ (jmethodID) SaxonProcessor::sxn_environ->env->GetMethodID(cppClass, "declareNamespace", "(Ljava/lang/String;Ljava/lang/String;)V"); if (!mID) { /*std::cerr << "Error: "<env->CallObjectMethod(cppXP, mID, SaxonProcessor::sxn_environ->env->NewStringUTF(prefix), SaxonProcessor::sxn_environ->env->NewStringUTF(uri)); //proc->checkAndCreateException(cppClass); } } #if CVERSION_API_NO >= 121 void XPathProcessor::setBackwardsCompatible(bool option) { if (option) { setProperty("backwardsCom:", "true"); } else { properties.erase("backwardsCom:"); } } void XPathProcessor::setCaching(bool caching){ if (caching) { setProperty("caching:", "true"); } else { properties.erase("caching:"); } } void XPathProcessor::importSchemaNamespace(const char* uri){ if (uri != NULL) { setProperty("importSN", uri); } } #endif void XPathProcessor::setBaseURI(const char * uriStr) { if (uriStr == NULL) { std::cerr << "Error:: XPath string cannot be empty or NULL" << std::endl; return; } setProperty("resources", proc->getResourcesDirectory()); jmethodID mID = (jmethodID) SaxonProcessor::sxn_environ->env->GetMethodID(cppClass, "setBaseURI", "(Ljava/lang/String;)Z"); if (!mID) { std::cerr << "Error: MyClassInDll." << "setBaseURI" << " not found\n" << std::endl; } else { SaxonProcessor::sxn_environ->env->CallObjectMethod(cppXP, mID, SaxonProcessor::sxn_environ->env->NewStringUTF(uriStr)); } } bool XPathProcessor::effectiveBooleanValue(const char * xpathStr) { if (xpathStr == NULL) { std::cerr << "Error:: XPath string cannot be empty or NULL" << std::endl; return false; } setProperty("resources", proc->getResourcesDirectory()); jmethodID mID = (jmethodID) SaxonProcessor::sxn_environ->env->GetMethodID(cppClass, "effectiveBooleanValue", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;)Z"); if (!mID) { std::cerr << "Error: MyClassInDll." << "effectiveBooleanValue" << " not found\n"<< std::endl; } else { jobjectArray stringArray = NULL; jobjectArray objectArray = NULL; jclass objectClass = lookForClass(SaxonProcessor::sxn_environ->env, "java/lang/Object"); jclass stringClass = lookForClass(SaxonProcessor::sxn_environ->env, "java/lang/String"); int size = parameters.size() + properties.size(); if (size > 0) { objectArray = SaxonProcessor::sxn_environ->env->NewObjectArray((jint) size, objectClass, 0); stringArray = SaxonProcessor::sxn_environ->env->NewObjectArray((jint) size, stringClass, 0); int i = 0; for (std::map::iterator iter = parameters.begin(); iter != parameters.end(); ++iter, i++) { SaxonProcessor::sxn_environ->env->SetObjectArrayElement(stringArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->first).c_str())); SaxonProcessor::sxn_environ->env->SetObjectArrayElement(objectArray, i, (iter->second)->getUnderlyingValue()); } for (std::map::iterator iter = properties.begin(); iter != properties.end(); ++iter, i++) { SaxonProcessor::sxn_environ->env->SetObjectArrayElement(stringArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->first).c_str())); SaxonProcessor::sxn_environ->env->SetObjectArrayElement(objectArray, i, SaxonProcessor::sxn_environ->env->NewStringUTF((iter->second).c_str())); } } jboolean result = (jboolean)( SaxonProcessor::sxn_environ->env->CallBooleanMethod(cppXP, mID, SaxonProcessor::sxn_environ->env->NewStringUTF(cwdXP.c_str()), SaxonProcessor::sxn_environ->env->NewStringUTF(xpathStr), stringArray, objectArray)); if (size > 0) { SaxonProcessor::sxn_environ->env->DeleteLocalRef(stringArray); SaxonProcessor::sxn_environ->env->DeleteLocalRef(objectArray); } proc->checkAndCreateException(cppClass); return result; } return false; } void XPathProcessor::setParameter(const char * name, XdmValue* value) { if(value != NULL){ value->incrementRefCount(); parameters["param:"+std::string(name)] = value; } } bool XPathProcessor::removeParameter(const char * name) { return (bool)(parameters.erase("param:"+std::string(name))); } void XPathProcessor::setProperty(const char * name, const char * value) { #ifdef DEBUG if(value == NULL) { std::cerr<<"XPathProc setProperty is NULL"<(std::string(name), std::string((value == NULL ? "" : value)))); } void XPathProcessor::clearParameters(bool delVal) { if(delVal){ for(std::map::iterator itr = parameters.begin(); itr != parameters.end(); itr++){ XdmValue * value = itr->second; value->decrementRefCount(); #ifdef DEBUG std::cerr<<"XPathProc.clearParameter() - XdmValue refCount="<getRefCount()<getRefCount() < 1){ delete value; } } parameters.clear(); } } void XPathProcessor::clearProperties() { properties.clear(); } void XPathProcessor::setcwd(const char* dir){ cwdXP = std::string(dir); } std::map& XPathProcessor::getParameters(){ std::map& ptr = parameters; return ptr; } std::map& XPathProcessor::getProperties(){ std::map &ptr = properties; return ptr; } void XPathProcessor::exceptionClear(){ if(proc->exception != NULL) { delete proc->exception; proc->exception = NULL; } SaxonProcessor::sxn_environ->env->ExceptionClear(); } int XPathProcessor::exceptionCount(){ if(proc->exception != NULL){ return proc->exception->count(); } return 0; } const char * XPathProcessor::getErrorCode(int i) { if(proc->exception == NULL) {return NULL;} return proc->exception->getErrorCode(i); } const char * XPathProcessor::getErrorMessage(int i ){ if(proc->exception == NULL) {return NULL;} return proc->exception->getErrorMessage(i); } bool XPathProcessor::exceptionOccurred(){ return proc->exceptionOccurred(); } const char* XPathProcessor::checkException(){ return proc->checkException(cppXP); }