Hello All
I have developed a java wrapper over the mozilla html parser. It is
working great except for an annoying multithreading issue. I am hoping
that someone can help me with it.


The problem is quite simple. At first , when the parser is
initializes , it starts a initXPCOM2() method to initialize the XPCOM
interface. if i then ask for a nsParser instance from that thread it
will give it to me with no problem and thus from that thread i can do
whatever i want.
The problem begins when i have another thread that is trying to get an
instance of nsParser. the code throws an assertion exception and tells
me that this is the class is thread safe . here is the error :

###!!! ASSERTION: nsParser not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file src
\nsParser.cpp, line 77

I have tried to use proxies but i didn't manage to get it right,
I have two questions :

1. is it possible at all to do what i am trying to do ? Is it possible
to parse two html pages asynchronously, from two different native
threads ?

2. I have another class that is apperantly not thread safe , it is
called JavaContentSink and it extends the nsLoggingSink class. when i
try to have multiple instances of it i am getting a huge memory leak ,
and thus i have to have only one instance of the content sink ... How
can get the xpcom to delete the references to the JavaContentSink
instances if i am not using the doCreateInstance() mechanism , but
just instantiate the object myslef directly in the code ?

Here is the code that of the MozillaParser.cpp that is not working

#include <jni.h>
#include "MozillaParser.h"
#include "JavaContentSink.h"
#include "nsXPCOM.h"
#include "nsIComponentManager.h"
#include "nsParserCIID.h"
#include "nsIParser.h"
#include "nsILoggingSink.h"
#include "nsIInputStream.h"
#include "nsILocalFile.h"
#include "nsEmbedString.h"
#include "nsIProxyObjectManager.h"
#include "nsParser.h"



// Class IID's
static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
static NS_DEFINE_CID(kLoggingSinkCID, NS_LOGGING_SINK_CID);
static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID);
static
NS_DEFINE_CID(kProxyObjectManagerCID,NS_PROXYEVENT_MANAGER_CID);

// JAVA Exception constants :
const char *PARSER_EXCEPTION="com/dappit/Dapper/parser/
ParserException";
const char *PARSER_INITIALIZATION_EXCEPTION="com/dappit/Dapper/parser/
ParserInitializationException";

// Java helper function :Generate an exception :
void generateException(JNIEnv * env , const char *exceptionName , char
*message){
        env->ExceptionDescribe();
        env->ExceptionClear();

        jclass newExcCls = env->FindClass(exceptionName);
        if (newExcCls == 0) /* Unable to find the new exception class, give
up. */
        {
                return;
        }
        env->ThrowNew( newExcCls, message);
}

void generateException(JNIEnv * env ,  char *message ){
        generateException(env,PARSER_EXCEPTION,message);
}

//static nsCOMPtr<nsIParser> parser;
//static nsCOMPtr<nsIDTD> dtd;


static nsIContentSink* sink;
static JavaContentSink javaContentSink;


JNIEXPORT void JNICALL
Java_com_dappit_Dapper_parser_MozillaParser_initXPCOM
  (JNIEnv *env, jclass , jstring componentBaseString)
{
        jboolean iscopy;
        const char *componentBaseInput = env-
>GetStringUTFChars(componentBaseString , &iscopy);
        int inputBaseLength = (int)env->GetStringLength(componentBaseString);

        printf("Initializing XPCOM from location : %s...\n" ,
componentBaseInput);
        nsresult rv;
        nsCOMPtr<nsILocalFile> file;
        nsString componentBaseNsString;
        componentBaseNsString.AppendWithConversion(componentBaseInput ,
inputBaseLength );
        rv = NS_NewLocalFile(nsEmbedString(componentBaseNsString), PR_FALSE,
                     getter_AddRefs(file));

        rv = NS_InitXPCOM2(nsnull, file , nsnull);
        env->ReleaseStringUTFChars(componentBaseString , componentBaseInput);
        if (NS_FAILED(rv))
        {

                char errMessage[100];
                sprintf(errMessage , "%x" , rv );
                generateException(env , PARSER_INITIALIZATION_EXCEPTION , 
"Starting
XPCOM Failed : %s");
        }

        nsresult result = NS_OK;

  sink = &javaContentSink;

}




JNIEXPORT void JNICALL
Java_com_dappit_Dapper_parser_MozillaParser_setDebug
  (JNIEnv *, jobject, jboolean aDoDebug)
  {
          JavaContentSink::setDebug((bool)aDoDebug);
  }


JNIEXPORT void JNICALL
Java_com_dappit_Dapper_parser_MozillaParser_parseHtml
  (JNIEnv *env, jobject mozillaParserObject, jstring stringToParse)
{

        jboolean iscopy;
        const char *parserInput = env->GetStringUTFChars(stringToParse,
&iscopy);
        int htmlLength = (int)env->GetStringLength(stringToParse);
//      printf("Got html : %s\nString Size:%d\n" , parserInput ,
htmlLength);
        printf("Parsing Html...");


          // Create a parser
  nsresult result = NS_OK;



  nsCOMPtr<nsIParser> parser(do_CreateInstance(kParserCID, &result));
  if (NS_FAILED(result)) {
    printf("\nUnable to create a parser : %x \n" , result);
    return;
  }


//nsIContentSink* sink;
//JavaContentSink javaContentSink;

javaContentSink.setJavaEnviroment(env , mozillaParserObject);




//   Create a dtd
  nsCOMPtr<nsIDTD> dtd(do_CreateInstance(kNavDTDCID, &result));
  if(NS_FAILED(result)) {
    printf("Unable to create a dtd\n");
    return;
  }
   parser->RegisterDTD(dtd);


  //printf("creating a stream out of input html...\n");
  nsString stream;
  stream.AppendWithConversion(parserInput , htmlLength);

//  printf("Preparing parser for parsing...\n");


//  sink = &javaContentSink;



  parser->SetContentSink(sink);
//  printf("parsing...\n");
 parser->Parse(stream, 0, NS_LITERAL_CSTRING("text/html"), PR_FALSE,
PR_TRUE);
  //parser->SetContentSink(nsnull);
  //sink->SetParser(nsnull);
 env->ReleaseStringUTFChars(stringToParse , parserInput);

}


Thanks

Ohad Serfaty

_______________________________________________
dev-embedding mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-embedding

Reply via email to