xmlServer.cxx

Go to the documentation of this file.
00001 /********************************************************************\
00002 
00003   Name:         xmlServer.cxx
00004   Created by:   Konstantin Olchanski
00005 
00006   Contents:     Serve XML-encoded ROOT objects through a TCP socket
00007 
00008   $Id$
00009 
00010 \********************************************************************/
00011 
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <assert.h>
00015 
00016 #include "xmlServer.h"
00017 
00018 /*==== ROOT socket histo server ====================================*/
00019 
00020 #if 1
00021 #define THREADRETURN
00022 #define THREADTYPE void
00023 #endif
00024 #if defined( OS_WINNT )
00025 #define THREADRETURN 0
00026 #define THREADTYPE DWORD WINAPI
00027 #endif
00028 #ifndef THREADTYPE
00029 #define THREADTYPE int
00030 #define THREADRETURN 0
00031 #endif
00032 
00033 #include <TROOT.h>
00034 #include <TClass.h>
00035 #include <TDirectory.h>
00036 #include <TKey.h>
00037 #include <TFolder.h>
00038 #include <TSocket.h>
00039 #include <TServerSocket.h>
00040 #include <TThread.h>
00041 #include <TMessage.h>
00042 #include <TObjString.h>
00043 #include <TH1.h>
00044 #include <TCutG.h>
00045 #include <TBufferXML.h>
00046 
00047 #include <deque>
00048 #include <map>
00049 #include <string>
00050 
00051 class XLockRootGuard
00052 {
00053 public:
00054    bool fIsLocked;
00055 
00056    XLockRootGuard() // ctor
00057    {
00058       TThread::Lock();
00059       fIsLocked = true;
00060    }
00061 
00062    ~XLockRootGuard() // dtor
00063    {
00064       if (fIsLocked)
00065          Unlock();
00066    }
00067 
00068    void Unlock()
00069    {
00070       fIsLocked = false;
00071       TThread::UnLock();
00072    };
00073 };
00074 
00075 static bool gVerbose = false;
00076 
00077 static std::deque<std::string> gExports;
00078 static std::map<std::string,std::string> gExportNames;
00079 
00080 /*------------------------------------------------------------------*/
00081 
00082 static std::string HtmlEncode(const char* s)
00083 {
00084    std::string r;
00085    while (*s) {
00086       char c = *s;
00087       if (c == '<') {
00088          r += "&lt;";
00089       } else if (c == '>') {
00090          r += "&gt;";
00091       } else if (c == '&') {
00092          r += "&amp;";
00093       } else {
00094          r += c;
00095       }
00096       s++;
00097    }
00098    return r;
00099 }
00100 
00101 static std::string UrlEncode(const char* s)
00102 {
00103    std::string r;
00104    while (*s) {
00105       char c = *s;
00106       if (isalpha(c)) {
00107          r += c;
00108       } else if (isdigit(c)) {
00109          r += c;
00110       } else {
00111          char buf[16];
00112          sprintf(buf, "%%%02x", c);
00113          r += buf;
00114       }
00115       s++;
00116    }
00117    return r;
00118 }
00119 
00120 static int atohex(int a)
00121 {
00122    if (a>='0' && a<='9')
00123       return a-'0';
00124    if (a>='a' && a<='f')
00125       return a-'a'+10;
00126    if (a>='A' && a<='F')
00127       return a-'A'+10;
00128    return 0;
00129 }
00130 
00131 static std::string HtmlDecode(const char* s)
00132 {
00133    std::string r;
00134    while (*s) {
00135       if (*s == '%') {
00136          s++;
00137          char c = 0;
00138          c = c*16 + atohex(s[0]);
00139          c = c*16 + atohex(s[1]);
00140          r += c;
00141 
00142          // be careful when incrementing "s" to not overrun the '\0' string terminator!
00143          if (*s)
00144             s++;
00145          if (*s)
00146             s++;
00147       } else {
00148          r += *s++;
00149       }
00150    }
00151    return r;
00152 }
00153 
00154 /*------------------------------------------------------------------*/
00155 
00156 static TObject* FollowPath(TObject* container, char* path)
00157 {
00158   if (0)
00159     printf("Follow path [%s] in container %p\n", path, container);
00160 
00161   while (1)
00162     {
00163       while (*path == '/')
00164         path++;
00165 
00166       char* s = strchr(path,'/');
00167 
00168       if (s)
00169         *s = 0;
00170 
00171       TObject *obj = NULL;
00172 
00173       std::string xpath = HtmlDecode(path);
00174       //printf("FindObject %s, decoded [%s]\n", path, xpath.c_str());
00175 
00176       if (container->InheritsFrom(TDirectory::Class()))
00177         obj = ((TDirectory*)container)->FindObject(xpath.c_str());
00178       else if (container->InheritsFrom(TFolder::Class()))
00179         obj = ((TFolder*)container)->FindObject(xpath.c_str());
00180       else if (container->InheritsFrom(TCollection::Class()))
00181         obj = ((TCollection*)container)->FindObject(xpath.c_str());
00182       else
00183         {
00184           fprintf(stderr, "XmlServer: ERROR: Container \'%s\' of type %s is not a TDirectory, TFolder or TCollection\n", container->GetName(), container->IsA()->GetName());
00185           return NULL;
00186         }
00187 
00188       if (!obj)
00189         return NULL;
00190 
00191       if (!s)
00192         return obj;
00193 
00194       container = obj;
00195 
00196       path = s+1;
00197     }
00198   /* NOT REACHED */
00199 }
00200 
00201 static TObject* FindTopLevelObject(const char* name)
00202 {
00203    TObject *obj = NULL;
00204    //gROOT->GetListOfFiles()->Print();
00205    obj = gROOT->GetListOfFiles()->FindObject(name);
00206    if (obj)
00207       return obj;
00208    obj = gROOT->FindObjectAny(name);
00209    if (obj)
00210       return obj;
00211    return NULL;
00212 }
00213 
00214 static TObject* TopLevel(char* path, char**opath)
00215 {
00216   if (0)
00217     printf("Extract top level object from [%s]\n", path);
00218 
00219   while (*path == '/')
00220     path++;
00221 
00222   char* s = strchr(path,'/');
00223   
00224   if (s)
00225     {
00226       *s = 0;
00227       *opath = s+1;
00228     }
00229   else
00230     {
00231       *opath = NULL;
00232     }
00233 
00234   std::string xpath = HtmlDecode(path);
00235 
00236   TObject *obj = NULL;
00237 
00238   for (unsigned int i=0; i<gExports.size(); i++)
00239     {
00240       const char* ename = gExports[i].c_str();
00241       //printf("Compare [%s] and [%s]\n", xpath.c_str(), ename);
00242       if (strcmp(xpath.c_str(), ename) == 0)
00243         {
00244           const char* xname = gExportNames[ename].c_str();
00245           obj = FindTopLevelObject(xname);
00246           //printf("Lookup of [%s] returned %p\n", xname, obj);
00247           break;
00248         }
00249     }
00250 
00251   if (!obj)
00252     {
00253       fprintf(stderr, "XmlServer: ERROR: Top level object \'%s\' not found in exports list\n", xpath.c_str());
00254       return NULL;
00255     }
00256 
00257   return obj;
00258 }
00259 
00260 static TObject* FollowPath(char* path)
00261 {
00262   if (0)
00263     printf("Follow path [%s]\n", path);
00264 
00265   char *s;
00266   TObject *obj = TopLevel(path, &s);
00267 
00268   if (!obj)
00269     return NULL;
00270 
00271   if (!s)
00272     return obj;
00273 
00274   return FollowPath(obj, s);
00275 }
00276 
00277 /*------------------------------------------------------------------*/
00278 
00279 static void ResetObject(TObject* obj)
00280 {
00281   assert(obj!=NULL);
00282 
00283   if (gVerbose)
00284     printf("ResetObject object %p name [%s] type [%s]\n", obj, obj->GetName(), obj->IsA()->GetName());
00285 
00286   if (obj->InheritsFrom(TH1::Class()))
00287     {
00288       ((TH1*)obj)->Reset();
00289     }
00290   else if (obj->InheritsFrom(TDirectory::Class()))
00291     {
00292       TDirectory* dir = (TDirectory*)obj;
00293       TList* objs = dir->GetList();
00294 
00295       TIter next = objs;
00296       while(1)
00297         {
00298           TObject *obj = next();
00299           if (obj == NULL)
00300             break;
00301           ResetObject(obj);
00302         }
00303     }
00304 }
00305 
00306 /*------------------------------------------------------------------*/
00307 
00308 static void SendString(TSocket* sock, const char* str)
00309 {
00310    sock->SendRaw(str, strlen(str));
00311 }
00312 
00313 static void SendHttpReply(TSocket* sock, const char* mimetype, const char* message)
00314 {
00315    char buf[256];
00316    int len = strlen(message);
00317    SendString(sock, "HTTP/1.1 200 OK\n");
00318    //SendString(sock, "Date: Tue, 15 May 2012 16:50:31 GMT\n");
00319    SendString(sock, "Server: ROOTANA xmlServer\n");
00320    sprintf(buf, "Content-Length: %d\n", len);
00321    SendString(sock, buf);
00322    //Connection: close\n
00323    sprintf(buf, "Content-Type: %s\n", mimetype);
00324    SendString(sock, buf);
00325    //charset=iso-8859-1\n
00326    SendString(sock, "\n");
00327    SendString(sock, message);
00328    printf("XmlServer: Reply content-length %d, content-type %s\n", len, mimetype);
00329 }
00330 
00331 static void SendHttpReply(TSocket* sock, const char* mimetype, const std::string& str)
00332 {
00333    SendHttpReply(sock, mimetype, str.c_str());
00334 }
00335 
00336 /*------------------------------------------------------------------*/
00337 
00338 static std::string HtmlTag(const char* tag, const char* contents)
00339 {
00340    std::string s;
00341    s += "<";
00342    s += tag;
00343    s += ">";
00344    s += contents;
00345    s += "</";
00346    s += tag;
00347    s += ">";
00348    return s;
00349 }
00350 
00351 static std::string HtmlTag(const char* tag, const std::string& contents)
00352 {
00353    std::string s;
00354    s += "<";
00355    s += tag;
00356    s += ">";
00357    s += contents;
00358    s += "</";
00359    s += tag;
00360    s += ">";
00361    return s;
00362 }
00363 
00364 /*------------------------------------------------------------------*/
00365 
00366 std::string MakeXmlEntry(const TObject* obj)
00367 {
00368    const char* objname = obj->GetName();
00369    const char* classname = obj->ClassName();
00370    bool isSubdir = false;
00371    std::string xkey = "";
00372 
00373    if (obj->InheritsFrom(TKey::Class())) {
00374       TKey* key = (TKey*)obj;
00375       classname = key->GetClassName();
00376       xkey = "<key/>";
00377    }
00378 
00379    const TClass *xclass = TClass::GetClass(classname);
00380 
00381    if (xclass->InheritsFrom(TDirectory::Class()))
00382       isSubdir = true;
00383 
00384    if (xclass->InheritsFrom(TFolder::Class()))
00385       isSubdir = true;
00386 
00387    if (xclass->InheritsFrom(TCollection::Class()))
00388       isSubdir = true;
00389 
00390    //printf("xclass %s, classname %s, subdir %d\n", xclass->GetName(), classname, isSubdir);
00391 
00392    if (isSubdir)
00393       return HtmlTag("subdir", HtmlTag("name", HtmlEncode(objname)) + HtmlTag("class", HtmlEncode(classname)) + xkey) + "\n";
00394    else
00395       return HtmlTag("object", HtmlTag("name", HtmlEncode(objname)) + HtmlTag("class", HtmlEncode(classname)) + xkey) + "\n";
00396 }
00397 
00398 std::string MakeHtmlEntry(const TObject* obj, const char* path)
00399 {
00400    const char* objname = obj->GetName();
00401    const char* classname = obj->ClassName();
00402    bool isKey = false;
00403 
00404    if (obj->InheritsFrom(TKey::Class())) {
00405       TKey* key = (TKey*)obj;
00406       classname = key->GetClassName();
00407       isKey = true;
00408    }
00409 
00410    std::string s;
00411 
00412    s += "<a href=\"";
00413    s += path; //dir->GetName();
00414    s += "/";
00415    s += UrlEncode(objname);
00416    s += "\">";
00417    s += objname;
00418    s += "</a>\n";
00419    s += " (";
00420    s += classname;
00421    s += ")";
00422    if (isKey)
00423       s += "-KEY";
00424    s += " ";
00425    s += "<a href=\"";
00426    s += path; //dir->GetName();
00427    s += "/";
00428    s += UrlEncode(objname);
00429    s += ".xml";
00430    s += "\">";
00431    s += "XML</a>\n";
00432 
00433    return s;
00434 }
00435    
00436 /*------------------------------------------------------------------*/
00437 
00438 static void SendFile(TSocket* sock, const char* filename, const char* mimetype)
00439 {
00440    std::string f = filename;
00441    std::string reply;
00442    FILE *fp = fopen(f.c_str(), "r");
00443    if (!fp) {
00444       std::string home = getenv("HOME");
00445       f = home + "/packages/rootana/libXmlServer/" + filename;
00446       fp = fopen(f.c_str(), "r");
00447    }
00448    printf("sending file %s, fp %p\n", f.c_str(), fp);
00449    if (fp) {
00450       while (1) {
00451          char buf[1024+1];
00452          int rd = fread(buf, 1, sizeof(buf)-1, fp);
00453          if (rd <= 0)
00454             break;
00455          buf[rd] = 0;
00456          reply += buf;
00457       }
00458       fclose(fp);
00459    }
00460    SendHttpReply(sock, mimetype, reply);
00461 }
00462 
00463 /*------------------------------------------------------------------*/
00464 
00465 static THREADTYPE xroot_server_thread(void *arg)
00466 /*
00467   Serve histograms over TCP/IP socket link
00468 */
00469 {
00470    char request[2560];
00471 
00472    TSocket *sock = (TSocket *) arg;
00473    //TMessage message(kMESS_OBJECT);
00474 
00475    do {
00476 
00477       /* close connection if client has disconnected */
00478       int rd = sock->RecvRaw(request, sizeof(request), kDontBlock); // (ESendRecvOptions)-1);
00479       if (rd <= 0)
00480         {
00481           if (gVerbose)
00482             fprintf(stderr, "XmlServer: connection from %s closed\n", sock->GetInetAddress().GetHostName());
00483           sock->Close();
00484           delete sock;
00485           return THREADRETURN;
00486         }
00487 
00488       if (1) {
00489          char *p;
00490          p = strchr(request, '\n');
00491          if (p)
00492             *p = 0;
00493          
00494          p = strchr(request, '\r');
00495          if (p)
00496             *p = 0;
00497       }
00498          
00499       if (gVerbose)
00500         printf("XmlServer: Request [%s] from %s\n", request, sock->GetInetAddress().GetHostName());
00501 
00502       if (0) {} 
00503       else if (strstr(request, "GET / "))
00504         {
00505           // enumerate top level exported directories
00506 
00507           XLockRootGuard lock;
00508           
00509           std::string reply;
00510 
00511           reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00512           reply += HtmlTag("title", "Export list") + "\n";
00513           reply += "</head><body>\n";
00514           reply += HtmlTag("h1", "Export list") + "\n";
00515 
00516           for (unsigned int i=0; i<gExports.size(); i++) {
00517              const char* ename = gExports[i].c_str();
00518              const char* xname = gExportNames[ename].c_str();
00519              
00520              TObject* obj = FindTopLevelObject(xname);
00521              
00522              if (obj) {
00523                 std::string s;
00524                 s += " ";
00525                 s += "<a href=\"";
00526                 s += UrlEncode(ename);
00527                 s += "\">";
00528                 s += ename;
00529                 s += "</a>\n";
00530                 s += "<a href=\"";
00531                 s += UrlEncode(ename);
00532                 s += ".xml";
00533                 s += "\">";
00534                 s += "XML</a>\n";
00535                 reply += HtmlTag("p", s) + "\n";
00536              } else {
00537                 std::string s;
00538                 s += ename;
00539                 s += " (cannot be found. maybe deleted?)\n";
00540                 reply += HtmlTag("p", s) + "\n";
00541              }
00542           }
00543           
00544           lock.Unlock();
00545 
00546           reply += "</body></html>\n";
00547           SendHttpReply(sock, "text/html", reply);
00548         }
00549       //else if (strstr(request, "GET /plot.html "))
00550       //  {
00551       //    SendFile(sock, "plot.html", "text/html");
00552       //  }
00553       else if (strstr(request, "js/jquery.min.js "))
00554         {
00555           SendFile(sock, "jquery.min.js", "text/javascript");
00556         }
00557       else if (strstr(request, "js/highcharts.js "))
00558         {
00559           SendFile(sock, "highcharts.js", "text/javascript");
00560         }
00561       else if (strstr(request, "js/exporting.js "))
00562         {
00563           SendFile(sock, "exporting.js", "text/javascript");
00564         }
00565       else if (strstr(request, "GET /favicon.ico "))
00566         {
00567           std::string reply;
00568 
00569           reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00570           reply += HtmlTag("title", "No favicon") + "\n";
00571           reply += "</head><body>\n";
00572           reply += HtmlTag("h1", "No favicon") + "\n";
00573           reply += HtmlTag("p", "No favicon") + "\n";
00574           reply += "</body></html>\n";
00575           SendHttpReply(sock, "text/html", reply);
00576         }
00577       else if (strstr(request, "GET /index.xml "))
00578         {
00579           // enumerate top level exported directories
00580 
00581           XLockRootGuard lock;
00582 
00583           std::string xml;
00584 
00585           xml += "<xml>\n";
00586           xml += "<dir>\n";
00587           
00588           for (unsigned int i=0; i<gExports.size(); i++)
00589             {
00590               const char* ename = gExports[i].c_str();
00591               const char* xname = gExportNames[ename].c_str();
00592 
00593               TObject* obj = FindTopLevelObject(xname);
00594 
00595               if (!obj) {
00596                  xml += HtmlTag("subdir", HtmlTag("name", HtmlEncode(ename)) + "<deleted/>") + "\n";
00597                  continue;
00598               }
00599 
00600               const char* cname = obj->ClassName();
00601 
00602               xml += HtmlTag("subdir", HtmlTag("name", HtmlEncode(ename)) + HtmlTag("class", HtmlEncode(cname))) + "\n";
00603             }
00604           
00605           lock.Unlock();
00606 
00607           xml += "</dir>\n";
00608           xml += "</xml>\n";
00609 
00610           SendHttpReply(sock, "application/xml", xml);
00611         }
00612       else if (strncmp(request, "GET /", 5) == 0)
00613         {
00614           XLockRootGuard lock;
00615 
00616           char* dirname = request + 5;
00617 
00618           char* x = strstr(dirname, " HTTP");
00619           if (x)
00620              *x = 0;
00621 
00622           bool xmlOutput = false;
00623 
00624           x = strstr(dirname, ".xml");
00625           if (x) {
00626              *x = 0;
00627              xmlOutput = true;
00628           }
00629 
00630           std::string path;
00631           path += "/";
00632           path += dirname;
00633 
00634           std::string xpath = HtmlDecode(dirname);
00635 
00636           //printf("path [%s] dirname [%s] xpath [%s]\n", path.c_str(), dirname, xpath.c_str());
00637 
00638           TObject* obj = FollowPath(dirname);
00639 
00640           if (!obj) {
00641              std::string reply;
00642              std::string buf;
00643              
00644              reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00645 
00646              buf = "Not found ";
00647              buf += xpath;
00648              reply += HtmlTag("title", buf) + "\n";
00649              reply += "</head><body>\n";
00650              reply += HtmlTag("h1", buf) + "\n";
00651              
00652              reply += HtmlTag("p", "Object not found");
00653 
00654              reply += "</body></html>\n";
00655              SendHttpReply(sock, "text/html", reply);
00656 
00657           } else if (obj && obj->InheritsFrom(TDirectory::Class())) {
00658              TDirectory* dir = (TDirectory*)obj;
00659 
00660              std::string reply;
00661              std::string buf;
00662              std::string xml;
00663 
00664              xml += "<xml>\n";
00665              xml += "<dir>\n";
00666              
00667              reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00668 
00669              buf = "Dir ";
00670              buf += xpath;
00671              reply += HtmlTag("title", buf) + "\n";
00672              reply += "</head><body>\n";
00673              reply += HtmlTag("h1", buf) + "\n";
00674 
00675              //printf("Directory %p\n", dir);
00676              //dir->Print();
00677 
00678              std::map<std::string, std::string> alist;
00679 
00680              if (1) {
00681                 TList* keys = dir->GetListOfKeys();
00682 
00683                 //printf("Directory %p keys:\n", dir);
00684                 //keys->Print();
00685              
00686                 TIter next = keys;
00687                 while(1) {
00688                    TObject *obj = next();
00689                    
00690                    //printf("object %p\n", obj);
00691                    
00692                    if (obj == NULL)
00693                       break;
00694 
00695                    std::string a = HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
00696                    //alist[objname] = a;
00697                    reply += a;
00698                    
00699                    xml += MakeXmlEntry(obj);
00700                 }
00701              }
00702 
00703              if (1) {
00704                 TList* objs = dir->GetList();
00705              
00706                 //printf("Directory %p objects:\n", dir);
00707                 //objs->Print();
00708                 
00709                 TIter next = objs;
00710                 while(1)
00711                    {
00712                       TObject *obj = next();
00713                       
00714                       //printf("object %p\n", obj);
00715                       
00716                       if (obj == NULL)
00717                          break;
00718                       
00719                       std::string a = HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
00720                       //alist[objname] = a;
00721                       reply += a;
00722 
00723                       xml += MakeXmlEntry(obj);
00724                    }
00725              }
00726                 
00727              lock.Unlock();
00728              
00729              if (1) {
00730                 std::map<std::string, std::string>::iterator iter = alist.begin();
00731                 for (; iter!=alist.end(); iter++) {
00732                    // iter->first is your key
00733                    // iter->second is it''s value
00734                    reply += iter->second;
00735                 }
00736              }
00737               
00738              reply += "</body></html>\n";
00739 
00740              xml += "</dir></xml>\n";
00741 
00742              if (xmlOutput)
00743                 SendHttpReply(sock, "application/xml", xml);
00744              else
00745                 SendHttpReply(sock, "text/html", reply);
00746              
00747           } else if (obj && obj->InheritsFrom(TFolder::Class())) {
00748              TFolder* folder = (TFolder*)obj;
00749 
00750              //printf("Folder %p\n", folder);
00751              //folder->Print();
00752 
00753              std::string xml;
00754 
00755              xml += "<xml>\n";
00756              xml += "<dir>\n";
00757              
00758              std::string reply;
00759              std::string buf;
00760              
00761              reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00762 
00763              buf = "Folder ";
00764              buf += xpath;
00765              reply += HtmlTag("title", buf) + "\n";
00766              reply += "</head><body>\n";
00767              reply += HtmlTag("h1", buf) + "\n";
00768              
00769              TIterator *iterator = folder->GetListOfFolders()->MakeIterator();
00770              
00771              while (1)
00772                 {
00773                    TNamed *obj = (TNamed*)iterator->Next();
00774                    if (obj == NULL)
00775                       break;
00776                    
00777                    reply += HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
00778                    xml += MakeXmlEntry(obj);
00779                 }
00780              
00781              delete iterator;
00782 
00783              lock.Unlock();
00784 
00785              xml += "</dir></xml>\n";
00786              reply += "</body></html>\n";
00787 
00788              if (xmlOutput)
00789                 SendHttpReply(sock, "application/xml", xml);
00790              else
00791                 SendHttpReply(sock, "text/html", reply);
00792 
00793           } else if (obj && obj->InheritsFrom(TCollection::Class())) {
00794              TCollection* collection = (TCollection*)obj;
00795              
00796              //printf("Collection %p\n", collection);
00797              //collection->Print();
00798              //printf("Entries %d\n", collection->GetEntries());
00799              //printf("IsEmpty %d\n", collection->IsEmpty());
00800              
00801              std::string xml;
00802 
00803              xml += "<xml>\n";
00804              xml += "<dir>\n";
00805              
00806              std::string reply;
00807              std::string buf;
00808              
00809              reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00810 
00811              buf = "Collection ";
00812              buf += xpath;
00813              reply += HtmlTag("title", buf) + "\n";
00814              reply += "</head><body>\n";
00815              reply += HtmlTag("h1", buf) + "\n";
00816              
00817              TIterator *iterator = collection->MakeIterator();
00818              
00819              while (1)
00820                 {
00821                    TNamed *obj = (TNamed*)iterator->Next();
00822                    if (obj == NULL)
00823                       break;
00824                    
00825                    reply += HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
00826                    xml += MakeXmlEntry(obj);
00827                 }
00828              
00829              delete iterator;
00830 
00831              lock.Unlock();
00832              
00833              xml += "</dir></xml>\n";
00834              reply += "</body></html>\n";
00835 
00836              if (xmlOutput)
00837                 SendHttpReply(sock, "application/xml", xml);
00838              else
00839                 SendHttpReply(sock, "text/html", reply);
00840 
00841           } else {
00842              if (xmlOutput) {
00843                 std::string xml;
00844                 xml += "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
00845                 xml += "<xml>\n";
00846                 xml += "<ROOTobject>\n";
00847                 TString msg = TBufferXML::ConvertToXML(obj);
00848                 xml += msg;
00849                 xml += "</ROOTobject>\n";
00850                 xml += "</xml>\n";
00851                 lock.Unlock();
00852                 SendHttpReply(sock, "application/xml", xml);
00853              } else {
00854                 SendFile(sock, "plot.html", "text/html");
00855                 if (0) {
00856                 std::string reply;
00857                 std::string buf;
00858                 
00859                 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00860                 
00861                 buf = "Object ";
00862                 buf += xpath;
00863                 reply += HtmlTag("title", buf) + "\n";
00864                 reply += "</head><body>\n";
00865                 reply += HtmlTag("h1", buf) + "\n";
00866                 
00867                 reply += HtmlTag("p", obj->GetName());
00868                 reply += HtmlTag("p", obj->ClassName());
00869                 
00870                 reply += "</body></html>\n";
00871                 SendHttpReply(sock, "text/html", reply);
00872                 }
00873              }
00874           }
00875         }
00876 #if 0
00877       else if (strncmp(request, "ResetTH1 ", 9) == 0)
00878         {
00879           XLockRootGuard lock;
00880           
00881           char* path = request + 9;
00882 
00883           if (strlen(path) > 1)
00884             {
00885               TObject *obj = FollowPath(path);
00886 
00887               if (obj)
00888                 ResetObject(obj);
00889             }
00890           else
00891             {
00892               for (unsigned int i=0; i<gExports.size(); i++)
00893                 {
00894                   const char* ename = gExports[i].c_str();
00895                   const char* xname = gExportNames[ename].c_str();
00896 
00897                   TObject* obj = FindTopLevelObject(xname);
00898 
00899                   if (!obj)
00900                     {
00901                       fprintf(stderr, "XmlServer: ResetTH1: Exported name \'%s\' cannot be found!\n", xname);
00902                       continue;
00903                     }
00904 
00905                   ResetObject(obj);
00906                 }
00907             }
00908           
00909           //TObjString s("Success");
00910 
00911           //message.Reset(kMESS_OBJECT);
00912           //message.WriteObject(&s);
00913           lock.Unlock();
00914           //sock->Send(message);
00915 
00916           const char *msg = "Success";
00917           sock->SendRaw(msg, strlen(msg) + 1);
00918         }
00919 #endif
00920       else
00921         {
00922           fprintf(stderr, "XmlServer: Received unknown request \"%s\"\n", request);
00923 
00924           std::string reply;
00925           reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
00926           reply += HtmlTag("title", "Unknown request") + "\n";
00927           reply += "</head><body>\n";
00928           reply += HtmlTag("h1", "Unknown request") + "\n";
00929           reply += HtmlTag("p", request) + "\n";
00930           reply += "</body></html>\n";
00931           SendHttpReply(sock, "text/html", reply);
00932         }
00933    } while (1);
00934 
00935    return THREADRETURN;
00936 }
00937 
00938 /*------------------------------------------------------------------*/
00939 
00940 static THREADTYPE xsocket_listener(void *arg)
00941 {
00942   // Server loop listening for incoming network connections on specified port.
00943   // Starts a searver_thread for each connection.
00944 
00945   int port = *(int *) arg;
00946   
00947   fprintf(stderr, "XmlServer: Listening on port %d...\n", port);
00948   TServerSocket *lsock = new TServerSocket(port, kTRUE);
00949   
00950   while (1)
00951     {
00952       TSocket *sock = lsock->Accept();
00953       
00954       if (sock==NULL)
00955         {
00956           fprintf(stderr, "XmlServer: TSocket->Accept() error\n");
00957           break;
00958         }
00959       
00960       if (gVerbose)
00961         fprintf(stderr, "XmlServer: connection from %s\n", sock->GetInetAddress().GetHostName());
00962       
00963 #if 1
00964       TThread *thread = new TThread("XmlServer", xroot_server_thread, sock);
00965       thread->Run();
00966 #else
00967       LPDWORD lpThreadId = 0;
00968       CloseHandle(CreateThread(NULL, 1024, &xroot_server_thread, sock, 0, lpThreadId));
00969 #endif
00970     }
00971   
00972   return THREADRETURN;
00973 }
00974 
00975 /*------------------------------------------------------------------*/
00976 
00977 void XmlServer::SetVerbose(bool verbose)
00978 {
00979   gVerbose = verbose;
00980 }
00981 
00982 /*------------------------------------------------------------------*/
00983 
00984 void XmlServer::Export(TDirectory* dir, const char* exportName)
00985 {
00986   if (gVerbose)
00987     printf("Export TDirectory %p named [%s] of type [%s] as [%s]\n", dir, dir->GetName(), dir->IsA()->GetName(), exportName);
00988 
00989   bool found = false;
00990   for (unsigned int i=0; i<gExports.size(); i++)
00991     {
00992       const char* ename = gExports[i].c_str();
00993       if (strcmp(ename, exportName) == 0)
00994         found = true;
00995     }
00996 
00997   if (!found)
00998     gExports.push_back(exportName);
00999   gExportNames[exportName] = dir->GetName();
01000 }
01001 
01002 void XmlServer::Export(TFolder* folder, const char* exportName)
01003 {
01004   if (gVerbose)
01005     printf("Export TFolder %p named [%s] of type [%s] as [%s]\n", folder, folder->GetName(), folder->IsA()->GetName(), exportName);
01006 
01007   bool found = false;
01008   for (unsigned int i=0; i<gExports.size(); i++)
01009     {
01010       const char* ename = gExports[i].c_str();
01011       if (strcmp(ename, exportName) == 0)
01012         found = true;
01013     }
01014 
01015   if (!found)
01016     gExports.push_back(exportName);
01017   gExportNames[exportName] = folder->GetName();
01018 }
01019 
01020 void XmlServer::Export(TCollection* collection, const char* exportName)
01021 {
01022   if (gVerbose)
01023     printf("Export TCollection %p named [%s] of type [%s] as [%s]\n", collection, collection->GetName(), collection->IsA()->GetName(), exportName);
01024 
01025   bool found = false;
01026   for (unsigned int i=0; i<gExports.size(); i++)
01027     {
01028       const char* ename = gExports[i].c_str();
01029       if (strcmp(ename, exportName) == 0)
01030         found = true;
01031     }
01032 
01033   if (!found)
01034     gExports.push_back(exportName);
01035   gExportNames[exportName] = collection->GetName();
01036 }
01037 
01038 void XmlServer::Start(int port)
01039 {
01040   if (port==0)
01041     return;
01042 
01043   //printf("Here!\n");
01044 
01045   static int pport = port;
01046 #if 1
01047   TThread *thread = new TThread("XmlServer", xsocket_listener, &pport);
01048   thread->Run();
01049 #else
01050   LPDWORD lpThreadId = 0;
01051   CloseHandle(CreateThread(NULL, 1024, &xroot_socket_server, &pport, 0, lpThreadId));
01052 #endif
01053 }
01054 
01055 /* emacs
01056  * Local Variables:
01057  * tab-width: 8
01058  * c-basic-offset: 3
01059  * indent-tabs-mode: nil
01060  * End:
01061  */

Generated on 12 Feb 2016 for ROOT Analyzer by  doxygen 1.6.1