ROOTANA
Loading...
Searching...
No Matches
xmlServer.cxx
Go to the documentation of this file.
1/********************************************************************\
2
3 Name: xmlServer.cxx
4 Created by: Konstantin Olchanski
5
6 Contents: Serve XML-encoded ROOT objects through a TCP socket
7
8 $Id$
9
10\********************************************************************/
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <assert.h>
15
16#include "xmlServer.h"
17
18/*==== ROOT socket histo server ====================================*/
19
20#if 1
21#define THREADRETURN
22#define THREADTYPE void
23#endif
24#if defined( OS_WINNT )
25#define THREADRETURN 0
26#define THREADTYPE DWORD WINAPI
27#endif
28#ifndef THREADTYPE
29#define THREADTYPE int
30#define THREADRETURN 0
31#endif
32
33#include <TROOT.h>
34#include <TClass.h>
35#include <TDirectory.h>
36#include <TKey.h>
37#include <TFolder.h>
38#include <TSocket.h>
39#include <TServerSocket.h>
40#include <TThread.h>
41#include <TMessage.h>
42#include <TObjString.h>
43#include <TH1.h>
44#include <TCutG.h>
45#include <TBufferXML.h>
46
47#include <deque>
48#include <map>
49#include <string>
50
52{
53public:
55
57 {
58 TThread::Lock();
59 fIsLocked = true;
60 }
61
63 {
64 if (fIsLocked)
65 Unlock();
66 }
67
68 void Unlock()
69 {
70 fIsLocked = false;
71 TThread::UnLock();
72 };
73};
74
75static bool gVerbose = false;
76
77static std::deque<std::string> gExports;
78static std::map<std::string,std::string> gExportNames;
79
80/*------------------------------------------------------------------*/
81
82static std::string HtmlEncode(const char* s)
83{
84 std::string r;
85 while (*s) {
86 char c = *s;
87 if (c == '<') {
88 r += "&lt;";
89 } else if (c == '>') {
90 r += "&gt;";
91 } else if (c == '&') {
92 r += "&amp;";
93 } else {
94 r += c;
95 }
96 s++;
97 }
98 return r;
99}
100
101static std::string UrlEncode(const char* s)
102{
103 std::string r;
104 while (*s) {
105 char c = *s;
106 if (isalpha(c)) {
107 r += c;
108 } else if (isdigit(c)) {
109 r += c;
110 } else {
111 char buf[16];
112 sprintf(buf, "%%%02x", c);
113 r += buf;
114 }
115 s++;
116 }
117 return r;
118}
119
120static int atohex(int a)
121{
122 if (a>='0' && a<='9')
123 return a-'0';
124 if (a>='a' && a<='f')
125 return a-'a'+10;
126 if (a>='A' && a<='F')
127 return a-'A'+10;
128 return 0;
129}
130
131static std::string HtmlDecode(const char* s)
132{
133 std::string r;
134 while (*s) {
135 if (*s == '%') {
136 s++;
137 char c = 0;
138 c = c*16 + atohex(s[0]);
139 c = c*16 + atohex(s[1]);
140 r += c;
141
142 // be careful when incrementing "s" to not overrun the '\0' string terminator!
143 if (*s)
144 s++;
145 if (*s)
146 s++;
147 } else {
148 r += *s++;
149 }
150 }
151 return r;
152}
153
154/*------------------------------------------------------------------*/
155
156static TObject* FollowPath(TObject* container, char* path)
157{
158 if (0)
159 printf("Follow path [%s] in container %p\n", path, container);
160
161 while (1)
162 {
163 while (*path == '/')
164 path++;
165
166 char* s = strchr(path,'/');
167
168 if (s)
169 *s = 0;
170
171 TObject *obj = NULL;
172
173 std::string xpath = HtmlDecode(path);
174 //printf("FindObject %s, decoded [%s]\n", path, xpath.c_str());
175
176 if (container->InheritsFrom(TDirectory::Class()))
177 obj = ((TDirectory*)container)->FindObject(xpath.c_str());
178 else if (container->InheritsFrom(TFolder::Class()))
179 obj = ((TFolder*)container)->FindObject(xpath.c_str());
180 else if (container->InheritsFrom(TCollection::Class()))
181 obj = ((TCollection*)container)->FindObject(xpath.c_str());
182 else
183 {
184 fprintf(stderr, "XmlServer: ERROR: Container \'%s\' of type %s is not a TDirectory, TFolder or TCollection\n", container->GetName(), container->IsA()->GetName());
185 return NULL;
186 }
187
188 if (!obj)
189 return NULL;
190
191 if (!s)
192 return obj;
193
194 container = obj;
195
196 path = s+1;
197 }
198 /* NOT REACHED */
199}
200
201static TObject* FindTopLevelObject(const char* name)
202{
203 if (0)
204 printf("FindTopLevelObject [%s]\n", name);
205 if (strcmp(name, "root") == 0)
206 return gROOT;
207 TObject *obj = NULL;
208 //gROOT->GetListOfFiles()->Print();
209 obj = gROOT->GetListOfFiles()->FindObject(name);
210 if (obj)
211 return obj;
212 obj = gROOT->FindObjectAny(name);
213 if (obj)
214 return obj;
215 return NULL;
216}
217
218static TObject* TopLevel(char* path, char**opath)
219{
220 if (0)
221 printf("Extract top level object from [%s]\n", path);
222
223 while (*path == '/')
224 path++;
225
226 char* s = strchr(path,'/');
227
228 if (s)
229 {
230 *s = 0;
231 *opath = s+1;
232 }
233 else
234 {
235 *opath = NULL;
236 }
237
238 std::string xpath = HtmlDecode(path);
239
240 TObject *obj = NULL;
241
242 for (unsigned int i=0; i<gExports.size(); i++)
243 {
244 const char* ename = gExports[i].c_str();
245 //printf("Compare [%s] and [%s]\n", xpath.c_str(), ename);
246 if (strcmp(xpath.c_str(), ename) == 0)
247 {
248 const char* xname = gExportNames[ename].c_str();
249 obj = FindTopLevelObject(xname);
250 //printf("Lookup of [%s] returned %p\n", xname, obj);
251 break;
252 }
253 }
254
255 if (!obj)
256 {
257 fprintf(stderr, "XmlServer: ERROR: Top level object \'%s\' not found in exports list\n", xpath.c_str());
258 return NULL;
259 }
260
261 return obj;
262}
263
264static TObject* FollowPath(char* path)
265{
266 if (0)
267 printf("Follow path [%s]\n", path);
268
269 char *s;
270 TObject *obj = TopLevel(path, &s);
271
272 if (!obj)
273 return NULL;
274
275 if (!s)
276 return obj;
277
278 return FollowPath(obj, s);
279}
280
281/*------------------------------------------------------------------*/
282
283#if 0
284static void ResetObject(TObject* obj)
285{
286 assert(obj!=NULL);
287
288 if (gVerbose)
289 printf("ResetObject object %p name [%s] type [%s]\n", obj, obj->GetName(), obj->IsA()->GetName());
290
291 if (obj->InheritsFrom(TH1::Class()))
292 {
293 ((TH1*)obj)->Reset();
294 }
295 else if (obj->InheritsFrom(TDirectory::Class()))
296 {
297 TDirectory* dir = (TDirectory*)obj;
298 TList* objs = dir->GetList();
299
300 TIter next = objs;
301 while(1)
302 {
303 TObject *obj = next();
304 if (obj == NULL)
305 break;
306 ResetObject(obj);
307 }
308 }
309}
310#endif
311
312/*------------------------------------------------------------------*/
313
314static void SendString(TSocket* sock, const char* str)
315{
316 sock->SendRaw(str, strlen(str));
317}
318
319static void SendHttpReply(TSocket* sock, const char* mimetype, const char* message)
320{
321 char buf[256];
322 int len = strlen(message);
323 SendString(sock, "HTTP/1.1 200 OK\n");
324 //SendString(sock, "Date: Tue, 15 May 2012 16:50:31 GMT\n");
325 SendString(sock, "Server: ROOTANA xmlServer\n");
326 sprintf(buf, "Content-Length: %d\n", len);
327 SendString(sock, buf);
328 //Connection: close\n
329 sprintf(buf, "Content-Type: %s\n", mimetype);
330 SendString(sock, buf);
331 //charset=iso-8859-1\n
332 SendString(sock, "\n");
333 SendString(sock, message);
334 printf("XmlServer: Reply content-length %d, content-type %s\n", len, mimetype);
335}
336
337static void SendHttpReply(TSocket* sock, const char* mimetype, const std::string& str)
338{
339 SendHttpReply(sock, mimetype, str.c_str());
340}
341
342/*------------------------------------------------------------------*/
343
344static std::string HtmlTag(const char* tag, const char* contents)
345{
346 std::string s;
347 s += "<";
348 s += tag;
349 s += ">";
350 s += contents;
351 s += "</";
352 s += tag;
353 s += ">";
354 return s;
355}
356
357static std::string HtmlTag(const char* tag, const std::string& contents)
358{
359 std::string s;
360 s += "<";
361 s += tag;
362 s += ">";
363 s += contents;
364 s += "</";
365 s += tag;
366 s += ">";
367 return s;
368}
369
370/*------------------------------------------------------------------*/
371
372std::string MakeXmlEntry(const TObject* obj)
373{
374 const char* objname = obj->GetName();
375 const char* classname = obj->ClassName();
376 bool isSubdir = false;
377 std::string xkey = "";
378
379 if (obj->InheritsFrom(TKey::Class())) {
380 TKey* key = (TKey*)obj;
381 classname = key->GetClassName();
382 xkey = "<key/>";
383 }
384
385 const TClass *xclass = TClass::GetClass(classname);
386
387 if (xclass->InheritsFrom(TDirectory::Class()))
388 isSubdir = true;
389
390 if (xclass->InheritsFrom(TFolder::Class()))
391 isSubdir = true;
392
393 if (xclass->InheritsFrom(TCollection::Class()))
394 isSubdir = true;
395
396 //printf("xclass %s, classname %s, subdir %d\n", xclass->GetName(), classname, isSubdir);
397
398 if (isSubdir)
399 return HtmlTag("subdir", HtmlTag("name", HtmlEncode(objname)) + HtmlTag("class", HtmlEncode(classname)) + xkey) + "\n";
400 else
401 return HtmlTag("object", HtmlTag("name", HtmlEncode(objname)) + HtmlTag("class", HtmlEncode(classname)) + xkey) + "\n";
402}
403
404std::string MakeHtmlEntry(const TObject* obj, const char* path)
405{
406 const char* objname = obj->GetName();
407 const char* classname = obj->ClassName();
408 bool isKey = false;
409
410 if (obj->InheritsFrom(TKey::Class())) {
411 TKey* key = (TKey*)obj;
412 classname = key->GetClassName();
413 isKey = true;
414 }
415
416 std::string s;
417
418 s += "<a href=\"";
419 s += path; //dir->GetName();
420 s += "/";
421 s += UrlEncode(objname);
422 s += "\">";
423 s += objname;
424 s += "</a>\n";
425 s += " (";
426 s += classname;
427 s += ")";
428 if (isKey)
429 s += "-KEY";
430 s += " ";
431 s += "<a href=\"";
432 s += path; //dir->GetName();
433 s += "/";
434 s += UrlEncode(objname);
435 s += ".xml";
436 s += "\">";
437 s += "XML</a>\n";
438
439 return s;
440}
441
442/*------------------------------------------------------------------*/
443
444static void SendFile(TSocket* sock, const char* filename, const char* mimetype)
445{
446 std::string f = filename;
447 std::string reply;
448 FILE *fp = fopen(f.c_str(), "r");
449 if (!fp) {
450 std::string home = getenv("HOME");
451 f = home + "/packages/rootana/libXmlServer/" + filename;
452 fp = fopen(f.c_str(), "r");
453 }
454 printf("sending file %s, fp %p\n", f.c_str(), fp);
455 if (fp) {
456 while (1) {
457 char buf[1024+1];
458 int rd = fread(buf, 1, sizeof(buf)-1, fp);
459 if (rd <= 0)
460 break;
461 buf[rd] = 0;
462 reply += buf;
463 }
464 fclose(fp);
465 }
466 SendHttpReply(sock, mimetype, reply);
467}
468
469/*------------------------------------------------------------------*/
470
472/*
473 Serve histograms over TCP/IP socket link
474*/
475{
476 char request[2560];
477
478 TSocket *sock = (TSocket *) arg;
479 //TMessage message(kMESS_OBJECT);
480
481 do {
482
483 /* close connection if client has disconnected */
484 int rd = sock->RecvRaw(request, sizeof(request), kDontBlock); // (ESendRecvOptions)-1);
485 if (rd <= 0)
486 {
487 if (gVerbose)
488 fprintf(stderr, "XmlServer: connection from %s closed\n", sock->GetInetAddress().GetHostName());
489 sock->Close();
490 delete sock;
491 return THREADRETURN;
492 }
493
494 if (1) {
495 char *p;
496 p = strchr(request, '\n');
497 if (p)
498 *p = 0;
499
500 p = strchr(request, '\r');
501 if (p)
502 *p = 0;
503 }
504
505 if (gVerbose)
506 printf("XmlServer: Request [%s] from %s\n", request, sock->GetInetAddress().GetHostName());
507
508 if (0) {}
509 else if (strstr(request, "GET / "))
510 {
511 // enumerate top level exported directories
512
513 XLockRootGuard lock;
514
515 std::string reply;
516
517 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
518 reply += HtmlTag("title", "Export list") + "\n";
519 reply += "</head><body>\n";
520 reply += HtmlTag("h1", "Export list") + "\n";
521
522 for (unsigned int i=0; i<gExports.size(); i++) {
523 const char* ename = gExports[i].c_str();
524 const char* xname = gExportNames[ename].c_str();
525
526 TObject* obj = FindTopLevelObject(xname);
527
528 if (obj) {
529 std::string s;
530 s += " ";
531 s += "<a href=\"";
532 s += UrlEncode(ename);
533 s += "\">";
534 s += ename;
535 s += "</a>\n";
536 s += "<a href=\"";
537 s += UrlEncode(ename);
538 s += ".xml";
539 s += "\">";
540 s += "XML</a>\n";
541 reply += HtmlTag("p", s) + "\n";
542 } else {
543 std::string s;
544 s += ename;
545 s += " (cannot be found. maybe deleted?)\n";
546 reply += HtmlTag("p", s) + "\n";
547 }
548 }
549
550 lock.Unlock();
551
552 reply += "</body></html>\n";
553 SendHttpReply(sock, "text/html", reply);
554 }
555 //else if (strstr(request, "GET /plot.html "))
556 // {
557 // SendFile(sock, "plot.html", "text/html");
558 // }
559 else if (strstr(request, "js/jquery.min.js "))
560 {
561 SendFile(sock, "jquery.min.js", "text/javascript");
562 }
563 else if (strstr(request, "js/highcharts.js "))
564 {
565 SendFile(sock, "highcharts.js", "text/javascript");
566 }
567 else if (strstr(request, "js/exporting.js "))
568 {
569 SendFile(sock, "exporting.js", "text/javascript");
570 }
571 else if (strstr(request, "GET /favicon.ico "))
572 {
573 std::string reply;
574
575 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
576 reply += HtmlTag("title", "No favicon") + "\n";
577 reply += "</head><body>\n";
578 reply += HtmlTag("h1", "No favicon") + "\n";
579 reply += HtmlTag("p", "No favicon") + "\n";
580 reply += "</body></html>\n";
581 SendHttpReply(sock, "text/html", reply);
582 }
583 else if (strstr(request, "GET /index.xml "))
584 {
585 // enumerate top level exported directories
586
587 XLockRootGuard lock;
588
589 std::string xml;
590
591 xml += "<xml>\n";
592 xml += "<dir>\n";
593
594 for (unsigned int i=0; i<gExports.size(); i++)
595 {
596 const char* ename = gExports[i].c_str();
597 const char* xname = gExportNames[ename].c_str();
598
599 TObject* obj = FindTopLevelObject(xname);
600
601 if (!obj) {
602 xml += HtmlTag("subdir", HtmlTag("name", HtmlEncode(ename)) + "<deleted/>") + "\n";
603 continue;
604 }
605
606 const char* cname = obj->ClassName();
607
608 xml += HtmlTag("subdir", HtmlTag("name", HtmlEncode(ename)) + HtmlTag("class", HtmlEncode(cname))) + "\n";
609 }
610
611 lock.Unlock();
612
613 xml += "</dir>\n";
614 xml += "</xml>\n";
615
616 SendHttpReply(sock, "application/xml", xml);
617 }
618 else if (strncmp(request, "GET /", 5) == 0)
619 {
620 XLockRootGuard lock;
621
622 char* dirname = request + 5;
623
624 char* x = strstr(dirname, " HTTP");
625 if (x)
626 *x = 0;
627
628 bool xmlOutput = false;
629
630 x = strstr(dirname, ".xml");
631 if (x) {
632 *x = 0;
633 xmlOutput = true;
634 }
635
636 std::string path;
637 path += "/";
638 path += dirname;
639
640 std::string xpath = HtmlDecode(dirname);
641
642 //printf("path [%s] dirname [%s] xpath [%s]\n", path.c_str(), dirname, xpath.c_str());
643
644 TObject* obj = FollowPath(dirname);
645
646 if (!obj) {
647 std::string reply;
648 std::string buf;
649
650 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
651
652 buf = "Not found ";
653 buf += xpath;
654 reply += HtmlTag("title", buf) + "\n";
655 reply += "</head><body>\n";
656 reply += HtmlTag("h1", buf) + "\n";
657
658 reply += HtmlTag("p", "Object not found");
659
660 reply += "</body></html>\n";
661 SendHttpReply(sock, "text/html", reply);
662
663 } else if (obj && obj->InheritsFrom(TDirectory::Class())) {
664 TDirectory* dir = (TDirectory*)obj;
665
666 std::string reply;
667 std::string buf;
668 std::string xml;
669
670 xml += "<xml>\n";
671 xml += "<dir>\n";
672
673 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
674
675 buf = "Dir ";
676 buf += xpath;
677 reply += HtmlTag("title", buf) + "\n";
678 reply += "</head><body>\n";
679 reply += HtmlTag("h1", buf) + "\n";
680
681 //printf("Directory %p\n", dir);
682 //dir->Print();
683
684 std::map<std::string, std::string> alist;
685
686 if (1) {
687 TList* keys = dir->GetListOfKeys();
688
689 //printf("Directory %p keys:\n", dir);
690 //keys->Print();
691
692 TIter next = keys;
693 while(1) {
694 TObject *obj = next();
695
696 //printf("object %p\n", obj);
697
698 if (obj == NULL)
699 break;
700
701 std::string a = HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
702 //alist[objname] = a;
703 reply += a;
704
705 xml += MakeXmlEntry(obj);
706 }
707 }
708
709 if (1) {
710 TList* objs = dir->GetList();
711
712 //printf("Directory %p objects:\n", dir);
713 //objs->Print();
714
715 TIter next = objs;
716 while(1)
717 {
718 TObject *obj = next();
719
720 //printf("object %p\n", obj);
721
722 if (obj == NULL)
723 break;
724
725 std::string a = HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
726 //alist[objname] = a;
727 reply += a;
728
729 xml += MakeXmlEntry(obj);
730 }
731 }
732
733 lock.Unlock();
734
735 if (1) {
736 std::map<std::string, std::string>::iterator iter = alist.begin();
737 for (; iter!=alist.end(); iter++) {
738 // iter->first is your key
739 // iter->second is it''s value
740 reply += iter->second;
741 }
742 }
743
744 reply += "</body></html>\n";
745
746 xml += "</dir></xml>\n";
747
748 if (xmlOutput)
749 SendHttpReply(sock, "application/xml", xml);
750 else
751 SendHttpReply(sock, "text/html", reply);
752
753 } else if (obj && obj->InheritsFrom(TFolder::Class())) {
754 TFolder* folder = (TFolder*)obj;
755
756 //printf("Folder %p\n", folder);
757 //folder->Print();
758
759 std::string xml;
760
761 xml += "<xml>\n";
762 xml += "<dir>\n";
763
764 std::string reply;
765 std::string buf;
766
767 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
768
769 buf = "Folder ";
770 buf += xpath;
771 reply += HtmlTag("title", buf) + "\n";
772 reply += "</head><body>\n";
773 reply += HtmlTag("h1", buf) + "\n";
774
775 TIterator *iterator = folder->GetListOfFolders()->MakeIterator();
776
777 while (1)
778 {
779 TNamed *obj = (TNamed*)iterator->Next();
780 if (obj == NULL)
781 break;
782
783 reply += HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
784 xml += MakeXmlEntry(obj);
785 }
786
787 delete iterator;
788
789 lock.Unlock();
790
791 xml += "</dir></xml>\n";
792 reply += "</body></html>\n";
793
794 if (xmlOutput)
795 SendHttpReply(sock, "application/xml", xml);
796 else
797 SendHttpReply(sock, "text/html", reply);
798
799 } else if (obj && obj->InheritsFrom(TCollection::Class())) {
800 TCollection* collection = (TCollection*)obj;
801
802 //printf("Collection %p\n", collection);
803 //collection->Print();
804 //printf("Entries %d\n", collection->GetEntries());
805 //printf("IsEmpty %d\n", collection->IsEmpty());
806
807 std::string xml;
808
809 xml += "<xml>\n";
810 xml += "<dir>\n";
811
812 std::string reply;
813 std::string buf;
814
815 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
816
817 buf = "Collection ";
818 buf += xpath;
819 reply += HtmlTag("title", buf) + "\n";
820 reply += "</head><body>\n";
821 reply += HtmlTag("h1", buf) + "\n";
822
823 TIterator *iterator = collection->MakeIterator();
824
825 while (1)
826 {
827 TNamed *obj = (TNamed*)iterator->Next();
828 if (obj == NULL)
829 break;
830
831 reply += HtmlTag("p", MakeHtmlEntry(obj, path.c_str())) + "\n";
832 xml += MakeXmlEntry(obj);
833 }
834
835 delete iterator;
836
837 lock.Unlock();
838
839 xml += "</dir></xml>\n";
840 reply += "</body></html>\n";
841
842 if (xmlOutput)
843 SendHttpReply(sock, "application/xml", xml);
844 else
845 SendHttpReply(sock, "text/html", reply);
846
847 } else {
848 if (xmlOutput) {
849 std::string xml;
850 xml += "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
851 xml += "<xml>\n";
852 xml += "<ROOTobject>\n";
853 TString msg = TBufferXML::ConvertToXML(obj);
854 xml += msg;
855 xml += "</ROOTobject>\n";
856 xml += "</xml>\n";
857 lock.Unlock();
858 SendHttpReply(sock, "application/xml", xml);
859 } else {
860 SendFile(sock, "plot.html", "text/html");
861 if (0) {
862 std::string reply;
863 std::string buf;
864
865 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
866
867 buf = "Object ";
868 buf += xpath;
869 reply += HtmlTag("title", buf) + "\n";
870 reply += "</head><body>\n";
871 reply += HtmlTag("h1", buf) + "\n";
872
873 reply += HtmlTag("p", obj->GetName());
874 reply += HtmlTag("p", obj->ClassName());
875
876 reply += "</body></html>\n";
877 SendHttpReply(sock, "text/html", reply);
878 }
879 }
880 }
881 }
882#if 0
883 else if (strncmp(request, "ResetTH1 ", 9) == 0)
884 {
885 XLockRootGuard lock;
886
887 char* path = request + 9;
888
889 if (strlen(path) > 1)
890 {
891 TObject *obj = FollowPath(path);
892
893 if (obj)
894 ResetObject(obj);
895 }
896 else
897 {
898 for (unsigned int i=0; i<gExports.size(); i++)
899 {
900 const char* ename = gExports[i].c_str();
901 const char* xname = gExportNames[ename].c_str();
902
903 TObject* obj = FindTopLevelObject(xname);
904
905 if (!obj)
906 {
907 fprintf(stderr, "XmlServer: ResetTH1: Exported name \'%s\' cannot be found!\n", xname);
908 continue;
909 }
910
911 ResetObject(obj);
912 }
913 }
914
915 //TObjString s("Success");
916
917 //message.Reset(kMESS_OBJECT);
918 //message.WriteObject(&s);
919 lock.Unlock();
920 //sock->Send(message);
921
922 const char *msg = "Success";
923 sock->SendRaw(msg, strlen(msg) + 1);
924 }
925#endif
926 else
927 {
928 fprintf(stderr, "XmlServer: Received unknown request \"%s\"\n", request);
929
930 std::string reply;
931 reply += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
932 reply += HtmlTag("title", "Unknown request") + "\n";
933 reply += "</head><body>\n";
934 reply += HtmlTag("h1", "Unknown request") + "\n";
935 reply += HtmlTag("p", request) + "\n";
936 reply += "</body></html>\n";
937 SendHttpReply(sock, "text/html", reply);
938 }
939 } while (1);
940
941 return THREADRETURN;
942}
943
944/*------------------------------------------------------------------*/
945
947{
948 // Server loop listening for incoming network connections on specified port.
949 // Starts a searver_thread for each connection.
950
951 int port = *(int *) arg;
952
953 fprintf(stderr, "XmlServer: Listening on port %d...\n", port);
954 TServerSocket *lsock = new TServerSocket(port, kTRUE);
955
956 while (1)
957 {
958 TSocket *sock = lsock->Accept();
959
960 if (sock==NULL)
961 {
962 fprintf(stderr, "XmlServer: TSocket->Accept() error\n");
963 break;
964 }
965
966 if (gVerbose)
967 fprintf(stderr, "XmlServer: connection from %s\n", sock->GetInetAddress().GetHostName());
968
969#if 1
970 TThread *thread = new TThread("XmlServer", xroot_server_thread, sock);
971 thread->Run();
972#else
973 LPDWORD lpThreadId = 0;
974 CloseHandle(CreateThread(NULL, 1024, &xroot_server_thread, sock, 0, lpThreadId));
975#endif
976 }
977
978 return THREADRETURN;
979}
980
981/*------------------------------------------------------------------*/
982
983void XmlServer::SetVerbose(bool verbose)
984{
985 gVerbose = verbose;
986}
987
988/*------------------------------------------------------------------*/
989
990void XmlServer::Export(TDirectory* dir, const char* exportName)
991{
992 if (gVerbose)
993 printf("Export TDirectory %p named [%s] of type [%s] as [%s]\n", dir, dir->GetName(), dir->IsA()->GetName(), exportName);
994
995 bool found = false;
996 for (unsigned int i=0; i<gExports.size(); i++)
997 {
998 const char* ename = gExports[i].c_str();
999 if (strcmp(ename, exportName) == 0)
1000 found = true;
1001 }
1002
1003 if (!found)
1004 gExports.push_back(exportName);
1005 gExportNames[exportName] = dir->GetName();
1006}
1007
1008void XmlServer::Export(TFolder* folder, const char* exportName)
1009{
1010 if (gVerbose)
1011 printf("Export TFolder %p named [%s] of type [%s] as [%s]\n", folder, folder->GetName(), folder->IsA()->GetName(), exportName);
1012
1013 bool found = false;
1014 for (unsigned int i=0; i<gExports.size(); i++)
1015 {
1016 const char* ename = gExports[i].c_str();
1017 if (strcmp(ename, exportName) == 0)
1018 found = true;
1019 }
1020
1021 if (!found)
1022 gExports.push_back(exportName);
1023 gExportNames[exportName] = folder->GetName();
1024}
1025
1026void XmlServer::Export(TCollection* collection, const char* exportName)
1027{
1028 if (gVerbose)
1029 printf("Export TCollection %p named [%s] of type [%s] as [%s]\n", collection, collection->GetName(), collection->IsA()->GetName(), exportName);
1030
1031 bool found = false;
1032 for (unsigned int i=0; i<gExports.size(); i++)
1033 {
1034 const char* ename = gExports[i].c_str();
1035 if (strcmp(ename, exportName) == 0)
1036 found = true;
1037 }
1038
1039 if (!found)
1040 gExports.push_back(exportName);
1041 gExportNames[exportName] = collection->GetName();
1042}
1043
1044void XmlServer::Start(int port)
1045{
1046 if (port==0)
1047 return;
1048
1049 //printf("Here!\n");
1050
1051 static int pport = port;
1052#if 1
1053 TThread *thread = new TThread("XmlServer", xsocket_listener, &pport);
1054 thread->Run();
1055#else
1056 LPDWORD lpThreadId = 0;
1057 CloseHandle(CreateThread(NULL, 1024, &xroot_socket_server, &pport, 0, lpThreadId));
1058#endif
1059}
1060
1061/* emacs
1062 * Local Variables:
1063 * tab-width: 8
1064 * c-basic-offset: 3
1065 * indent-tabs-mode: nil
1066 * End:
1067 */
virtual TList * GetList() const
virtual TList * GetListOfKeys() const
void Export(TDirectory *dir, const char *exportName)
void SetVerbose(bool verbose)
void Start(int port)
static bool gVerbose
static std::deque< std::string > gExports
static std::map< std::string, std::string > gExportNames
static void ResetObject(TObject *obj)
static std::string HtmlDecode(const char *s)
std::string MakeHtmlEntry(const TObject *obj, const char *path)
std::string MakeXmlEntry(const TObject *obj)
static std::deque< std::string > gExports
Definition xmlServer.cxx:77
#define THREADRETURN
Definition xmlServer.cxx:21
static std::string HtmlTag(const char *tag, const char *contents)
#define THREADTYPE
Definition xmlServer.cxx:22
static bool gVerbose
Definition xmlServer.cxx:75
static std::map< std::string, std::string > gExportNames
Definition xmlServer.cxx:78
static TObject * FollowPath(TObject *container, char *path)
static std::string UrlEncode(const char *s)
static TObject * FindTopLevelObject(const char *name)
static void SendString(TSocket *sock, const char *str)
static THREADTYPE xsocket_listener(void *arg)
static TObject * TopLevel(char *path, char **opath)
static void SendHttpReply(TSocket *sock, const char *mimetype, const char *message)
static std::string HtmlEncode(const char *s)
Definition xmlServer.cxx:82
static THREADTYPE xroot_server_thread(void *arg)
static int atohex(int a)
static void SendFile(TSocket *sock, const char *filename, const char *mimetype)