diff -r 4ebc2e2fb97c -r 71c04702a3d5 src/hotspot/share/utilities/xmlstream.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/utilities/xmlstream.hpp Tue Sep 12 19:03:39 2017 +0200 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_XMLSTREAM_HPP +#define SHARE_VM_UTILITIES_XMLSTREAM_HPP + +#include "runtime/handles.hpp" +#include "utilities/ostream.hpp" + +class xmlStream; +class defaultStream; + +// Sub-stream for writing quoted text, as opposed to markup. +// Characters written to this stream are subject to quoting, +// as '<' => "<", etc. +class xmlTextStream : public outputStream { + friend class xmlStream; + friend class defaultStream; // tty + private: + + xmlStream* _outer_xmlStream; + + xmlTextStream() { _outer_xmlStream = NULL; } + + public: + virtual void flush(); // _outer.flush(); + virtual void write(const char* str, size_t len); // _outer->write_text() +}; + + +// Output stream for writing XML-structured logs. +// To write markup, use special calls elem, head/tail, etc. +// Use the xmlStream::text() stream to write unmarked text. +// Text written that way will be quoted as necessary using '<', etc. +// Characters written directly to an xmlStream via print_cr, etc., +// are directly written to the encapsulated stream, xmlStream::out(). +// This can be used to produce markup directly, character by character. +// (Such writes are not checked for markup syntax errors.) + +class xmlStream : public outputStream { + friend class defaultStream; // tty + public: + enum MarkupState { BODY, // after end_head() call, in text + HEAD, // after begin_head() call, in attrs + ELEM }; // after begin_elem() call, in attrs + + protected: + outputStream* _out; // file stream by which it goes + julong _last_flush; // last position of flush + MarkupState _markup_state; // where in the elem/head/tail dance + outputStream* _text; // text stream + xmlTextStream _text_init; + + // for subclasses + xmlStream() {} + void initialize(outputStream* out); + + // protect this from public use: + outputStream* out() { return _out; } + + // helpers for writing XML elements + void va_tag(bool push, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0); + virtual void see_tag(const char* tag, bool push) NOT_DEBUG({}); + virtual void pop_tag(const char* tag) NOT_DEBUG({}); + +#ifdef ASSERT + // in debug mode, we verify matching of opening and closing tags + int _element_depth; // number of unfinished elements + char* _element_close_stack_high; // upper limit of down-growing stack + char* _element_close_stack_low; // upper limit of down-growing stack + char* _element_close_stack_ptr; // pointer of down-growing stack +#endif + + public: + // creation + xmlStream(outputStream* out) { initialize(out); } + DEBUG_ONLY(virtual ~xmlStream();) + + bool is_open() { return _out != NULL; } + + // text output + bool inside_attrs() { return _markup_state != BODY; } + + // flushing + virtual void flush(); // flushes out, sets _last_flush = count() + virtual void write(const char* s, size_t len); + void write_text(const char* s, size_t len); // used by xmlTextStream + int unflushed_count() { return (int)(out()->count() - _last_flush); } + + // writing complete XML elements + void elem(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void begin_elem(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void end_elem(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void end_elem(); + void head(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void begin_head(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void end_head(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void end_head(); + void done(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); // xxx_done event, plus tail + void done_raw(const char * kind); + void tail(const char* kind); + + // va_list versions + void va_elem(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); + void va_begin_elem(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); + void va_head(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); + void va_begin_head(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); + void va_done(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); + + // write text (with quoting of special XML characters <>&'" etc.) + outputStream* text() { return _text; } + void text(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + void va_text(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) { + text()->vprint(format, ap); + } + + // commonly used XML attributes + void stamp(); // stamp='1.234' + void method(const methodHandle& m); // method='k n s' ... + void klass(Klass* k); // klass='name' + void name(const Symbol* s); // name='name' + void object(const char* attr, Metadata* val); + void object(const char* attr, Handle val); + + // print the text alone (sans ''): + void method_text(const methodHandle& m); + void klass_text(Klass* k); // klass='name' + void name_text(const Symbol* s); // name='name' + void object_text(Metadata* x); + void object_text(Handle x); + + /* Example uses: + + // Empty element, simple case. + elem("X Y='Z'"); \n + + // Empty element, general case. + begin_elem("X Y='Z'"); + + // Compound element, simple case. + head("X Y='Z'"); \n + ...body... ...body... + tail("X"); \n + + // Compound element, general case. + begin_head("X Y='Z'"); \n + ...body... ...body... + tail("X"); \n + + // Printf-style formatting: + elem("X Y='%s'", "Z"); \n + + */ + +}; + +// Standard log file, null if no logging is happening. +extern xmlStream* xtty; + +// Note: If ::xtty != NULL, ::tty == ::xtty->text(). + +#endif // SHARE_VM_UTILITIES_XMLSTREAM_HPP