aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/vespa/storageframework/generic/status/xmlstatusreporter.h
blob: eff5a44148ecf6237d330645b83cfa8aa4a437f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
 * \class storage::framework::XmlStatusReporter
 * \ingroup component
 *
 * \brief Specialization of StatusReporter for reporters of XML data.
 *
 * To make it easy to write legal XML and escape content that needs to be
 * escaped, an XML writer is used to write the actual XML data.
 *
 * Note: If you want to write XML from a status reporter that can also write
 * other types of content, best practise is to implement StatusReporter, and if
 * serving XML in the reportStatus function, create a temporary
 * XmlStatusReporter object, in order to reuse the report functions to init
 * and finalize XML writing.
 */

#pragma once

#include "statusreporter.h"
#include <vespa/vespalib/util/xmlstream.h>

namespace storage::framework {

struct XmlStatusReporter : public StatusReporter {
    XmlStatusReporter(vespalib::stringref id, vespalib::stringref name);
    virtual ~XmlStatusReporter();

    virtual void initXmlReport(vespalib::xml::XmlOutputStream&,
                               const HttpUrlPath&) const;

    /**
     * @return Empty string if ok, otherwise indicate a failure condition.
     */
    virtual vespalib::string reportXmlStatus(vespalib::xml::XmlOutputStream&,
                                             const HttpUrlPath&) const = 0;

    virtual void finalizeXmlReport(vespalib::xml::XmlOutputStream&,
                                   const HttpUrlPath&) const;

    // Implementation of status reporter interface
    vespalib::string getReportContentType(const HttpUrlPath&) const override;
    bool reportStatus(std::ostream&, const HttpUrlPath&) const override;
};

/**
 * If you're only reporting XML in some cases, you can use this instance to
 * wrap the actual XML parts, so you can reuse the code that outputs the XML.
 * Just use output operator in this class to add the actual XML.
 */
class PartlyXmlStatusReporter : public XmlStatusReporter {
    vespalib::XmlOutputStream _xos;
    const HttpUrlPath& _path;

public:
    PartlyXmlStatusReporter(const StatusReporter& main, std::ostream& out,
                            const HttpUrlPath& path)
        : XmlStatusReporter(main.getId(), main.getName()),
          _xos(out),
          _path(path)
    {
        initXmlReport(_xos, path);
    }

    ~PartlyXmlStatusReporter() {
        finalizeXmlReport(_xos, _path);
    }

    vespalib::XmlOutputStream& getStream() { return _xos; }
    vespalib::string reportXmlStatus(vespalib::xml::XmlOutputStream&, const HttpUrlPath&) const override { return ""; }

    template<typename T>
    PartlyXmlStatusReporter& operator<<(const T& v) {
        _xos << v;
        return *this;
    }
};

}