XRootD
XrdXmlRdrTiny.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X m l R d r T i n y . c c */
4 /* */
5 /* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <cctype>
31 #include <cstdlib>
32 #include <cstring>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <iostream>
37 
38 #include "XrdSys/XrdSysE2T.hh"
39 #include "tinyxml.h"
40 #include "XrdXml/XrdXmlRdrTiny.hh"
41 
42 /******************************************************************************/
43 /* L o c a l D e f i n i t i o n s */
44 /******************************************************************************/
45 
46 namespace
47 {
48 // Develop a sane enum structure of xml node types
49 //
50 enum XmlNodeType {ntNone = TiXmlNode::TINYXML_UNKNOWN,
51  ntElmBeg = TiXmlNode::TINYXML_ELEMENT,
52  ntElmEnd = -1,
53  ntText = TiXmlNode::TINYXML_TEXT,
54  ntCmt = TiXmlNode::TINYXML_COMMENT,
55  ntDoc = TiXmlNode::TINYXML_DOCUMENT,
56  ntXMLDcl = TiXmlNode::TINYXML_DECLARATION
57  };
58 
59 /******************************************************************************/
60 /* X m l N o d e N a m e */
61 /******************************************************************************/
62 
63 const char *NodeName(int ntype)
64 {
65  switch(ntype)
66  {case ntNone: return "isNode "; break;
67  case ntElmBeg: return "isElmBeg"; break;
68  case ntText: return "isText "; break;
69  case ntCmt: return "isCmt "; break;
70  case ntDoc: return "isDoc "; break;
71  case ntElmEnd: return "isElmEnd"; break;
72  case ntXMLDcl: return "isXMLDcl"; break;
73  default: break;
74  };
75  return "???";
76 }
77 }
78 
79 /******************************************************************************/
80 /* C o n s t r c u t o r # 1 */
81 /******************************************************************************/
82 
83 XrdXmlRdrTiny::XrdXmlRdrTiny(bool &aOK, const char *fname, const char *enc) : reader(0) // make sure the pointer is nil initialized otherwise if stat fails the destructor segfaults
84 {
85  struct stat Stat;
86  const char *etext;
87 
88 // Initialize the standard values
89 //
90  curNode = 0;
91  curElem = 0;
92  elmNode = 0;
93  eCode = 0;
94  *eText = 0;
95  debug = getenv("XrdXmlDEBUG") != 0;
96 
97 // Make sure this file exists
98 //
99  if (stat(fname, &Stat))
100  {eCode = errno;
101  snprintf(eText,sizeof(eText),"%s opening %s", XrdSysE2T(errno), fname);
102  aOK = false;
103  return;
104  }
105 
106 // Get a file reader
107 //
108  reader = new TiXmlDocument(fname);
109  if (reader->LoadFile())
110  {curNode = (TiXmlNode *)reader;
111  curElem = 0;
112  elmNode = curNode;
113  aOK = true;
114  } else {
115  if (!(etext = reader->ErrorDesc()) || *etext)
116  {if ((eCode = errno)) etext = XrdSysE2T(errno);
117  else etext = "Unknown error";
118  }
119  snprintf(eText,sizeof(eText),"%s opening %s", etext, fname);
120  eCode = EINVAL;
121  aOK = false;
122  }
123 }
124 
125 /******************************************************************************/
126 /* D e s t r u c t o r */
127 /******************************************************************************/
128 
130 {
131 
132 // Tear down the reader
133 //
134  if (reader)
135  {
136  delete reader;
137  reader = 0;
138  }
139 }
140 
141 /******************************************************************************/
142 /* Private: D e b u g */
143 /******************************************************************************/
144 
145 void XrdXmlRdrTiny::Debug(const char *hdr, const char *want, const char *have,
146  const char *scope, int nType)
147 {
148  char buff[512];
149 
150 // Format the message
151 //
152  snprintf(buff,sizeof(buff),"%s %s scope: %s want: %s have: %s\n",
153  hdr,NodeName(nType),scope,want,have);
154  std::cerr <<buff <<std::flush;
155 }
156 
157 /******************************************************************************/
158 /* G e t A t t r i b u t e s */
159 /******************************************************************************/
160 
161 bool XrdXmlRdrTiny::GetAttributes(const char **aname, char **aval)
162 {
163  const char *value;
164  int i = 0;
165  bool found = false;
166 
167 // If we are not at the begining of an element, this is a sequence error
168 //
169  if (!curElem)
170  {snprintf(eText, sizeof(eText),
171  "Element not fetched when seeking attribute %s",aname[0]);
172  eCode = EILSEQ;
173  return false;
174  }
175 
176 // Find all the requested attributes
177 //
178  while(aname[i])
179  {if ((value = curElem->Attribute(aname[i])))
180  {if (aval[i]) free(aval[i]);
181  aval[i] = strdup(value);
182  found = true;
183  }
184  i++;
185  }
186 
187 // All done
188 //
189  return found;
190 }
191 
192 /******************************************************************************/
193 /* G e t E l e m e n t */
194 /******************************************************************************/
195 
196 int XrdXmlRdrTiny::GetElement(const char **ename, bool reqd)
197 {
198  TiXmlNode *theChild;
199  const char *name = (curNode ? curNode->Value() : 0);
200  int i;
201 
202 // If we are positioned either at the current node or the last node we returned
203 // Complain if that is not the case.
204 //
205  if (*ename[0])
206  {if (name && strcmp(name, ename[0]))
207  {if (curElem && !strcmp(elmNode->Value(),ename[0])) curNode = elmNode;
208  else {snprintf(eText, sizeof(eText),
209  "Current context '%s' does not match stated scope '%s'",
210  (name ? name : ""), ename[0]);
211  eCode = EILSEQ;
212  return false;
213  }
214  }
215  }
216 
217 // Sequence to the next node at appropriate level.
218 //
219  if (curNode == elmNode ) theChild = curNode->FirstChild();
220  else if (elmNode) theChild = elmNode->NextSibling();
221  else theChild = curNode->NextSibling();
222 
223 
224 // Scan over to the first wanted element
225 //
226  while(theChild)
227  {if ((name = theChild->Value()) && theChild->Type() == ntElmBeg)
228  {i = 1;
229  while(ename[i] && strcmp(name, ename[i])) i++;
230  if (ename[i])
231  {if (debug) Debug("getelem:",ename[i],name,ename[0],ntElmBeg);
232  curElem = theChild->ToElement();
233  elmNode = theChild;
234  return i;
235  }
236  }
237  theChild = theChild->NextSibling();
238  }
239 
240 // We didn't find any wanted tag here in this scope. Transition to the element's
241 // parent we finished the tag
242 //
243  if (debug) Debug("getelem:",ename[1],ename[0],ename[0],ntElmEnd);
244  elmNode = curNode;
245  curNode = curNode->Parent();
246  curElem = 0;
247  return 0;
248 
249 // This is an error if this element was required
250 //
251  if (reqd)
252  {snprintf(eText,sizeof(eText),"Required element '%s' not found in '%s'",
253  (ename[1] ? ename[1] : "???"), ename[0]);
254  eCode = ESRCH;
255  }
256  return 0;
257 }
258 
259 /******************************************************************************/
260 /* G e t T e x t */
261 /******************************************************************************/
262 
263 char *XrdXmlRdrTiny::GetText(const char *ename, bool reqd)
264 {
265  const char *value;
266  char *sP;
267 
268 // If we are not at the begining of an element, this is a sequence error
269 //
270  if (!curElem)
271  {snprintf(eText, sizeof(eText),
272  "Illegal position seeking text for tag %s",ename);
273  eCode = EILSEQ;
274  return 0;
275  }
276 
277 // Get the text associated with element (simple text only)
278 //
279  value = curElem->GetText();
280 
281 // We did not find a value. If not required return.
282 //
283  if (value || !reqd)
284  {if (!value) return 0;
285  sP = strdup(value);
286  return sP;
287  }
288 
289 // Create error message
290 //
291  snprintf(eText, sizeof(eText), "Required %s tag value not found", ename);
292  eCode = ENOMSG;
293  return 0;
294 }
295 
296 /******************************************************************************/
297 /* I n i t */
298 /******************************************************************************/
299 
300 bool XrdXmlRdrTiny::Init() {return true;}
struct stat Stat
Definition: XrdCks.cc:49
int stat(const char *path, struct stat *buf)
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
XrdXmlRdrTiny(bool &aOK, const char *fname, const char *enc=0)
Constructor & Destructor.
virtual bool GetAttributes(const char **aname, char **aval)
virtual int GetElement(const char **ename, bool reqd=false)
virtual char * GetText(const char *ename, bool reqd=false)
static bool Init()
virtual ~XrdXmlRdrTiny()