ROOT logo
// $Id$
// Author: Sergey Linev   22/12/2013

#ifndef ROOT_TRootSniffer
#define ROOT_TRootSniffer

#ifndef ROOT_TNamed
#include "TNamed.h"
#endif

#ifndef ROOT_TList
#include "TList.h"
#endif

class TFolder;
class TMemFile;
class TBufferFile;
class TDataMember;
class THttpCallArg;
class TRootSnifferStore;
class TRootSniffer;

class TRootSnifferScanRec {

friend class TRootSniffer;

protected:
   // different bits used to scan hierarchy
   enum {
      kScan         = 0x0001,  ///< normal scan of hierarchy
      kExpand       = 0x0002,  ///< expand of specified item - allowed to scan object members
      kSearch       = 0x0004,  ///< search for specified item (only objects and collections)
      kCheckChilds  = 0x0008,  ///< check if there childs, very similar to search
      kOnlyFields   = 0x0010,  ///< if set, only fields for specified item will be set (but all fields)
      kActions      = 0x001F   ///< mask for actions, only actions copied to child rec
   };


   TRootSnifferScanRec *fParent;      //! pointer on parent record
   UInt_t               fMask;        //! defines operation kind
   const char          *fSearchPath;  //! current path searched
   Int_t                fLevel;       //! current level of hierarchy
   TString              fItemName;    //! name of current item
   TList                fItemsNames;  //! list of created items names, need to avoid duplication
   Int_t                fRestriction; //! restriction 0 - default, 1 - read-only, 2 - full access

   TRootSnifferStore   *fStore;       //! object to store results
   Bool_t               fHasMore;     //! indicates that potentially there are more items can be found
   Bool_t               fNodeStarted; //! indicate if node was started
   Int_t                fNumFields;   //! number of fields
   Int_t                fNumChilds;   //! number of childs

public:

   TRootSnifferScanRec();
   virtual ~TRootSnifferScanRec();

   void CloseNode();

   /** return true when fields could be set to the hierarchy item */
   Bool_t CanSetFields() const
   {
      return (fMask & kScan) && (fStore != 0);
   }

   Bool_t ScanOnlyFields() const
   {
      return (fMask & kOnlyFields) && (fMask & kScan);
   }

   /** Starts new node, must be closed at the end */
   void CreateNode(const char *_node_name);

   void BeforeNextChild();

   /** Set item field only when creating is specified */
   void SetField(const char *name, const char *value, Bool_t with_quotes = kTRUE);

   /** Mark item with ROOT class and correspondent streamer info */
   void SetRootClass(TClass *cl);

   /** Returns true when item can be expanded */
   Bool_t CanExpandItem();

   /** Checks if result will be accepted. Used to verify if sniffer should read object from the file */
   Bool_t IsReadyForResult() const;

   /** Obsolete, use SetFoundResult instead */
   Bool_t SetResult(void *obj, TClass *cl, TDataMember *member = 0);

   /** Set found element with class and datamember (optional) */
   Bool_t SetFoundResult(void *obj, TClass *cl, TDataMember *member = 0);

   /** Returns depth of hierarchy */
   Int_t Depth() const;

   /** Method indicates that scanning can be interrupted while result is set */
   Bool_t Done() const;

   /** Construct item name, using object name as basis */
   void MakeItemName(const char *objname, TString &itemname);

   /** Produces full name for the current item */
   void BuildFullName(TString& buf, TRootSnifferScanRec* prnt = 0);

   /** Returns read-only flag for current item */
   Bool_t IsReadOnly(Bool_t dflt = kTRUE);

   Bool_t GoInside(TRootSnifferScanRec &super, TObject *obj, const char *obj_name = 0, TRootSniffer* sniffer = 0);

   ClassDef(TRootSnifferScanRec, 0) // Scan record for objects sniffer
};

//_______________________________________________________________________

class TRootSniffer : public TNamed {
   enum {
      kItemField = BIT(21)  // item property stored as TNamed
   };
protected:
   TString        fObjectsPath;     //! default path for registered objects
   TMemFile      *fMemFile;         //! file used to manage streamer infos
   TList         *fSinfo;           //! last produced streamer info
   Bool_t         fReadOnly;        //! indicate if sniffer allowed to change ROOT structures - for instance, read objects from files
   Bool_t         fScanGlobalDir;   //! when enabled (default), scan gROOT for histograms, canvases, open files
   THttpCallArg  *fCurrentArg;      //! current http arguments (if any)
   Int_t          fCurrentRestrict; //! current restriction for last-found object
   TString        fCurrentAllowedMethods;  //! list of allowed methods, extracted when analyzed object restrictions
   TList          fRestrictions;    //! list of restrictions for different locations
   TString        fAutoLoad;        //! scripts names, which are add as _autoload parameter to h.json request

