~ubuntu-branches/ubuntu/hardy/steam/hardy

« back to all changes in this revision

Viewing changes to server/classes/DocXSL.pike

  • Committer: Bazaar Package Importer
  • Author(s): Alain Schroeder
  • Date: 2006-11-21 16:03:12 UTC
  • mfrom: (2.1.4 feisty)
  • Revision ID: james.westby@ubuntu.com-20061121160312-nf96y6nihzsyd2uv
Tags: 2.2.31-3
Add patch to prevent inconsistent data after shutdown.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2004  Thomas Bopp, Thorsten Hampel, Ludger Merkens
 
1
/* Copyright (C) 2000-2006  Thomas Bopp, Thorsten Hampel, Ludger Merkens
2
2
 *
3
3
 *  This program is free software; you can redistribute it and/or modify
4
4
 *  it under the terms of the GNU General Public License as published by
14
14
 *  along with this program; if not, write to the Free Software
15
15
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 * 
17
 
 * $Id: DocXSL.pike,v 1.5 2005/03/29 12:32:55 astra Exp $
 
17
 * $Id: DocXSL.pike,v 1.19 2006/10/09 15:05:21 exodusd Exp $
18
18
 */
19
19
 
20
 
constant cvs_version="$Id: DocXSL.pike,v 1.5 2005/03/29 12:32:55 astra Exp $";
 
20
constant cvs_version="$Id: DocXSL.pike,v 1.19 2006/10/09 15:05:21 exodusd Exp $";
21
21
 
22
22
 
23
23
//! This class keep XSL Stylesheets and is able to do XSLT with libxslt
33
33
#include <classes.h>
34
34
#include <events.h>
35
35
#include <exception.h>
 
36
#include <access.h>
36
37
 
37
38
//#define DOCXSL_DEBUG
38
39
 
39
40
#ifdef DOCXSL_DEBUG
40
 
#define DEBUG_DOCXSL(s) werror(s+"\n")
 
41
#define DEBUG_DOCXSL(s, args...) werror(s+"\n", args)
41
42
#else
42
43
#define DEBUG_DOCXSL
43
44
#endif
44
45
 
45
46
static object              XML;
46
47
static mapping    mXML = ([ ]);
 
48
static mapping mDepend = ([ ]);
47
49
static mapping mLang   = ([ ]);
48
 
static mapping mDepend = ([ ]);
49
50
static bool  xmlIsLoad = false;
50
51
 
 
52
 
51
53
static mapping   mStylesheets = ([ ]); // all stylesheet objects
52
54
static object         oDescriptionXML;
53
 
static mapping               usedTags; // special rxml tags used
54
55
 
55
56
 
56
57
static Thread.Mutex          xmlMutex = Thread.Mutex();
100
101
    inherit Events.Listener;
101
102
 
102
103
    object __obj;
103
 
    
 
104
 
104
105
    void create(object obj, object _this) {
105
106
        ::create(EVENT_UPLOAD, PHASE_NOTIFY, obj, 0);
106
107
        __obj = _this;
107
108
        obj->listen_event(this_object());
108
109
    }
109
110
    void notify(int event, mixed args) {
110
 
        MESSAGE("Update of Stylesheet depend: %s", __obj->describe());
111
111
        if ( zero_type(::get_object()) ) {
112
112
          destruct(this_object());
113
113
          return;
114
114
        }
 
115
        if ( _Server->query_config("xsl_disable_auto_reload") ) {
 
116
            //MESSAGE("XSL: no auto reload (server config) ...");
 
117
            return;
 
118
        }
 
119
 
115
120
        __obj->load_xml_structure(); // reload
116
 
        __obj->inc_stylesheet_changed();
 
121
        __obj->inc_stylesheet_changed(); // refresh xsl
117
122
    }
