1 #include "xercesc/framework/LocalFileFormatTarget.hpp" 
    2 #include "xercesc/framework/MemBufInputSource.hpp" 
    3 #include "xercesc/sax/SAXParseException.hpp" 
    4 #include "xercesc/sax/EntityResolver.hpp" 
    5 #include "xercesc/sax/InputSource.hpp" 
    6 #include "xercesc/parsers/XercesDOMParser.hpp" 
    7 #include "xercesc/util/PlatformUtils.hpp" 
    8 #include "xercesc/util/XercesDefs.hpp" 
    9 #include "xercesc/util/XMLUni.hpp" 
   10 #include "xercesc/util/XMLURL.hpp" 
   11 #include "xercesc/util/XMLString.hpp" 
   12 #include "xercesc/dom/DOM.hpp" 
   23 #include <sys/types.h> 
   25 #include "uuid/uuid.h" 
   27 #include <boost/format.hpp> 
   29 using namespace xercesc;
 
   30 using namespace Gaudi;
 
   33 #if _XERCES_VERSION <= 30000 
   35 #define setIdAttribute(a, b) setIdAttribute(a) 
   43   typedef const string& 
CSTR;
 
   44   inline string _toString(
const XMLCh *toTranscode)  {
 
   45     char * buff = XMLString::transcode(toTranscode);
 
   46     string tmp(buff==0 ? 
"" : buff);
 
   47     XMLString::release(&buff);
 
   52       try { XMLPlatformUtils::Initialize();      }
 
   53       catch (
const XMLException& e)   {
 
   54         cout << 
"Xerces-c error in initialization:" << _toString(e.getMessage()) << endl;
 
   58       XMLPlatformUtils::Terminate();
 
   65     XMLStr(CSTR 
c)                { m_xml=XMLString::transcode(c.c_str());  }
 
   66     ~XMLStr()                     { 
if (m_xml) XMLString::release(&m_xml);  }
 
   67     operator const XMLCh*() 
const { 
return m_xml;                           }
 
   69   struct XMLTag : 
public XMLStr {
 
   71     XMLTag(CSTR 
s) : XMLStr(s), m_str(s) {  }
 
   73     operator CSTR ()
 const  { 
return m_str; }
 
   76   bool operator==(CSTR 
c, 
const XMLTag& b) {  
return c==b.m_str; }
 
   77   struct XMLCollection  {
 
   79     XMLCollection(DOMNode* 
n, 
bool use_children=
true) : m_node((DOMElement*)n) {
 
   81         if ( m_node ) m_node = (DOMElement*)m_node->getFirstChild();
 
   82         if ( m_node && m_node->getNodeType() != DOMNode::ELEMENT_NODE ) ++(*
this);
 
   85     operator bool()
  const                { 
return 0 != m_node;                         }
 
   86     operator DOMNode* () 
const            { 
return m_node;                              }
 
   87     operator DOMElement* () 
const         { 
return m_node;                              }
 
   88     DOMElement* operator->()
 const        { 
return m_node;                              }
 
   89     string attr(
const XMLTag& tag)
 const  { 
return _toString(m_node->getAttribute(tag));}
 
   90     string attr(CSTR tag)
  const          { 
return attr(XMLTag(tag));                   }
 
   91     string tag()
 const                    { 
return _toString(m_node->getTagName());     }
 
   94         m_node = (DOMElement*)m_node->getNextSibling();
 
   95         if ( m_node && m_node->getNodeType() == DOMNode::ELEMENT_NODE ) {
 
  101   struct ErrHandler : 
public ErrorHandler    {
 
  107     void resetErrors()                          {      }
 
  109     void warning(
const SAXParseException& )    {     }
 
  111     void error(
const SAXParseException& e);
 
  113     void fatalError(
const SAXParseException& e);
 
  114     virtual ~ErrHandler() {}
 
  116   struct DTDRedirect : 
public EntityResolver  {
 
  117     InputSource* resolveEntity(
const XMLCh* 
const , 
const XMLCh* 
const )  {
 
  118       static const char* dtdID = 
"redirectinmem.dtd";
 
  119       static const char* dtd = \
 
  121         <!ELEMENT POOLFILECATALOG (META*,File*)>\ 
  122         <!ELEMENT META EMPTY>\ 
  123         <!ELEMENT File (physical,logical,metadata*)>\ 
  124         <!ATTLIST META name CDATA #REQUIRED>\ 
  125         <!ATTLIST META type CDATA #REQUIRED>\ 
  126         <!ELEMENT physical (pfn)+>\ 
  127         <!ELEMENT logical (lfn)*>\ 
  128         <!ELEMENT metadata EMPTY>\ 
  129         <!ELEMENT lfn EMPTY>\ 
  130         <!ELEMENT pfn EMPTY>\ 
  131         <!ATTLIST File ID ID  #REQUIRED>\ 
  132         <!ATTLIST pfn name ID #REQUIRED>\ 
  133         <!ATTLIST pfn filetype CDATA #IMPLIED>\ 
  134         <!ATTLIST pfn se CDATA #IMPLIED>\ 
  135         <!ATTLIST lfn name ID #REQUIRED>\ 
  136         <!ATTLIST metadata att_name  CDATA #REQUIRED>\ 
  137         <!ATTLIST metadata att_value CDATA #REQUIRED>\ 
  139       static const size_t len = strlen(dtd);
 
  140       return new MemBufInputSource((
const XMLByte*)dtd,len,dtdID,
false);
 
  142     virtual ~DTDRedirect() {}
 
  145   void ErrHandler::error(
const SAXParseException& e)  {
 
  146     string m(_toString(e.getMessage()));
 
  147     if (m.find(
"The values for attribute 'name' must be names or name tokens")!=string::npos ||
 
  148       m.find(
"The values for attribute 'ID' must be names or name tokens")!=string::npos   ||
 
  149       m.find(
"for attribute 'name' must be Name or Nmtoken")!=string::npos                 ||
 
  150       m.find(
"for attribute 'ID' must be Name or Nmtoken")!=string::npos                   ||
 
  151       m.find(
"for attribute 'name' is invalid Name or NMTOKEN value")!=string::npos        ||
 
  152       m.find(
"for attribute 'ID' is invalid Name or NMTOKEN value")!=string::npos      )
 
  154     string sys(_toString(e.getSystemId()));
 
  156     log << 
MSG::ERROR << 
"Error at file \""  << sys
 
  157       << 
"\", line " << e.getLineNumber() << 
", column " << e.getColumnNumber() << 
endmsg 
  158       << 
"Message: " << m << 
endmsg;
 
  160   void ErrHandler::fatalError(
const SAXParseException& e)  {
 
  162     string m(_toString(e.getMessage()));
 
  163     string sys(_toString(e.getSystemId()));
 
  164     log << 
MSG::ERROR << 
"Fatal Error at file \"" << sys
 
  165       << 
"\", line " << e.getLineNumber() << 
", column " << e.getColumnNumber() << 
endmsg 
  166       << 
"Message: " << m << 
endmsg;
 
  167     throw runtime_error( 
"Standard pool exception : Fatal Error on the DOM Parser" );
 
  170   const XMLTag EmptyCatalog(
"<!-- Edited By POOL -->\n" 
  171                               "<!DOCTYPE POOLFILECATALOG SYSTEM \"InMemory\">\n" 
  172                               "<POOLFILECATALOG>\n" 
  173                               "</POOLFILECATALOG>\n");
 
  174   const XMLTag PFNCOLL         (
"physical");
 
  175   const XMLTag LFNCOLL         (
"logical");
 
  176   const XMLTag PFNNODE         ( 
"pfn");
 
  177   const XMLTag LFNNODE         ( 
"lfn");
 
  178   const XMLTag Attr_type       ( 
"type");
 
  179   const XMLTag Attr_ID         ( 
"ID");
 
  180   const XMLTag Attr_name       ( 
"name");
 
  181   const XMLTag Attr_ftype      ( 
"filetype");
 
  182   const XMLTag MetaNode        ( 
"metadata");
 
  183   const XMLTag Attr_metaName   ( 
"att_name");
 
  184   const XMLTag Attr_metaValue  ( 
"att_value");
 
  190   ::uuid_generate_time(uuid);
 
  193     unsigned short Data2;
 
  194     unsigned short Data3;
 
  195     unsigned char  Data4[8];
 
  198   boost::format text(
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X");
 
  199   text % 
g->Data1 % 
g->Data2 % 
g->Data3;
 
  200   for (
int i = 0; 
i < 8; ++
i)
 
  201     text % (
unsigned short)
g->Data4[
i];
 
  206 : m_rdOnly(false),m_update(false),m_doc(0),m_parser(0),m_errHdlr(0),
 
  207   m_file(uri), m_msgSvc(m)
 
  225   if ( !
m_doc && throw_if_no_exists )
 
  226     printError(
"The XML catalog was not started.",
true);
 
  234     throw runtime_error(
"XMLFileCatalog> "+msg);
 
  239   string xmlFile = 
getfile(
false);
 
  243     m_parser->setValidationScheme(XercesDOMParser::Val_Auto);
 
  245     DTDRedirect dtdinmem;
 
  246     m_parser->setEntityResolver(&dtdinmem);
 
  249     if ( !xmlFile.empty() )  {
 
  253       const std::string& 
s = EmptyCatalog;
 
  254       MemBufInputSource src((
const XMLByte*)s.c_str(),s.length(),
"MemCatalog");
 
  259   catch (
const XMLException& e) {
 
  260     printError(
"XML parse error["+xmlFile+
"]: "+_toString(e.getMessage()));
 
  262   catch (
const DOMException& e) {
 
  263     printError(
"XML parse error["+xmlFile+
"]: "+_toString(e.getMessage()));
 
  266     printError(
"UNKNOWN XML parse error in file "+xmlFile);
 
  272   DOMNode* e = 
element(fid,
false);
 
  273   e = e ? e->getParentNode() : 0;    
 
  274   e = e ? e->getParentNode() : 0;    
 
  276     if ( e->getAttributes() ) { 
 
  277       char* nam = XMLString::transcode(((DOMElement*)e)->getAttribute(Attr_ID));
 
  278       if ( nam ) result = nam;
 
  279       XMLString::release(&nam);
 
  287   DOMNode* fde = 
getDoc(
true)->getElementsByTagName(XMLStr(
"*"))->item(0);
 
  288   for(XMLCollection 
c(
child(fde,
"File"), 
false); 
c; ++
c)
 
  289     fids.push_back(
c.attr(Attr_ID));
 
  295     files.push_back(make_pair(
c.attr(Attr_name),
c.attr(Attr_ftype)));
 
  301     files.push_back(make_pair(
c.attr(Attr_name),fid));
 
  307     attr.push_back(make_pair(
c.attr(Attr_metaName),
c.attr(Attr_metaValue)));
 
  308   if ( attr.size() > 0 )
 
  309     attr.push_back(make_pair(
"guid",fid));
 
  313   for(XMLCollection 
c(par); 
c; ++
c ) {
 
  314     if( 
c.tag() == tag )  {
 
  315       if( !attr.empty() && 
c.attr(attr) != val) 
continue;
 
  325     DOMElement* mnod = (DOMElement*)
child(node,MetaNode,Attr_metaName,attr);
 
  327       mnod = 
getDoc(
true)->createElement(MetaNode);
 
  328       node->appendChild(mnod);
 
  329       mnod->setAttribute(Attr_metaName,XMLStr(attr));
 
  331     mnod->setAttribute(Attr_metaValue,XMLStr(val));
 
  335   printError(
"Cannot update readonly catalog!");
 
  339   XMLCollection 
c(
child(
getDoc(
true)->getElementById(XMLStr(fid)),MetaNode,Attr_metaName,attr));
 
  340   return c ? c.attr(attr) : string(
"");
 
  344   vector<DOMNode*> gbc;
 
  345   DOMNode* fn = 
getDoc(
true)->getElementById(XMLStr(fid));
 
  346   for(XMLCollection 
c(
child(fn,MetaNode)); 
c; ++
c)
 
  347     if ( attr[0]==
'*' || !
c.attr(attr).empty() ) gbc.push_back(
c);
 
  348   for(vector<DOMNode*>::iterator 
i=gbc.begin(); 
i != gbc.end(); 
i++)
 
  353   DOMNode* node = 
getDoc(
true)->getElementById(XMLStr(element_name));
 
  354   if ( !node && print_err ) 
printError(
"Cannot find element:"+element_name);
 
  359   DOMNode *pn = 0, *fn = 
element(fid);
 
  360   if ( fn ) pn = fn->getParentNode();
 
  361   if ( pn ) pn->removeChild(fn);
 
  365   if ( !fid.empty() ) {
 
  366     std::pair<DOMElement*, DOMElement*> res = 
i_registerFID(fid);
 
  367     if ( res.first == 0 || res.second == 0 )  {
 
  372   throw runtime_error(
"XMLFileCatalog> Cannot register LFN for invalid FID:"+fid);
 
  378     DOMElement *
file = (DOMElement*)
element(fid,
false), *phyelem = 0, *logelem = 0;
 
  379     DOMDocument* doc = 
getDoc(
true);
 
  381       DOMNode* fde = doc->getElementsByTagName(XMLStr(
"*"))->item(0);
 
  382       file = 
m_doc->createElement(XMLStr(
"File"));
 
  383       file->setAttribute(Attr_ID, XMLStr(fid));
 
  384       file->setIdAttribute(Attr_ID, 
true);
 
  385       fde->appendChild(file);
 
  388     for(XMLCollection c1(file); c1; ++c1 )  {
 
  389       char* nam = XMLString::transcode(c1->getNodeName());
 
  390       if ( nam == PFNCOLL ) phyelem = c1;
 
  391       if ( nam == LFNCOLL ) logelem = c1;
 
  392       XMLString::release(&nam);
 
  395       phyelem = doc->createElement(PFNCOLL);
 
  396       file->appendChild(phyelem);
 
  400       logelem = doc->createElement(LFNCOLL);
 
  401       file->appendChild(logelem);
 
  404     return std::make_pair(logelem,phyelem);
 
  406   printError(
"Cannot update readonly catalog!");
 
  407   return std::pair<DOMElement*, DOMElement*>(0,0);
 
  411   if ( !fid.empty() )  {
 
  413     DOMElement* phyelem = res.second, *fnelem = 0;
 
  414     for(XMLCollection 
c(phyelem); 
c; ++
c )  {
 
  415       char* nam = XMLString::transcode(
c->getNodeName());
 
  416       if ( nam == PFNNODE )  {
 
  417         XMLString::release(&nam);
 
  418         nam = XMLString::transcode(
c->getAttribute(Attr_name));
 
  420           XMLString::release(&nam);
 
  425       XMLString::release(&nam);
 
  428       fnelem = 
getDoc(
true)->createElement(PFNNODE);
 
  429       phyelem->appendChild(fnelem);
 
  430       fnelem->setAttribute(Attr_ftype,XMLStr(ftype));
 
  431       fnelem->setAttribute(Attr_name,XMLStr(pfn));
 
  432       fnelem->setIdAttribute(Attr_name, 
true);
 
  437   throw runtime_error(
"XMLFileCatalog> Cannot register PFN for invalid FID:"+fid);
 
  441   if ( !fid.empty() )  {
 
  442     std::pair<DOMElement*, DOMElement*> res = 
i_registerFID(fid);
 
  443     DOMElement* logelem = res.first, *fnelem = 0;
 
  444     for(XMLCollection 
c(logelem); 
c; ++
c )  {
 
  445       char* nam = XMLString::transcode(
c->getNodeName());
 
  446       if ( nam == LFNNODE )  {
 
  447         XMLString::release(&nam);
 
  448         nam = XMLString::transcode(
c->getAttribute(Attr_name));
 
  450           XMLString::release(&nam);
 
  457       fnelem = 
getDoc(
true)->createElement(LFNNODE);
 
  458       logelem->appendChild(fnelem);
 
  459       fnelem->setAttribute(Attr_name,XMLStr(lfn));
 
  460       fnelem->setIdAttribute(Attr_name, 
true);
 
  465   throw runtime_error(
"XMLFileCatalog> Cannot register LFN for invalid FID:"+fid);
 
  471       string xmlfile = 
getfile(
true);
 
  473       DOMImplementation *imp = DOMImplementationRegistry::getDOMImplementation(ii);
 
  474       XMLFormatTarget   *tar = 
new LocalFileFormatTarget(xmlfile.c_str());
 
  475 #if _XERCES_VERSION <= 30000 
  476       DOMWriter         *wr  = imp->createDOMWriter();
 
  477       wr->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, 
true);
 
  478       wr->writeNode(tar, *
m_doc);
 
  481       DOMLSOutput       *output = imp->createLSOutput();
 
  482       output->setByteStream(tar);
 
  483       DOMLSSerializer   *wr     = imp->createLSSerializer();
 
  484       wr->getDomConfig()->setParameter(XMLStr(
"format-pretty-print"), 
true);
 
  485       wr->write(
m_doc, output);
 
  492   catch ( exception& e )  {
 
  493     printError(
string(
"Cannot open output file:")+e.what());
 
  501   string protocol, 
path;
 
  504     xerurl   = (
const XMLCh*)XMLStr(
m_file);
 
  505     protocol = _toString(xerurl.getProtocolName());
 
  506     path     = _toString(xerurl.getPath());
 
  508   catch (
const XMLException& e ) {
 
  511   if ( protocol.empty() )    {
 
  514   else if ( protocol == 
"http" || protocol == 
"ftp" )  {
 
  517   else if ( protocol == 
"file" ) {
 
  520     int exist = ::stat(path.c_str(),&buff) != -1;
 
  521     if ( create && !exist )  {
 
  523       log << 
MSG::INFO << 
"File '" << path << 
"' does not exist. New file created." << 
endmsg;
 
  524       ofstream out(path.c_str());
 
  526         out << (
CSTR)EmptyCatalog << endl;
 
  536     else if ( !create )  {
 
  541     printError(protocol + 
": protocol not supported.");
 
Definition of the MsgStream class used to transmit messages. 
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)". 
virtual bool readOnly() const 
Check if the catalog is read-only. 
#define DECLARE_FACTORY(type, factory)
xercesc::XercesDOMParser * m_parser
virtual ~XMLFileCatalog()
Destructor,. 
std::string lookupFID(CSTR lfn) const 
Gaudi::PluginService::Factory< IInterface *, const std::string &, IMessageSvc * > Factory
std::string getfile(bool create)
virtual std::string getMetaDataItem(CSTR fid, CSTR name) const 
Access metadata item. 
virtual void dropMetaData(CSTR fid) const 
Drop all metadata of one FID. 
xercesc::DOMNode * element(CSTR fid, bool print_err=true) const 
virtual void setMetaData(CSTR fid, CSTR name, CSTR value) const 
Insert/update metadata item. 
virtual void registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const 
Create a FileID and Node of the physical file name with all the attributes. 
virtual void init()
Parse the DOM tree of the XML catalog. 
virtual bool dirty() const 
Check if the catalog should be updated. 
xercesc::DOMNode * child(xercesc::DOMNode *par, CSTR tag, CSTR attr="", CSTR val="") const 
bool operator==(const GaudiUtils::Allocator< T1 > &, const GaudiUtils::Allocator< T2 > &)
void printError(CSTR msg, bool throw_exc=true) const 
virtual void getFID(Strings &fids) const 
Dump all file Identifiers. 
The IMessage is the interface implemented by the message service. 
xercesc::DOMDocument * m_doc
xercesc::DOMDocument * getDoc(bool throw_if_no_exists=true) const 
virtual void getLFN(CSTR fid, Files &files) const 
Dump all logical file names of the catalog associate to the FileID. 
virtual void deleteFID(CSTR FileID) const 
Delete FileID Node from the catalog. 
GAUDI_API std::string path(const AIDA::IBaseHistogram *aida)
get the path in THS for AIDA histogram 
xercesc::ErrorHandler * m_errHdlr
std::string createGuidAsString()
Create file identifier using UUID mechanism. 
virtual void commit()
Save DOM catalog to file. 
virtual void getPFN(CSTR fid, Files &files) const 
Dump all physical file names of the catalog and their attributes associate to the FileID...
std::pair< xercesc::DOMElement *, xercesc::DOMElement * > i_registerFID(CSTR fid) const 
virtual void getMetaData(CSTR fid, Attributes &attr) const 
Dump all MetaData of the catalog for a given file ID. 
virtual void registerFID(CSTR fid) const 
Create a FileID and Node. 
This is a number of static methods for bootstrapping the Gaudi framework. 
This class constitutes the core of the XML based FileCatalog API for POOL. 
virtual std::string createFID() const 
Catalog interface. 
virtual void registerLFN(CSTR fid, CSTR lfn) const 
Create a FileID and Node of the logical file name with all the attributes. 
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.