   void ScanObjectMembers(TRootSnifferScanRec &rec, TClass *cl, char *ptr);

   virtual void ScanObjectProperties(TRootSnifferScanRec &rec, TObject *obj);

   virtual void ScanObjectChilds(TRootSnifferScanRec &rec, TObject *obj);

   void ScanCollection(TRootSnifferScanRec &rec, TCollection *lst,
                       const char *foldername = 0, TCollection *keys_lst = 0);

   /* Method is used to scan ROOT objects.
    * Can be reimplemented to extend scanning */
   virtual void ScanRoot(TRootSnifferScanRec &rec);

   void CreateMemFile();

   TString DecodeUrlOptionValue(const char *value, Bool_t remove_quotes = kTRUE);

   TObject *GetItem(const char *fullname, TFolder *&parent, Bool_t force = kFALSE, Bool_t within_objects = kTRUE);

   TFolder *GetSubFolder(const char *foldername, Bool_t force = kFALSE);

   const char *GetItemField(TFolder *parent, TObject *item, const char *name);

   Bool_t IsItemField(TObject* obj) const;

   Bool_t AccessField(TFolder *parent, TObject *item,
                      const char *name, const char *value, TNamed **only_get = 0);

   Int_t WithCurrentUserName(const char* option);

public:

   TRootSniffer(const char *name, const char *objpath = "Objects");
   virtual ~TRootSniffer();

   static Bool_t IsDrawableClass(TClass *cl);

   void  SetReadOnly(Bool_t on = kTRUE)
   {
      // When readonly on (default), sniffer is not allowed to change ROOT structures
      // For instance, it is not allowed to read new objects from files

      fReadOnly = on;
   }

   Bool_t IsReadOnly() const
   {
      // Returns readonly mode

      return fReadOnly;
   }

   void Restrict(const char* path, const char* options);

   Bool_t HasRestriction(const char* item_name);

   Int_t CheckRestriction(const char* item_name);

   void SetScanGlobalDir(Bool_t on = kTRUE)
   {
      // When enabled (default), sniffer scans gROOT for files, canvases, histograms

      fScanGlobalDir = on;
   }

   void SetAutoLoad(const char* scripts = "");

   const char* GetAutoLoad() const;

   Bool_t IsScanGlobalDir() const { return fScanGlobalDir; }

   Bool_t RegisterObject(const char *subfolder, TObject *obj);

   Bool_t UnregisterObject(TObject *obj);

   Bool_t RegisterCommand(const char *cmdname, const char *method, const char *icon);

   Bool_t CreateItem(const char *fullname, const char *title);

   Bool_t SetItemField(const char *fullname, const char *name, const char *value);

   const char *GetItemField(const char *fullname, const char *name);

   void SetCurrentCallArg(THttpCallArg* arg);

   /** Method scans normal objects, registered in ROOT */
   void ScanHierarchy(const char *topname, const char *path,
                      TRootSnifferStore *store, Bool_t only_fields = kFALSE);

   TObject *FindTObjectInHierarchy(const char *path);

   virtual void *FindInHierarchy(const char *path, TClass **cl = 0, TDataMember **member = 0, Int_t *chld = 0);

   Bool_t CanDrawItem(const char *path);

   Bool_t CanExploreItem(const char *path);

   Bool_t IsStreamerInfoItem(const char *itemname);

   ULong_t GetStreamerInfoHash();

   ULong_t GetItemHash(const char *itemname);

   Bool_t ProduceJson(const char *path, const char *options, TString &res);

   Bool_t ProduceXml(const char *path, const char *options, TString &res);

   Bool_t ProduceBinary(const char *path, const char *options, void *&ptr, Long_t &length);

   Bool_t ProduceImage(Int_t kind, const char *path, const char *options, void *&ptr, Long_t &length);

   Bool_t ProduceExe(const char *path, const char *options, Int_t reskind, TString *ret_str, void **ret_ptr = 0, Long_t *ret_length = 0);

   Bool_t ExecuteCmd(const char *path, const char *options, TString &res);