118
123
    mapping save() {
119
124
        // do not save !
129
134
 */
130
135
static void load_document()
131
136
{
132
 
    MESSAGE("XSL: %s loaded....", describe());
133
 
    usedTags = ([ ]);
134
 
    XML =  _Server->get_module("Converter:XML");
 
137
  MESSAGE("XSL: %s loading ...", describe());
 
138
  XML =  _Server->get_module("Converter:XML");
 
139
  if ( !do_query_attribute(OBJ_VERSIONOF) )
135
140
    load_xml_structure();
136
141
}
137
142
 
138
 
/**
139
 
 * Get a mapping of all tags.
140
 
 *  
141
 
 * @return tag-name: tag-handler mapping
142
 
 */
143
 
mapping get_tags() 
144
 
{
145
 
    return usedTags;
146
 
}
147
 
 
148
143
 
149
144
/**
150
145
 * Add a dependant stylesheet and notify it when the content
151
146
 * of this stylesheet changed.
152
147
 *  
153
148
 * @param object o - the dependant stylesheet
154
 
 * @author <a href="mailto:astra@upb.de">Thomas Bopp</a>) 
155
149
 */
156
150
void add_depend(object o)
157
151
{
163
157
 *  
164
158
 * @param string uri - the uri to locate the stylesheet
165
159
 * @return the stylesheet content or zero.
166
 
 * @author <a href="mailto:astra@upb.de">Thomas Bopp</a>) 
167
160
 */
168
161
static string|int
169
162
find_stylesheet(string uri, string language)
178
171
        obj = _FILEPATH->path_to_object(uri);
179
172
        if ( objectp(obj) ) {
180
173
          obj->add_depend(this());
181
 
          string contstr = obj->get_content(language);
 
174
          string contstr = obj->get_language_content(language);
182
175
          return contstr;
183
176
        }
184
177
        FATAL("Failed to find Stylesheet: "+ uri +" !");
195
188
 
196
189
    if ( objectp(obj) ) {
197
190
        obj->add_depend(this());
198
 
        return obj->get_content(language);
 
191
        return obj->get_language_content(language);
199
192
    }
200
193
    return 0;
201
194
}
232
225
    obj->add_depend(this());
233
226
 
234
227
    DEBUG_DOCXSL("read_stylesheet(language="+language+")");
235
 
    string contstr = obj->get_content(language);
 
228
    string contstr = obj->get_language_content(language);
236
229
    DEBUG_DOCXSL("length="+strlen(contstr) + " of " + obj->get_object_id());
237
230
    return contstr;
238
231
  }
247
240
 
248
241
static void clean_xsls()
249
242
{
250
 
  foreach(values(mStylesheets), object stylesheet)
251
 
    destruct(stylesheet);
 
243
    foreach(values(mStylesheets), object stylesheet)
 
244
        destruct(stylesheet);
252
245
  
253
 
  mStylesheets = ([ ]);
254
 
  foreach( indices(mDepend), object o ) {
255
 
    if ( objectp(o) )
256
 
      o->inc_stylesheet_changed();
257
 
  }
 
246
    mStylesheets = ([ ]);
 
247
    foreach( indices(mDepend), object o ) {
 
248
        if ( objectp(o) )
 
249
            o->inc_stylesheet_changed();
 
250
    }
258
251
}
259
252
 
260
253
void inc_stylesheet_changed()
282
275
      switch ( prefix ) {
283
276
      case "group":
284
277
        return MODULE_GROUPS->lookup(val);
 
278
      case "instance":
285
279
      case "orb":
286
280
          object oOrb = _FILEPATH->path_to_object(val);
287
281
          if (objectp(oOrb) && oOrb->get_object_class() & CLASS_DOCLPC &&
366
360
    case "container":
367
361
        return XML->containerXML;
368
362
        break;
 
363
    case "properties":
 
364
      return 0;
369
365
    }
 
366
    FATAL("Warning: Default map of " + data + " not found in %s", 
 
367
          get_identifier());
370
368
    return 0;
371
369
}
372
370
 
391
389
    }
392
390
    else if ( n->name == "var" ) {
393
391
      object datanode = n->get_node("def");
394
 
      if ( sizeof(datanode->sibling) ) {
395
 
        FATAL("datanode with sibling found:" +
396
 
              datanode->sibling[0]->data+"\n");
 
392
      if ( sizeof(datanode->children) ) {
 
393
        FATAL("datanode with children found:" +
 
394
              datanode->children[0]->data+"\n");
397
395
        return unserialize_var(
398
396
            n->get_node("name")->data, 
399
 
            unserialize(datanode->sibling[0]));
 
397
            unserialize(datanode->children[0]));
400
398
      }
401
399
      else
402
400
        return unserialize_var(
414
412
    }
415
413
    else if ( n->name == "maps" ) {
416
414
        mapping res = ([ ]);
417
 
        foreach(n->sibling, NodeXML sibling) {
418
 
          mapping m = get_default_map(sibling->data);
 
415
        foreach(n->children, NodeXML children) {
 
416
          mapping m = get_default_map(children->data);
419
417
          res |= m;
420
418
        }
421
419
        return res;
523
521
    return ::compose(m);
524
522
}
525
523
 
 
524
object find_xml(void|object xml)
 
525
{
 
526
  string name;
 
527
  if ( objectp(xml) )
 
528
    return xml;
 
529
  
 
530
  if ( objectp(oEnvironment) ) {
 
531
    xml = oEnvironment->get_object_byname(get_identifier()+".xml");
 
532
    sscanf(get_identifier(), "%s.%*s", name);
 
533
    
 
534
    if ( !objectp(xml) ) {
 
535
      xml = oEnvironment->get_object_byname(name+".xgl");
 
536
    }
 
537
  }
 
538
  if ( !objectp(xml) )
 
539
    xml = do_query_attribute(DOC_XSL_XML);
 
540
 
 
541
  // fall back to public Stylesheet, if available
 
542
  if ( !objectp(xml) || xml->status() < 0 || xml->status() == PSTAT_DELETED ) {
 
543
    xml = OBJ("/stylesheets/public.xsl.xml");
 
544
  }
 
545
  return xml;
 
546
}
 
547
 
 
548
array load_imports(object n)
 
549
{
 
550
  array nodes;
 
551
  if ( objectp(n) )
 
552
    nodes = n->get_nodes("language");
 
553
  
 
554
  if ( arrayp(nodes) ) 
 
555
  {
 
556
    foreach(nodes, object node) {
 
557
      array(object) imports = ({ });
 
558
      
 
559
      if ( stringp(node->attributes->auto) ) {
 
560
        object languageCont = OBJ("/languages");
 
561
        if ( objectp(languageCont) ) {
 
562
          array(object) languageNodes = ({ });
 
563
          foreach( languageCont->get_inventory_by_class(CLASS_DOCXML), object langXML) 
 
564
          {
 
565
            NodeXML langnode = xmlCache.parse(langXML);
 
566
            imports += langnode->get_nodes("import");
 
567
            languageNodes += ({ langnode });
 
568
          }
 
569
          node->replace_node( languageNodes );
 
570
        }
 
571
      }
 
572
      else 
 
573
        imports = node->get_nodes("import");
 
574
          
 
575
      foreach(imports, object imp) {
 
576
        mixed e = catch {
 
577
          object import_obj = parse_import(imp->attributes->file);
 
578
          if ( !objectp(import_obj) ) continue;
 
579
          imp->replace_node(import_obj,
 
580
                            imp->attributes->xpath);
 
581
        };
 
582
        if ( e ) {
 
583
          if ( !stringp(imp->attributes->file) ) 
 
584
            FATAL("Importing language: "+
 
585
                  "Missing file attribute on %s tag !",
 
586
                  imp->get_name());
 
587
          else
 
588
            FATAL("Failed to import file: %s, %O\n%O", 
 
589
                  imp->attributes->file, e[0], e[1]);
 
590
        }
 
591
      }
 
592
    }
 
593
  }
 
594
  return nodes;
 
595
}
 
596
 
 
597
static int in_backtrace(object obj)
 
598
{
 
599
  if ( !objectp(obj) || !functionp(obj->get_object) || 
 
600
       !objectp(obj->get_object()) )
 
601
    return 0;
 
602
 
 
603
  foreach( backtrace(), mixed preceed ) {
 
604
    if ( function_object(preceed[2]) == obj->get_object() )
 
605
      return 1;
 
606
  }
 
607
  return 0;
 
608
}
 
609
 
526
610
/**
527
 
 *
 
611
 * Load the related xgl (or xsl.xml) document
528
612
 *  
529
 
 * @param 
530
 
 * @return 
531
 
 * @author <a href="mailto:astra@upb.de">Thomas Bopp</a>) 
532
 
 * @see 
533
613
 */
534
 
void load_xml_structure()
 
614
void load_xml_structure(void|object xml)
535
615
{
 
616
  if ( in_backtrace(get_module("tar")) ) {
 
617
    call(load_xml_structure, 1);
 
618
    return;
 
619
  }
 
620
 
 
621
  if ( do_query_attribute(OBJ_VERSIONOF) || this()->status() < 0 || this()->status() == PSTAT_DELETED )
 
622
    return; // do not load xml for old versions
 
623
 
536
624
    // factories must be loaded
537
625
  if ( !objectp(get_factory(CLASS_OBJECT)) ) {
538
626
    call(load_xml_structure,  1);
539
627
    return;
540
628
  }
541
 
  object xmlLock = xmlMutex->lock();
 
629
 
 
630
  object xmlLock = xmlMutex->trylock();
 
631
  if ( !objectp(xmlLock) )
 
632
    steam_error("Failed to obtain xml-lock in %O", get_identifier());
 
633
  
542
634
  mixed xmlErr = catch {
543
 
    if ( objectp(oEnvironment) ) {
544
 
      object xml = oEnvironment->get_object_byname(get_identifier()+".xml");
545
 
      if ( !objectp(xml) ) {
546
 
        string name;
547
 
        sscanf(get_identifier(), "%s.%*s", name);
548
 
        xml = oEnvironment->get_object_byname(name+".xgl");
549
 
      }
550
 
      if ( !objectp(xml) ) {
551
 
        // load anything
552
 
        xml = OBJ("/stylesheets/public.xsl.xml");
553
 
      }
554
 
      if ( objectp(xml) ) {
555
 
        usedTags = ([ ]);
556
 
        MESSAGE("Loading XML of " + xml->get_identifier());
557
 
        if ( !objectp(mUpdates[xml]) ) 
558
 
          mUpdates[xml] = UpdateListener(xml, this());
559
 
        
560
 
        mixed err = catch {
561
 
          NodeXML n = parse_data(xml->get_content());
562
 
          array nodes = n->get_nodes("language");
563
 
          
564
 
          if ( arrayp(nodes) ) {
565
 
            foreach(nodes, object node) {
566
 
              array(object) imports = node->get_nodes("import");
567
 
              foreach(imports, object imp) {
568
 
                mixed e = catch {
569
 
                  
570
 
                  imp->replace_node(read_import(imp->attributes->file),
571
 
                                    imp->attributes->xpath);
572
 
                };
573
 
                if ( e ) {
574
 
                  FATAL("Failed to import file: %s, %O", 
575
 
                        imp->attributes->file, e);
576
 
                }
577
 
              }
578
 
            }
579
 
            mLang = read_languages(n->get_nodes("language"));
580
 
          }
581
 
          else {
582
 
            MESSAGE("No imports found, no languages for %s!", 
583
 
                    get_identifier());
584
 
            mLang = ([ ]);
585
 
          }
586
 
          
587
 
          if ( !objectp(n) )
588
 
            throw( ({ "Root node '<structure>' not found in "+
589
 
                      "XML description file !", backtrace() }) );
590
 
          if ( n->name == "structure" ) {
591
 
            mXML = xmlTags(n);
592
 
            if ( (stringp(n->attributes->generate) && 
593
 
                  n->attributes->generate == "pike") ||
594
 
                 stringp(n->get_pi()["steam"]) )
595
 
              hook_xml(xml->get_content());
596
 
          }
597
 
          else
598
 
            mXML = xmlMap(n);
599
 
          
600
 
        };
601
 
        if ( err != 0 ) {
602
 
          FATAL("Error while generating xml map ["
603
 
                +_FILEPATH->object_to_filename(xml)+"]:\n"+err[0]+
604
 
                sprintf("%O",err[1]));
605
 
          if ( CALLER != this_object() ) {
606
 
            destruct(xmlLock);
607
 
            throw(err);
608
 
          }
609
 
        }
610
 
        else {
611
 
          clean_xsls();
612
 
        }
613
 
      }
614
 
      else {
615
 
        if ( CALLER != this_object() ) {
616
 
          destruct(xmlLock);
617
 
          THROW("No description file ("+get_identifier()
618
 
                +".xml) found for Stylesheet !", E_ERROR);
619
 
        }
 
635
    xml = find_xml(xml);
 
636
    if ( objectp(xml) ) {
 
637
      if ( !objectp(mUpdates[xml]) ) 
 
638
          mUpdates[xml] = UpdateListener(xml, this());
 
639
      
 
640
      NodeXML n = parse_data(xml->get_content());
 
641
      array nodes = load_imports(n);
 
642
      mLang = read_languages(nodes);
 
643
      
 
644
      object xmlscript = do_query_attribute(DOC_XSL_PIKE);
 
645
 
 
646
      if ( !objectp(n) ) {
 
647
        throw( ({ "Root node '<structure>' not found in "+
 
648
                    "XML description file !", backtrace() }) );
 
649
      }
 
650
      if ( n->name == "structure" ) {
 
651
        if ( (stringp(n->attributes->generate) && 
 
652
              n->attributes->generate == "pike") ||
 
653
             stringp(n->get_pi()["steam"]) ) 
 
654
        {
 
655
          hook_xml(xml, n);
 
656
        }
 
657
        else {
 
658
          if ( objectp(xmlscript) )
 
659
            xmlscript->delete();
 
660
          do_set_attribute(DOC_XSL_PIKE);
 
661
          mXML = xmlTags(n);
 
662
        }
 
663
      }
 
664
    }
 
665
    else {
 
666
      if ( CALLER != this_object() ) {
 
667
        destruct(xmlLock);
 
668
        FATAL("No description file ("+get_identifier()+".xml) found for Stylesheet !");
 
669
        return;
620
670
      }
621
671
    }
622
672
  };
 
673
  
 
674
  xmlIsLoad = true;
623
675
  if ( xmlErr ) {
624
 
    FATAL("Failed to load xml structure for " + get_identifier() + "\n"+
625
 
          sprintf("%O\n", xmlErr));
 
676
    FATAL("Failed to load xml structure for %s\n%O",
 
677
          _FILEPATH->object_to_filename(this_object()),
 
678
          xmlErr);
 
679
    clean_xsls();
 
680
    if ( CALLER != this_object() ) {
 
681
      destruct(xmlLock);
 
682
      throw(xmlErr);
 
683
    }
626
684
  }
627
 
    
628
 
  xmlIsLoad = true;
629
685
  destruct(xmlLock);
630
686
}
631
687
 
632
688
static string read_import(string fname)
633
689
{
634
690
  object f = _FILEPATH->path_to_object(fname);
635
 
  if ( !objectp(f) )
 
691
  if ( !objectp(f) ) 
636
692
    return 0;
 
693
 
637
694
  if ( !objectp(mUpdates[f]) )
638
695
      mUpdates[f] = UpdateListener(f, this());
639
696
  return f->get_content();
640
697
}
641
698
 
642
 
static object hook_xml(string xml)
 
699
static object parse_import(string fname)
 
700
{
 
701
  object f = _FILEPATH->path_to_object(fname);
 
702
  if ( !objectp(f) ) 
 
703
    return 0;
 
704
 
 
705
  if ( !objectp(mUpdates[f]) )
 
706
      mUpdates[f] = UpdateListener(f, this());
 
707
  return xmlCache.parse(f);
 
708
}
 
709
 
 
710
int check_xgl_consistency(object xmlscript, object xmlObj)
 
711
{
 
712
  if ( objectp(xmlscript) ) {
 
713
    object script_xml = xmlscript->query_attribute(DOCLPC_XGL);
 
714
    object xgl = do_query_attribute(DOC_XSL_XML);
 
715
    if ( objectp(script_xml) && xgl != script_xml )
 
716
    {
 
717
      FATAL("DocXSL: mismatched Pike-Script and XGL File !\n%s(%O): %s(%O)",
 
718
            (objectp(script_xml)?script_xml->get_identifier(): "null"),
 
719
            script_xml,
 
720
            (objectp(xgl)?xgl->get_identifier():"null"),
 
721
            xgl);
 
722
      do_set_attribute(DOC_XSL_XML);
 
723
      xmlObj->set_attribute(DOC_LAST_MODIFIED, time());
 
724
      return 0;
 
725
    }
 
726
  }
 
727
  return 1;
 
728
}
 
729
 
 
730
 
 
731
static void hook_xml(object xmlObj, void|object rootNode)
643
732
{
644
733
  object xmlscript = do_query_attribute(DOC_XSL_PIKE);
645
 
  
646
 
  string pikecode = XMLCodegen.codegen(xml, read_import);
 
734
 
 
735
  check_xgl_consistency(xmlscript, xmlObj);
 
736
  if ( xmlObj == OBJ("/stylesheets/public.xsl.xml") ) {
 
737
    object oxgl = do_query_attribute(DOC_XSL_XML);
 
738
  }
 
739
  
 
740
  // check for update
 
741
  int tss = 0;
 
742
  if (objectp(xmlscript))
 
743
      tss = xmlscript->query_attribute(DOCLPC_INSTANCETIME);
 
744
  int tsc = xmlObj->query_attribute(DOC_LAST_MODIFIED);
 
745
 
 
746
  DEBUG_DOCXSL("Timestamp test when hooking XML: (tss=%d, tsc=%d)", tss, tsc);
 
747
  // also see if XGL file has not changed !
 
748
  if ( tss > tsc && do_query_attribute(DOC_XSL_XML) == xmlObj )
 
749
    return;
 
750
 
 
751
  string pikecode = XMLCodegen.codegen(xmlObj, read_import);
 
752
  set_attribute(DOC_XSL_XML, xmlObj);
 
753
  
 
754
  DEBUG_DOCXSL("Updating Pike XML Generation ...");
 
755
  string scriptname = get_object_id() + ".pike";
647
756
  if ( !objectp(xmlscript) )
648
 
    xmlscript = get_factory(CLASS_DOCUMENT)->execute(([ "name": "xml.pike",]));
 
757
    xmlscript = get_factory(CLASS_DOCUMENT)->execute(([ "name": scriptname,]));
649
758
 
650
759
  mixed err;
651
760
  do_set_attribute(DOC_XSL_PIKE, xmlscript);
 
761
  xmlscript->set_attribute(DOCLPC_XGL, xmlObj);
 
762
  
 
763
  if ( !check_xgl_consistency(xmlscript, xmlObj) )
 
764
    steam_error("DocXSL: consistency check failed .... !");
 
765
 
652
766
  err = catch(xmlscript->set_content(pikecode));
 
767
  if ( arrayp(xmlscript->get_errors()) && sizeof(xmlscript->get_errors()) > 0 ) {
 
768
    FATAL("Errors in xml Script: %O", xmlscript->get_errors());
 
769
  }
 
770
  catch(xmlscript->sanction_object(GROUP("everyone"),SANCTION_READ|SANCTION_EXECUTE));
653
771
  if ( err ) 
654
772
    FATAL("Failed to hook xml content: %s", err[0]);
655
773
  xmlscript->provide_instance(); // should create an instance when loaded
656
 
  
657
774
}
658
775
 
659
776
/**
691
808
        if ( m->attributes->name )
692
809
            res["name"] = m->attributes->name;
693
810
        
694
 
        foreach(m->sibling, object tag) {
 
811
        foreach(m->children, object tag) {
695
812
            if ( tag->name == "tag" ) {
696
813
                res[tag->attributes->name] += xmlTag(tag);
697
814
            }
698
815
            else if ( tag->name == "def" ) {
699
 
                res += get_default_map(tag->data);
 
816
                mapping def = get_default_map(tag->data);
 
817
                if ( mappingp(def) ) {
 
818
                    res += def;             
 
819
                }
700
820
            }
701
821
        }
702
822
        return res;
714
834
    else {
715
835
        obj = unserialize_myobject(o->data);
716
836
    }
717
 
 
 
837
        
718
838
    
719
839
    mixed err = catch {
720
 
      func = [function]obj->find_function(na->data);
 
840
        if ( !objectp(na) ) 
 
841
          steam_user_error("Missing 'n' Node inside <f> to specify function!");
 
842
        func = [function]obj->find_function(na->data);
721
843
    };
722
844
    if ( err != 0 ) {
723
845
        FATAL("Failed to deserialize function in: " + f->dump() + 
724
 
            " inside " + master()->describe_object(obj) + "\n"+
725
 
            err[0] + "\n" + sprintf("%O", err[1]));
 
846
            " inside %s\n%s", _FILEPATH->object_to_filename(this()), err[0]);
726
847
        return 0;
727
848
    }
728
849
    return func;
741
862
    if ( fname == "query_attribute" ) {
742
863
      for ( int i = sizeof(params) - 1; i >= 0; i-- ) {
743
864
        if ( stringp(mAttrConv[params[i]]) ) {
744
 
          MESSAGE("Warning: old integer Syntax used for Attribute: "+
745
 
                  params[i] + "("+mAttrConv[params[i]] + ")");
746
865
                params[i] = mAttrConv[params[i]];
747
866
            }
748
867
        }
805
924
private static mapping xmlTags(NodeXML n) 
806
925
{
807
926
    mapping res = ([ ]);
808
 
    foreach(n->sibling, object node) {
 
927
    foreach(n->children, object node) {
809
928
        if ( node->name == "class" ) {
810
929
            int t;
811
930
            string type = node->attributes->type;
828
947
              res[t][tag->attributes->name] = xmlTag(tag);
829
948
            }
830
949
        }
831
 
        else if ( node->name == "tags" ) {
832
 
            foreach(node->get_nodes("tag"), object tag) {
833
 
                usedTags[tag->attributes->name] = find_object(tag->get_data());
834
 
            }
835
 
        }
836
950
    }
837
951
    if ( n->attributes->name )
838
952
        res["name"] = n->attributes->name;
840
954
    return res;
841
955
}
842
956
 
843
 
static mapping read_languages(array(NodeXML) nodes)
 
957
static mapping read_languages(array(NodeXML) nodes, void|object xml)
844
958
{
845
959
  mapping res = ([ ]);
846
960
 
858
972
  return res;
859
973
}
860
974
 
861
 
string serialize_xml()
862
 
{
863
 
    object factory = _Server->get_factory(CLASS_DOCUMENT);
864
 
 
865
 
    object o;
866
 
    o = oEnvironment->get_object_byname(get_identifier()+"xml");
867
 
    if ( !objectp(o) )
868
 
        o = factory->execute((["name":get_identifier()+".xml",]));
869
 
    string xml = compose(mXML);
870
 
    o->set_content(xml);
871
 
    o->move(oEnvironment);
872
 
    return xml;
873
 
}
874
 
 
875
975
static void 
876
976
content_finished()
877
977
{
878
978
    // successfull upload...
879
979
    ::content_finished();
880
980
    clean_xsls();
881
 
 
882
 
 
883
 
 
884
981
}
885
982
 
886
983
/**
893
990
 * @return the stylesheet.
894
991
 */
895
992
 
896
 
string get_content(void|string language)
 
993
string get_language_content(void|string language)
897
994
{
898
995
  string content;
899
996
  if ( stringp(language) ) {
900
997
    string str = ::get_content();
901
 
    
 
998
 
902
999
    if ( mappingp(mLang[language]) ) {
903
 
      mapping m = copy_value(mLang[language]);
 
1000
      mapping m = mLang[language];
904
1001
      content = replace(str, indices(m), values(m));
905
1002
    }
906
1003
    else if ( mappingp(mLang->english) ) {
907
1004
      content = replace(str, indices(mLang->english),values(mLang->english));
908
1005
    }
909
1006
    else {
910
 
      FATAL("No Languages initialized for %s", get_identifier());
 
1007
      //FATAL("No Languages initialized for %s", get_identifier());
911
1008
      return str;
912
1009
    }
913
1010
    return content;
916
1013
    return ::get_content();
917
1014
}
918
1015
 
919
 
string __term(string lang, string term)
920
 
{
921
 
  return mLang[lang]["{"+term+"}"];
922
 
}
923
1016
 
924
1017
/**
925
1018
 * Get the xslt.Stylesheet() object.
944
1037
      object stylesheet;
945
1038
      err = catch {
946
1039
        
947
 
        string xsl_code = get_content(language);
 
1040
        string xsl_code = get_language_content(language);
 
1041
        xsl_code = replace( xsl_code, "&nbsp;", "&#160;" );
 
1042
    
948
1043
        stylesheet = xslt.Stylesheet();
949
1044
        mStylesheets[language] = stylesheet;
950
1045
 
987
1082
    return "utf-8";
988
1083
}
989
1084
 
990
 
/**
991
 
 *
992
 
 *  
993
 
 * @param 
994
 
 * @return 
995
 
 * @author <a href="mailto:astra@upb.de">Thomas Bopp</a>) 
996
 
 * @see 
997
 
 */
998
1085
array(string) get_styles() 
999
1086
1000
1087
    return ({ "content", "attributes", "access", "annotations" });
1002
1089
 
1003
1090
bool   check_swap() { return false; } // do not swap out stylesheets
1004
1091
int get_object_class() { return ::get_object_class() | CLASS_DOCXSL; }
1005
 
 
 
1092
string get_class() { return "DocXSL"; }
 
1093
 
 
1094
 
 
1095
void test()
 
1096
{
 
1097
  // check xsl.xml here...
 
1098
  MESSAGE("* Testing DocXSL functionality and libxslt ...");
 
1099
  MESSAGE("Creating test container...");
 
1100
  object testcont = OBJ("/home/steam/__xsltestcont");
 
1101
  if ( !objectp(testcont) ) {
 
1102
    testcont=get_factory(CLASS_CONTAINER)->execute( (["name":"__xsltestcont"]) );
 
1103
    testcont->move(OBJ("/home/steam"));
 
1104
  } else {
 
1105
    foreach(testcont->get_inventory(), object inv) {
 
1106
      inv->delete();
 
1107
    }
 
1108
  }
 
1109
  move(testcont);
 
1110
  
 
1111
  MESSAGE("Creating language file...");
 
1112
  object languages = get_factory(CLASS_DOCUMENT)->execute( (["name":"terms.xml",]) );
 
1113
  MESSAGE("Language file is %O", languages);
 
1114
  languages->set_content("<?xml version='1.0' encoding='utf-8'?>\n<language><term name='TERM1'>term_1</term></language>\n");
 
1115
  languages->move(testcont);
 
1116
 
 
1117
  string pathname = _FILEPATH->object_to_filename(languages);
 
1118
 
 
1119
  MESSAGE("Creating XGL File...");
 
1120
  object xgl = get_factory(CLASS_DOCUMENT)->execute( (["name": "test.xgl", ]) );
 
1121
  xgl->set_content("<?xml version='1.0' encoding='utf-8'?>\n<structure generate='pike'>\n<class type='Object'>\n<tag name='test'><call><function name='get_identifier' /></call><show><function name='show' /></show></tag></class><language name='english'><import file='"+pathname+"' xpath='term' /></language>\n</structure>\n");
 
1122
  
 
1123
  xgl->move(testcont);
 
1124
  MESSAGE("Testing xsl...");
 
1125
  set_content("<?xml version='1.0' encoding='utf-8'?>\n<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>\n<xsl:output method='html' encoding='utf-8' />\n<xsl:template match='Object/test'>{TERM1}: testing</xsl:template>\n</xsl:stylesheet>");
 
1126
  load_xml_structure(xgl);
 
1127
  
 
1128
  object pikescript = do_query_attribute(DOC_XSL_PIKE);
 
1129
  if ( !objectp(pikescript) )
 
1130
    steam_error("Generation of Pike-Script failed !");
 
1131
 
 
1132
  MESSAGE("Looking for UpdateListener ...");
 
1133
  if ( !objectp(mUpdates[xgl]) )
 
1134
    steam_error("No Update Listener for XGL ...");
 
1135
  if ( !objectp(mUpdates[languages]) ) {
 
1136
    MESSAGE("Dumping Update Listeners:\n%O", indices(mUpdates));
 
1137
    steam_error("No Update Listener for Language Term File (%O) ...", languages);
 
1138
  }
 
1139
  call(test_more, 1, pikescript, xgl, languages, testcont, "", 0);
 
1140
}
 
1141
 
 
1142
void test_more(object pikescript, object xgl, object languages, object testcont, string xml, int test)
 
1143
{
 
1144
  if ( pikescript->status() != PSTAT_DISK ) {
 
1145
    pikescript->drop();
 
1146
    call(test_more, 5, pikescript, xgl, languages, testcont, xml, test);
 
1147
    return;
 
1148
  }
 
1149
  switch(test) {
 
1150
  case 0:
 
1151
    MESSAGE("Testing xml generation !");
 
1152
    mapping params = ([ "this_user": USER("root")->get_object_id(), ]);
 
1153
    xml = get_module("Converter:XML")->get_xml(this(), this(), params);
 
1154
    // xgl file controls xml generatoin - should be simple xml
 
1155
    MESSAGE("XML Generated: \n%s---", xml);
 
1156
    if ( search(xml, "XGL File: "+_FILEPATH->object_to_filename(xgl)) == -1 )
 
1157
      steam_error("XGL Test: Used wrong xgl file for XML Generation !");
 
1158
    string result = get_module("libxslt")->run(xml, this(), ([ ]));
 
1159
    MESSAGE("OUTPUT = %s", result);
 
1160
    call(test_more, 2, pikescript, xgl, languages, testcont, xml, 1);
 
1161
    break;
 
1162
  default:
 
1163
    MESSAGE("Testing update of depend...");
 
1164
    languages->set_content("<?xml version='1.0' encoding='utf-8'?>\n<language><term name='TERM1'>modified</term></language>\n");
 
1165
    result = get_module("libxslt")->run(xml, this(), ([ ]));
 
1166
    if ( search(result, "modified") == -1 )
 
1167
      steam_error("Language File Update did not update Term Definition in %O !"+
 
1168
                  "\nDump: %s", languages, result);
 
1169
    languages->delete();
 
1170
    testcont->delete();
 
1171
    xgl->delete();
 
1172
    delete();
 
1173
    MESSAGE("* DocXSL.test() all tests finished successfully !");
 
1174
  }
 
1175
}