   Bool_t ProduceItem(const char *path, const char *options, TString &res, Bool_t asjson = kTRUE);

   Bool_t ProduceMulti(const char *path, const char *options, void *&ptr, Long_t &length, TString &str, Bool_t asjson = kTRUE);

   Bool_t Produce(const char *path, const char *file, const char *options, void *&ptr, Long_t &length, TString &str);

   ClassDef(TRootSniffer, 0) // Sniffer of ROOT objects
};

#endif
 TRootSniffer.h:1
 TRootSniffer.h:2
 TRootSniffer.h:3
 TRootSniffer.h:4
 TRootSniffer.h:5
 TRootSniffer.h:6
 TRootSniffer.h:7
 TRootSniffer.h:8
 TRootSniffer.h:9
 TRootSniffer.h:10
 TRootSniffer.h:11
 TRootSniffer.h:12
 TRootSniffer.h:13
 TRootSniffer.h:14
 TRootSniffer.h:15
 TRootSniffer.h:16
 TRootSniffer.h:17
 TRootSniffer.h:18
 TRootSniffer.h:19
 TRootSniffer.h:20
 TRootSniffer.h:21
 TRootSniffer.h:22
 TRootSniffer.h:23
 TRootSniffer.h:24
 TRootSniffer.h:25
 TRootSniffer.h:26
 TRootSniffer.h:27
 TRootSniffer.h:28
 TRootSniffer.h:29
 TRootSniffer.h:30
 TRootSniffer.h:31
 TRootSniffer.h:32
 TRootSniffer.h:33
 TRootSniffer.h:34
 TRootSniffer.h:35
 TRootSniffer.h:36
 TRootSniffer.h:37
 TRootSniffer.h:38
 TRootSniffer.h:39
 TRootSniffer.h:40
 TRootSniffer.h:41
 TRootSniffer.h:42
 TRootSniffer.h:43
 TRootSniffer.h:44
 TRootSniffer.h:45
 TRootSniffer.h:46
 TRootSniffer.h:47
 TRootSniffer.h:48
 TRootSniffer.h:49
 TRootSniffer.h:50
 TRootSniffer.h:51
 TRootSniffer.h:52
 TRootSniffer.h:53
 TRootSniffer.h:54
 TRootSniffer.h:55
 TRootSniffer.h:56
 TRootSniffer.h:57
 TRootSniffer.h:58
 TRootSniffer.h:59
 TRootSniffer.h:60
 TRootSniffer.h:61
 TRootSniffer.h:62
 TRootSniffer.h:63
 TRootSniffer.h:64
 TRootSniffer.h:65
 TRootSniffer.h:66
 TRootSniffer.h:67
 TRootSniffer.h:68
 TRootSniffer.h:69
 TRootSniffer.h:70
 TRootSniffer.h:71
 TRootSniffer.h:72
 TRootSniffer.h:73
 TRootSniffer.h:74
 TRootSniffer.h:75
 TRootSniffer.h:76
 TRootSniffer.h:77
 TRootSniffer.h:78
 TRootSniffer.h:79
 TRootSniffer.h:80
 TRootSniffer.h:81
 TRootSniffer.h:82
 TRootSniffer.h:83
 TRootSniffer.h:84
 TRootSniffer.h:85
 TRootSniffer.h:86
 TRootSniffer.h:87
 TRootSniffer.h:88
 TRootSniffer.h:89
 TRootSniffer.h:90
 TRootSniffer.h:91
 TRootSniffer.h:92
 TRootSniffer.h:93
 TRootSniffer.h:94
 TRootSniffer.h:95
 TRootSniffer.h:96
 TRootSniffer.h:97
 TRootSniffer.h:98
 TRootSniffer.h:99
 TRootSniffer.h:100
 TRootSniffer.h:101
 TRootSniffer.h:102
 TRootSniffer.h:103
 TRootSniffer.h:104
 TRootSniffer.h:105
 TRootSniffer.h:106
 TRootSniffer.h:107
 TRootSniffer.h:108
 TRootSniffer.h:109
 TRootSniffer.h:110
 TRootSniffer.h:111
 TRootSniffer.h:112
 TRootSniffer.h:113
 TRootSniffer.h:114
 TRootSniffer.h:115
 TRootSniffer.h:116
 TRootSniffer.h:117
 TRootSniffer.h:118
 TRootSniffer.h:119
 TRootSniffer.h:120
 TRootSniffer.h:121
 TRootSniffer.h:122
 TRootSniffer.h:123
 TRootSniffer.h:124
 TRootSniffer.h:125
 TRootSniffer.h:126
 TRootSniffer.h:127
 TRootSniffer.h:128
 TRootSniffer.h:129
 TRootSniffer.h:130
 TRootSniffer.h:131
 TRootSniffer.h:132
 TRootSniffer.h:133
 TRootSniffer.h:134
 TRootSniffer.h:135
 TRootSniffer.h:136
 TRootSniffer.h:137
 TRootSniffer.h:138
 TRootSniffer.h:139
 TRootSniffer.h:140
 TRootSniffer.h:141
 TRootSniffer.h:142
 TRootSniffer.h:143
 TRootSniffer.h:144
 TRootSniffer.h:145
 TRootSniffer.h:146
 TRootSniffer.h:147
 TRootSniffer.h:148
 TRootSniffer.h:149
 TRootSniffer.h:150
 TRootSniffer.h:151
 TRootSniffer.h:152
 TRootSniffer.h:153
 TRootSniffer.h:154
 TRootSniffer.h:155
 TRootSniffer.h:156
 TRootSniffer.h:157
 TRootSniffer.h:158
 TRootSniffer.h:159
 TRootSniffer.h:160
 TRootSniffer.h:161
 TRootSniffer.h:162
 TRootSniffer.h:163
 TRootSniffer.h:164
 TRootSniffer.h:165
 TRootSniffer.h:166
 TRootSniffer.h:167
 TRootSniffer.h:168
 TRootSniffer.h:169
 TRootSniffer.h:170
 TRootSniffer.h:171
 TRootSniffer.h:172
 TRootSniffer.h:173
 TRootSniffer.h:174
 TRootSniffer.h:175
 TRootSniffer.h:176
 TRootSniffer.h:177
 TRootSniffer.h:178
 TRootSniffer.h:179
 TRootSniffer.h:180
 TRootSniffer.h:181
 TRootSniffer.h:182
 TRootSniffer.h:183
 TRootSniffer.h:184
 TRootSniffer.h:185
 TRootSniffer.h:186
 TRootSniffer.h:187
 TRootSniffer.h:188
 TRootSniffer.h:189
 TRootSniffer.h:190
 TRootSniffer.h:191
 TRootSniffer.h:192
 TRootSniffer.h:193
 TRootSniffer.h:194
 TRootSniffer.h:195
 TRootSniffer.h:196
 TRootSniffer.h:197
 TRootSniffer.h:198
 TRootSniffer.h:199
 TRootSniffer.h:200
 TRootSniffer.h:201
 TRootSniffer.h:202
 TRootSniffer.h:203
 TRootSniffer.h:204
 TRootSniffer.h:205
 TRootSniffer.h:206
 TRootSniffer.h:207
 TRootSniffer.h:208
 TRootSniffer.h:209
 TRootSniffer.h:210
 TRootSniffer.h:211
 TRootSniffer.h:212
 TRootSniffer.h:213
 TRootSniffer.h:214
 TRootSniffer.h:215
 TRootSniffer.h:216
 TRootSniffer.h:217
 TRootSniffer.h:218
 TRootSniffer.h:219
 TRootSniffer.h:220
 TRootSniffer.h:221
 TRootSniffer.h:222
 TRootSniffer.h:223
 TRootSniffer.h:224
 TRootSniffer.h:225
 TRootSniffer.h:226
 TRootSniffer.h:227
 TRootSniffer.h:228
 TRootSniffer.h:229
 TRootSniffer.h:230
 TRootSniffer.h:231
 TRootSniffer.h:232
 TRootSniffer.h:233
 TRootSniffer.h:234
 TRootSniffer.h:235
 TRootSniffer.h:236
 TRootSniffer.h:237
 TRootSniffer.h:238
 TRootSniffer.h:239
 TRootSniffer.h:240
 TRootSniffer.h:241
 TRootSniffer.h:242
 TRootSniffer.h:243
 TRootSniffer.h:244
 TRootSniffer.h:245
 TRootSniffer.h:246
 TRootSniffer.h:247
 TRootSniffer.h:248
 TRootSniffer.h:249
 TRootSniffer.h:250
 TRootSniffer.h:251
 TRootSniffer.h:252
 TRootSniffer.h:253
 TRootSniffer.h:254
 TRootSniffer.h:255
 TRootSniffer.h:256