summaryrefslogtreecommitdiff
path: root/qpid/cpp/managementgen
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp/managementgen')
-rw-r--r--qpid/cpp/managementgen/CMakeLists.txt26
-rw-r--r--qpid/cpp/managementgen/Makefile.am39
-rwxr-xr-xqpid/cpp/managementgen/qmf-gen100
-rw-r--r--qpid/cpp/managementgen/qmfgen/__init__.py19
-rwxr-xr-xqpid/cpp/managementgen/qmfgen/generate.py494
-rw-r--r--qpid/cpp/managementgen/qmfgen/management-types.xml77
-rwxr-xr-xqpid/cpp/managementgen/qmfgen/schema.py1852
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Args.h40
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/CMakeLists.cmake39
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Class.cpp339
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Class.h122
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Event.cpp101
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Event.h58
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Makefile.mk40
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Package.cpp32
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/Package.h41
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/V2Package.cpp37
-rw-r--r--qpid/cpp/managementgen/qmfgen/templates/V2Package.h46
18 files changed, 3502 insertions, 0 deletions
diff --git a/qpid/cpp/managementgen/CMakeLists.txt b/qpid/cpp/managementgen/CMakeLists.txt
new file mode 100644
index 0000000000..2511b745a3
--- /dev/null
+++ b/qpid/cpp/managementgen/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+project(qpidc-qmfgen)
+cmake_minimum_required(VERSION 2.4.0 FATAL_ERROR)
+
+install(PROGRAMS qmf-gen DESTINATION managementgen
+ COMPONENT ${QPID_COMPONENT_QMF})
+install(DIRECTORY qmfgen DESTINATION managementgen
+ COMPONENT ${QPID_COMPONENT_QMF}
+ PATTERN ".svn" EXCLUDE PATTERN "*.pyc" EXCLUDE)
diff --git a/qpid/cpp/managementgen/Makefile.am b/qpid/cpp/managementgen/Makefile.am
new file mode 100644
index 0000000000..8769200719
--- /dev/null
+++ b/qpid/cpp/managementgen/Makefile.am
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+qmfpythondir = $(pythondir)
+dist_bin_SCRIPTS = \
+ qmf-gen
+pkgpyexec_qmfgendir = $(pyexecdir)/qmfgen
+pkgpyexec_qmfgen_PYTHON = \
+ qmfgen/__init__.py \
+ qmfgen/generate.py \
+ qmfgen/schema.py \
+ qmfgen/templates/Args.h \
+ qmfgen/templates/Class.cpp \
+ qmfgen/templates/Class.h \
+ qmfgen/templates/Event.cpp \
+ qmfgen/templates/Event.h \
+ qmfgen/templates/Makefile.mk \
+ qmfgen/templates/Package.cpp \
+ qmfgen/templates/Package.h \
+ qmfgen/templates/V2Package.cpp \
+ qmfgen/templates/V2Package.h \
+ qmfgen/management-types.xml
+
+EXTRA_DIST = $(nobase_qmfpython_DATA) CMakeLists.txt
diff --git a/qpid/cpp/managementgen/qmf-gen b/qpid/cpp/managementgen/qmf-gen
new file mode 100755
index 0000000000..6e8f864256
--- /dev/null
+++ b/qpid/cpp/managementgen/qmf-gen
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+import sys
+import os
+from qmfgen.schema import SchemaPackage, SchemaClass
+from qmfgen.generate import Generator
+from optparse import OptionParser
+
+dataPath = os.path.dirname(Generator.getModulePath())
+defaultTypeFile = dataPath + "/management-types.xml"
+defaultTemplateDir = dataPath + "/templates"
+
+# Set command line options
+usage = "usage: %prog [options] schema-document..."
+parser = OptionParser(usage=usage)
+parser.add_option("-o", "--outputdir", dest="outputdir", metavar="DIR", default="./",
+ help="Output directory")
+parser.add_option("-c", "--cmakelists", dest="cmakelists", metavar="FILE",
+ help="CMakeLists fragment")
+parser.add_option("-m", "--makefile", dest="makefile", metavar="FILE",
+ help="Makefile fragment")
+parser.add_option("-t", "--typefile", dest="typefile", metavar="FILE", default=defaultTypeFile,
+ help="Override type descriptor file")
+parser.add_option("-d", "--templatedir", dest="templatedir", metavar="DIR", default=defaultTemplateDir,
+ help="Override template directory")
+parser.add_option("-p", "--gen-prefix", dest="genprefix", default="",
+ help="Prefix for generated files in make dependencies")
+parser.add_option("-q", "--qpid-broker", dest="qpidbroker", default=False, action="store_true",
+ help="Generate makefile for Qpid broker")
+parser.add_option("-b", "--broker-plugin", dest="brokerplugin", default=False, action="store_true",
+ help="Generate code for use in a qpid broker plugin")
+parser.add_option("-2", "--v2-style", dest="v2_style", default=False, action="store_true",
+ help="Generate code for use with the QMFv2 Agent API")
+
+(opts, args) = parser.parse_args()
+
+typefile = opts.typefile
+templatedir = opts.templatedir
+outdir = opts.outputdir
+v2_style = opts.v2_style
+gen = Generator(outdir, templatedir)
+
+if len(args) == 0:
+ print "no input files"
+ parser.exit()
+
+vargs = {}
+if opts.brokerplugin:
+ vargs["agentHeaderDir"] = "management"
+ vargs["genQmfV1"] = True
+else:
+ vargs["agentHeaderDir"] = "agent"
+ vargs["genQmfV1"] = None
+
+for schemafile in args:
+ package = SchemaPackage(typefile, schemafile, opts)
+
+ gen.setPackage(package.packageName)
+
+ if v2_style:
+ gen.makeV2PackageFile("V2Package.h", package, vars=vargs)
+ gen.makeV2PackageFile("V2Package.cpp", package, vars=vargs)
+ else:
+ gen.makeClassFiles ("Class.h", package, vars=vargs)
+ gen.makeClassFiles ("Class.cpp", package, vars=vargs)
+ gen.makeMethodFiles ("Args.h", package, vars=vargs)
+ gen.makeEventFiles ("Event.h", package, vars=vargs)
+ gen.makeEventFiles ("Event.cpp", package, vars=vargs)
+ gen.makePackageFile ("Package.h", package, vars=vargs)
+ gen.makePackageFile ("Package.cpp", package, vars=vargs)
+
+if opts.makefile != None:
+ args = {}
+ args["qpidbroker"] = opts.qpidbroker
+ args["genprefix"] = opts.genprefix
+ gen.makeSingleFile("Makefile.mk", opts.makefile, force=True, vars=args)
+
+if opts.cmakelists != None:
+ args = {}
+ args["qpidbroker"] = opts.qpidbroker
+ args["genprefix"] = opts.genprefix
+ gen.makeSingleFile("CMakeLists.cmake", opts.cmakelists, force=True, vars=args)
diff --git a/qpid/cpp/managementgen/qmfgen/__init__.py b/qpid/cpp/managementgen/qmfgen/__init__.py
new file mode 100644
index 0000000000..63a3f41f28
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/__init__.py
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
diff --git a/qpid/cpp/managementgen/qmfgen/generate.py b/qpid/cpp/managementgen/qmfgen/generate.py
new file mode 100755
index 0000000000..4e688e3bc7
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/generate.py
@@ -0,0 +1,494 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from xml.dom.minidom import parse, parseString, Node
+from cStringIO import StringIO
+from stat import *
+from errno import *
+import os
+import os.path
+import filecmp
+import re
+
+class Template:
+ """
+ Expandable File Template - This class is instantiated each time a
+ template is to be expanded. It is instantiated with the "filename"
+ which is the full path to the template file and the "handler" which
+ is an object that is responsible for storing variables (setVariable),
+ checking conditions (testCondition), and expanding tags (substHandler).
+ """
+ def __init__ (self, filename, handler):
+ self.filename = filename
+ self.handler = handler
+ self.handler.initExpansion ()
+ self.writing = 0 # 0 => write output lines; >0 => recursive depth of conditional regions
+
+ def expandLine (self, line, stream, object):
+ cursor = 0
+ while 1:
+ sub = line.find ("/*MGEN:", cursor)
+ if sub == -1:
+ if self.writing == 0:
+ stream.write (line[cursor:len (line)])
+ return
+
+ subend = line.find("*/", sub)
+ if self.writing == 0:
+ stream.write (line[cursor:sub])
+ cursor = subend + 2
+
+ tag = line[sub:subend]
+
+ if tag[7:10] == "IF(":
+ if self.writing == 0:
+ close = tag.find(")")
+ if close == -1:
+ raise ValueError ("Missing ')' on condition")
+ cond = tag[10:close]
+ dotPos = cond.find (".")
+ if dotPos == -1:
+ raise ValueError ("Invalid condition tag: %s" % cond)
+ tagObject = cond[0:dotPos]
+ tagName = cond[dotPos + 1 : len(cond)]
+ if not self.handler.testCondition(object, tagObject, tagName):
+ self.writing += 1
+ else:
+ self.writing += 1
+
+ elif tag[7:12] == "ENDIF":
+ if self.writing > 0:
+ self.writing -= 1
+
+ else:
+ equalPos = tag.find ("=")
+ if equalPos == -1:
+ dotPos = tag.find (".")
+ if dotPos == -1:
+ raise ValueError ("Invalid tag: %s" % tag)
+ tagObject = tag[7:dotPos]
+ tagName = tag[dotPos + 1:len (tag)]
+ if self.writing == 0:
+ self.handler.substHandler (object, stream, tagObject, tagName)
+ else:
+ tagKey = tag[7:equalPos]
+ tagVal = tag[equalPos + 1:len (tag)]
+ if self.writing == 0:
+ self.handler.setVariable (tagKey, tagVal)
+
+ def expand (self, object):
+ fd = open (self.filename)
+ stream = StringIO ()
+
+ for line in fd:
+ self.expandLine (line, stream, object)
+ fd.close ()
+
+ return stream
+
+
+class Makefile:
+ """ Object representing a makefile fragment """
+ def __init__ (self, filelists, templateFiles, packagelist):
+ self.filelists = filelists
+ self.templateFiles = templateFiles
+ self.packagelist = packagelist
+
+ def genGenSources (self, stream, variables):
+ mdir = variables["mgenDir"]
+ sdir = variables["specDir"]
+ stream.write (mdir + "/qmf-gen \\\n")
+ stream.write (" " + mdir + "/qmfgen/generate.py \\\n")
+ stream.write (" " + mdir + "/qmfgen/schema.py \\\n")
+ stream.write (" " + mdir + "/qmfgen/management-types.xml \\\n")
+ stream.write (" " + sdir + "/management-schema.xml \\\n")
+ first = True
+ for template in self.templateFiles:
+ if first:
+ first = False
+ stream.write (" ")
+ else:
+ stream.write (" \\\n ")
+ stream.write (mdir + "/qmfgen/templates/" + template)
+
+ def genGenCppFiles (self, stream, variables):
+ first = True
+ for file in self.filelists["cpp"]:
+ if first:
+ first = False
+ else:
+ stream.write (" \\\n ")
+ stream.write (file)
+
+ def genGenHFiles (self, stream, variables):
+ first = True
+ for file in self.filelists["h"]:
+ if first:
+ first = False
+ else:
+ stream.write (" \\\n ")
+ stream.write (file)
+
+ def genGeneratedFiles(self, stream, variables):
+ first = True
+ extensions = ("h", "cpp")
+ for ext in extensions:
+ for file in self.filelists[ext]:
+ if first:
+ first = False
+ else:
+ stream.write(" \\\n ")
+ if "genprefix" in variables:
+ prefix = variables["genprefix"]
+ if prefix != "":
+ stream.write(prefix + "/")
+ stream.write(file)
+
+ def genHeaderInstalls (self, stream, variables):
+ for package in self.packagelist:
+ name = "_".join(package.split("/"))
+ stream.write(name + "dir = $(includedir)/qmf/" + package + "\n")
+ stream.write("dist_" + name + "_HEADERS = ")
+ first = True
+ for file in self.filelists["h"]:
+ if file.find("qmf/" + package) == 0:
+ if first:
+ first = False
+ else:
+ stream.write (" \\\n ")
+ stream.write(file)
+ stream.write("\n\n")
+
+ def testQpidBroker(self, variables):
+ if "qpidbroker" in variables:
+ return variables["qpidbroker"]
+ return False
+
+class CMakeLists(Makefile):
+ """ Object representing a makefile fragment """
+
+ # Regardless of what normalize() did, switch all the dir separators back
+ # to '/' - cmake expects that regardless of platform.
+ def unNormCase (self, path):
+ return re.sub("\\\\", "/", path)
+
+ def genGenSources (self, stream, variables):
+ mdir = self.unNormCase(variables["mgenDir"])
+ sdir = self.unNormCase(variables["specDir"])
+ stream.write (mdir + "/qmf-gen \n")
+ stream.write (" " + mdir + "/qmfgen/generate.py\n")
+ stream.write (" " + mdir + "/qmfgen/schema.py\n")
+ stream.write (" " + mdir + "/qmfgen/management-types.xml\n")
+ stream.write (" " + sdir + "/management-schema.xml\n")
+ first = True
+ for template in self.templateFiles:
+ if first:
+ first = False
+ stream.write (" ")
+ else:
+ stream.write ("\n ")
+ stream.write (mdir + "/qmfgen/templates/" + template)
+
+ def genGenCppFiles (self, stream, variables):
+ first = True
+ for file in self.filelists["cpp"]:
+ if first:
+ first = False
+ else:
+ stream.write (" \n ")
+ stream.write (self.unNormCase(file))
+
+ def genGenHFiles (self, stream, variables):
+ first = True
+ for file in self.filelists["h"]:
+ if first:
+ first = False
+ else:
+ stream.write (" \n ")
+ stream.write (self.unNormCase(file))
+
+ def genGeneratedFiles(self, stream, variables):
+ first = True
+ extensions = ("h", "cpp")
+ for ext in extensions:
+ for file in self.filelists[ext]:
+ if first:
+ first = False
+ else:
+ stream.write(" \n ")
+ if "genprefix" in variables:
+ prefix = variables["genprefix"]
+ if prefix != "":
+ stream.write(prefix + "/")
+ stream.write(self.unNormCase(file))
+
+ def genHeaderInstalls (self, stream, variables):
+ for package in self.packagelist:
+ stream.write("#Come back to this later...\n")
+ name = "_".join(package.split("/"))
+ stream.write("#" + name + "dir = $(includedir)/qmf/" + package + "\n")
+ stream.write("#dist_" + name + "_HEADERS = ")
+ first = True
+ for file in self.filelists["h"]:
+ file = self.unNormCase(file)
+ if file.find("qmf/" + package) == 0:
+ if first:
+ first = False
+ else:
+ stream.write ("\n ")
+ stream.write("#" + file)
+ stream.write("\n\n")
+
+
+class Generator:
+ """
+ This class manages code generation using template files. It is instantiated
+ once for an entire code generation session.
+ """
+ def createPath (self, path):
+ exists = True
+ try:
+ mode = os.stat (path)[ST_MODE]
+ except OSError, (err,text):
+ if err == ENOENT or err == ESRCH:
+ exists = False
+ else:
+ raise
+ if exists and not S_ISDIR (mode):
+ raise ValueError ("path is not directory: %s" % path)
+ if not exists:
+ pair = os.path.split (path)
+ if pair[0] != '':
+ self.createPath (pair[0])
+ os.mkdir (path)
+
+ def normalize (self, path):
+ newpath = os.path.normcase (os.path.normpath (path))
+ self.createPath (newpath)
+ return newpath + "/"
+
+ def __init__ (self, destDir, templateDir):
+ self.dest = self.normalize (destDir)
+ self.input = self.normalize (templateDir)
+ self.packagePath = self.dest
+ self.filelists = {}
+ self.filelists["h"] = []
+ self.filelists["cpp"] = []
+ self.filelists["mk"] = []
+ self.filelists["cmake"] = []
+ self.packagelist = []
+ self.templateFiles = []
+ self.variables = {}
+
+ def setPackage (self, packageName):
+ path = "/".join(packageName.split("."))
+ self.packagelist.append(path)
+ self.packagePath = self.normalize(self.dest + path)
+
+ def testGenQMFv1 (self, variables):
+ return variables["genQmfV1"]
+
+ def genDisclaimer (self, stream, variables):
+ prefix = variables["commentPrefix"]
+ stream.write (prefix + " This source file was created by a code generator.\n")
+ stream.write (prefix + " Please do not edit.")
+
+ def fileExt (self, path):
+ dot = path.rfind (".")
+ if dot == -1:
+ return ""
+ return path[dot + 1:]
+
+ def writeIfChanged (self, stream, target, force=False):
+ ext = self.fileExt (target)
+ self.filelists[ext].append (target)
+ tempFile = target + ".gen.tmp"
+ fd = open (tempFile, "w")
+ fd.write (stream.getvalue ())
+ fd.close ()
+
+ try:
+ if not force and filecmp.cmp (target, tempFile):
+ os.remove (tempFile)
+ return
+ except:
+ pass
+
+ try:
+ os.remove (target)
+ except:
+ pass
+
+ os.rename (tempFile, target)
+ print "Generated:", target
+
+ def targetPackageFile (self, schema, templateFile):
+ dot = templateFile.find(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:len (templateFile)]
+ path = self.packagePath + "Package" + extension
+ return path
+
+ def targetV2PackageFile (self, schema, templateFile):
+ dot = templateFile.find(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:len (templateFile)]
+ path = self.packagePath + "QmfPackage" + extension
+ return path
+
+ def targetClassFile (self, _class, templateFile):
+ dot = templateFile.find(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:len (templateFile)]
+ path = self.packagePath + _class.getNameCap () + extension
+ return path
+
+ def targetEventFile (self, event, templateFile):
+ dot = templateFile.find(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:len (templateFile)]
+ path = self.packagePath + "Event" + event.getNameCap () + extension
+ return path
+
+ def targetMethodFile (self, method, templateFile):
+ """ Return the file name for a method file """
+ dot = templateFile.rfind(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ extension = templateFile[dot:]
+ path = self.packagePath + "Args" + method.getFullName () + extension
+ return path
+
+ def initExpansion (self):
+ self.variables = {}
+
+ def substHandler (self, object, stream, tagObject, tag):
+ if tagObject == "Root":
+ obj = "self"
+ else:
+ obj = "object" # MUST be the same as the 2nd formal parameter
+
+ call = obj + ".gen" + tag + "(stream, self.variables)"
+ eval (call)
+
+ def testCondition (self, object, tagObject, tag):
+ if tagObject == "Root":
+ obj = "self"
+ else:
+ obj = "object" # MUST be the same as the 2nd formal parameter
+
+ call = obj + ".test" + tag + "(self.variables)"
+ return eval (call)
+
+ def setVariable (self, key, value):
+ self.variables[key] = value
+
+ def makeClassFiles (self, templateFile, schema, force=False, vars=None):
+ """ Generate an expanded template per schema class """
+ classes = schema.getClasses ()
+ template = Template (self.input + templateFile, self)
+ if vars:
+ for arg in vars:
+ self.setVariable(arg, vars[arg])
+ self.templateFiles.append (templateFile)
+ for _class in classes:
+ target = self.targetClassFile (_class, templateFile)
+ stream = template.expand (_class)
+ self.writeIfChanged (stream, target, force)
+
+ def makeEventFiles (self, templateFile, schema, force=False, vars=None):
+ """ Generate an expanded template per schema event """
+ events = schema.getEvents()
+ template = Template (self.input + templateFile, self)
+ if vars:
+ for arg in vars:
+ self.setVariable(arg, vars[arg])
+ self.templateFiles.append (templateFile)
+ for event in events:
+ target = self.targetEventFile(event, templateFile)
+ stream = template.expand(event)
+ self.writeIfChanged(stream, target, force)
+
+ def makeMethodFiles (self, templateFile, schema, force=False, vars=None):
+ """ Generate an expanded template per method-with-arguments """
+ classes = schema.getClasses ()
+ template = Template (self.input + templateFile, self)
+ if vars:
+ for arg in vars:
+ self.setVariable(arg, vars[arg])
+ self.templateFiles.append (templateFile)
+ for _class in classes:
+ methods = _class.getMethods ()
+ for method in methods:
+ if method.getArgCount () > 0:
+ target = self.targetMethodFile (method, templateFile)
+ stream = template.expand (method)
+ self.writeIfChanged (stream, target, force)
+
+ def makePackageFile (self, templateFile, schema, force=False, vars=None):
+ """ Generate a package-specific file """
+ template = Template (self.input + templateFile, self)
+ if vars:
+ for arg in vars:
+ self.setVariable(arg, vars[arg])
+ self.templateFiles.append (templateFile)
+ target = self.targetPackageFile (schema, templateFile)
+ stream = template.expand (schema)
+ self.writeIfChanged (stream, target, force)
+
+ def makeV2PackageFile (self, templateFile, schema, force=False, vars=None):
+ """ Generate a QMFv2 package definition file """
+ template = Template (self.input + templateFile, self)
+ if vars:
+ for arg in vars:
+ self.setVariable(arg, vars[arg])
+ self.templateFiles.append (templateFile)
+ target = self.targetV2PackageFile (schema, templateFile)
+ stream = template.expand (schema)
+ self.writeIfChanged (stream, target, force)
+
+ def makeSingleFile (self, templateFile, target, force=False, vars=None):
+ """ Generate a single expanded template """
+ dot = templateFile.find(".")
+ if dot == -1:
+ raise ValueError ("Invalid template file name %s" % templateFile)
+ className = templateFile[0:dot]
+ if className == "Makefile":
+ classType = Makefile
+ elif className == "CMakeLists":
+ classType = CMakeLists
+ else:
+ raise ValueError ("Invalid class name %s" % className)
+ makefile = classType (self.filelists, self.templateFiles, self.packagelist)
+ template = Template (self.input + templateFile, self)
+ if vars:
+ for arg in vars:
+ self.setVariable(arg, vars[arg])
+ self.templateFiles.append (templateFile)
+ stream = template.expand (makefile)
+ self.writeIfChanged (stream, target, force)
+
+ def getModulePath():
+ return __file__
+
+ getModulePath = staticmethod(getModulePath)
diff --git a/qpid/cpp/managementgen/qmfgen/management-types.xml b/qpid/cpp/managementgen/qmfgen/management-types.xml
new file mode 100644
index 0000000000..c88f0caeae
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/management-types.xml
@@ -0,0 +1,77 @@
+<schema-types>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!-- "unmap": cast to convert from Variant to native type constructor,
+ "map": cast to convert from native type to Variant constructor parameter
+-->
+
+<type name="objId" base="REF" cpp="::qpid::management::ObjectId"
+ encode="{std::string _s; #.encode(_s); @.putRawData(_s);}"
+ decode="{std::string _s; @.getRawData(_s, #.encodedSize()); #.decode(_s);}"
+ stream="#.getV2Key()" size="16" accessor="direct" init="::qpid::management::ObjectId()" byRef="y"/>
+<type name="uint8" base="U8" cpp="uint8_t" encode="@.putOctet(#)" decode="# = @.getOctet()" stream="#" size="1" accessor="direct" init="0"/>
+<type name="uint16" base="U16" cpp="uint16_t" encode="@.putShort(#)" decode="# = @.getShort()" stream="#" size="2" accessor="direct" init="0"/>
+<type name="uint32" base="U32" cpp="uint32_t" encode="@.putLong(#)" decode="# = @.getLong()" stream="#" size="4" accessor="direct" init="0"/>
+<type name="uint64" base="U64" cpp="uint64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" stream="#" size="8" accessor="direct" init="0"/>
+<type name="int8" base="S8" cpp="int8_t" encode="@.putInt8(#)" decode="# = @.getInt8()" stream="#" size="1" accessor="direct" init="0"/>
+<type name="int16" base="S16" cpp="int16_t" encode="@.putInt16(#)" decode="# = @.getInt16()" stream="#" size="2" accessor="direct" init="0"/>
+<type name="int32" base="S32" cpp="int32_t" encode="@.putInt32(#)" decode="# = @.getInt32()" stream="#" size="4" accessor="direct" init="0"/>
+<type name="int64" base="S64" cpp="int64_t" encode="@.putInt64(#)" decode="# = @.getInt64()" stream="#" size="8" accessor="direct" init="0"/>
+<type name="bool" base="BOOL" cpp="bool" encode="@.putOctet(#?1:0)" decode="# = @.getOctet()==1" stream="#" size="1" accessor="direct" init="0"/>
+<type name="sstr" base="SSTR" cpp="std::string" encode="@.putShortString(#)" decode="@.getShortString(#)" stream="#" size="(1 + #.length())" accessor="direct" init='""' byRef="y" unmap="(#).getString()"/>
+<type name="lstr" base="LSTR" cpp="std::string" encode="@.putMediumString(#)" decode="@.getMediumString(#)" stream="#" size="(2 + #.length())" accessor="direct" init='""' byRef="y" unmap="(#).getString()"/>
+<type name="absTime" base="ABSTIME" cpp="int64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" stream="#" size="8" accessor="direct" init="0"/>
+<type name="deltaTime" base="DELTATIME" cpp="uint64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" stream="#" size="8" accessor="direct" init="0"/>
+<type name="float" base="FLOAT" cpp="float" encode="@.putFloat(#)" decode="# = @.getFloat()" stream="#" size="4" accessor="direct" init="0."/>
+<type name="double" base="DOUBLE" cpp="double" encode="@.putDouble(#)" decode="# = @.getDouble()" stream="#" size="8" accessor="direct" init="0."/>
+<type name="uuid" base="UUID" cpp="::qpid::types::Uuid"
+ encode="@.putRawData(#.data(), 16)"
+ decode="{ unsigned char d[16]; @.getRawData(d, 16); # = ::qpid::types::Uuid(d); }"
+ stream="#" size="16" accessor="direct" init="::qpid::types::Uuid()" byRef="y"
+ unmap="(#).asUuid().data()"
+ map="::qpid::types::Uuid((#).data())" />
+<type name="map" base="FTABLE" cpp="::qpid::types::Variant::Map"
+ encode="@.putMap(#)"
+ decode="@.getMap(#)"
+ size="::qpid::amqp_0_10::MapCodec::encodedSize(#)"
+ stream="#" accessor="direct" init="::qpid::types::Variant::Map()" byRef="y" unmap="(#).asMap()"/>
+<type name="list" base="LIST" cpp="::qpid::types::Variant::List"
+ encode="@.putList(#)"
+ decode="@.getList(#)"
+ size="::qpid::amqp_0_10::ListCodec::encodedSize(#)"
+ stream="#" accessor="direct" init="::qpid::types::Variant::List()" byRef="y" unmap="(#).asList()"/>
+
+<type name="hilo8" base="U8" cpp="uint8_t" encode="@.putOctet(#)" decode="# = @.getOctet()" style="wm" stream="#" size="1" accessor="counter" init="0"/>
+<type name="hilo16" base="U16" cpp="uint16_t" encode="@.putShort(#)" decode="# = @.getShort()" style="wm" stream="#" size="2" accessor="counter" init="0"/>
+<type name="hilo32" base="U32" cpp="uint32_t" encode="@.putLong(#)" decode="# = @.getLong()" style="wm" stream="#" size="4" accessor="counter" init="0"/>
+<type name="hilo64" base="U64" cpp="uint64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" style="wm" stream="#" size="8" accessor="counter" init="0"/>
+
+<type name="count8" base="U8" cpp="uint8_t" encode="@.putOctet(#)" decode="# = @.getOctet()" stream="#" size="1" accessor="counter" init="0" perThread="y"/>
+<type name="count16" base="U16" cpp="uint16_t" encode="@.putShort(#)" decode="# = @.getShort()" stream="#" size="2" accessor="counter" init="0" perThread="y"/>
+<type name="count32" base="U32" cpp="uint32_t" encode="@.putLong(#)" decode="# = @.getLong()" stream="#" size="4" accessor="counter" init="0" perThread="y"/>
+<type name="count64" base="U64" cpp="uint64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" stream="#" size="8" accessor="counter" init="0" perThread="y"/>
+
+<!-- Min/Max/Average statistics -->
+<type name="mma32" base="U32" cpp="uint32_t" encode="@.putLong(#)" decode="# = @.getLong()" style="mma" stream="#" size="4" accessor="direct" init="0" perThread="y"/>
+<type name="mma64" base="U64" cpp="uint64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" style="mma" stream="#" size="8" accessor="direct" init="0" perThread="y"/>
+<type name="mmaTime" base="DELTATIME" cpp="uint64_t" encode="@.putLongLong(#)" decode="# = @.getLongLong()" style="mma" stream="#" size="8" accessor="direct" init="0" perThread="y"/>
+
+</schema-types>
diff --git a/qpid/cpp/managementgen/qmfgen/schema.py b/qpid/cpp/managementgen/qmfgen/schema.py
new file mode 100755
index 0000000000..59e951fb6e
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/schema.py
@@ -0,0 +1,1852 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+from xml.dom.minidom import parse, parseString, Node
+from cStringIO import StringIO
+#import md5
+try:
+ import hashlib
+ _md5Obj = hashlib.md5
+except ImportError:
+ import md5
+ _md5Obj = md5.new
+
+class Hash:
+ """ Manage the hash of an XML sub-tree """
+ def __init__(self, node):
+ self.md5Sum = _md5Obj()
+ self._compute(node)
+
+ def addSubHash(self, hash):
+ """ Use this method to add the hash of a dependend-on XML fragment that is not in the sub-tree """
+ self.md5Sum.update(hash.getDigest())
+
+ def getDigest(self):
+ return self.md5Sum.digest()
+
+ def _compute(self, node):
+ attrs = node.attributes
+ self.md5Sum.update(node.nodeName)
+
+ for idx in range(attrs.length):
+ self.md5Sum.update(attrs.item(idx).nodeName)
+ self.md5Sum.update(attrs.item(idx).nodeValue)
+
+ for child in node.childNodes:
+ if child.nodeType == Node.ELEMENT_NODE:
+ self._compute(child)
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaType:
+ def __init__ (self, node):
+ self.name = None
+ self.base = None
+ self.cpp = None
+ self.encode = None
+ self.decode = None
+ self.style = "normal"
+ self.stream = "#"
+ self.size = "1"
+ self.accessor = None
+ self.init = "0"
+ self.perThread = False
+ self.byRef = False
+ self.unmap = "#"
+ self.map = "#"
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'base':
+ self.base = val
+
+ elif key == 'cpp':
+ self.cpp = val
+
+ elif key == 'encode':
+ self.encode = val
+
+ elif key == 'decode':
+ self.decode = val
+
+ elif key == 'style':
+ self.style = val
+
+ elif key == 'stream':
+ self.stream = val
+
+ elif key == 'size':
+ self.size = val
+
+ elif key == 'accessor':
+ self.accessor = val
+
+ elif key == 'init':
+ self.init = val
+
+ elif key == 'perThread':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in perThread attribute")
+ self.perThread = True
+
+ elif key == 'byRef':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in byRef attribute")
+ self.byRef = True
+
+ elif key == 'unmap':
+ self.unmap = val
+
+ elif key == 'map':
+ self.map = val
+
+ else:
+ raise ValueError ("Unknown attribute in type '%s'" % key)
+
+ if self.name == None or self.base == None or self.cpp == None or \
+ self.encode == None or self.decode == None:
+ raise ValueError ("Missing required attribute(s) in type")
+
+ if self.byRef:
+ self.asArg = "const " + self.cpp + "&"
+ else:
+ self.asArg = self.cpp
+
+ def getName (self):
+ return self.name
+
+ def genAccessor (self, stream, varName, changeFlag = None, optional = False):
+ if self.perThread:
+ prefix = "getThreadStats()->"
+ if self.style == "wm":
+ raise ValueError ("'wm' style types can't be per-thread")
+ else:
+ prefix = ""
+ if self.accessor == "direct":
+ stream.write (" inline void set_" + varName + " (" + self.asArg + " val) {\n");
+ if not self.perThread:
+ stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
+ if self.style != "mma":
+ stream.write (" " + prefix + varName + " = val;\n")
+ if optional:
+ stream.write (" presenceMask[presenceByte_%s] |= presenceMask_%s;\n" % (varName, varName))
+ if self.style == "wm":
+ stream.write (" if (" + varName + "Low > val)\n")
+ stream.write (" " + varName + "Low = val;\n")
+ stream.write (" if (" + varName + "High < val)\n")
+ stream.write (" " + varName + "High = val;\n")
+ if self.style == "mma":
+ stream.write (" " + prefix + varName + "Count++;\n")
+ stream.write (" " + prefix + varName + "Total += val;\n")
+ stream.write (" if (" + prefix + varName + "Min > val)\n")
+ stream.write (" " + prefix + varName + "Min = val;\n")
+ stream.write (" if (" + prefix + varName + "Max < val)\n")
+ stream.write (" " + prefix + varName + "Max = val;\n")
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n")
+ if self.style != "mma":
+ stream.write (" inline " + self.asArg + " get_" + varName + "() {\n");
+ if not self.perThread:
+ stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
+ stream.write (" return " + prefix + varName + ";\n")
+ stream.write (" }\n")
+ if optional:
+ stream.write (" inline void clr_" + varName + "() {\n")
+ stream.write (" presenceMask[presenceByte_%s] &= ~presenceMask_%s;\n" % (varName, varName))
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n")
+ stream.write (" inline bool isSet_" + varName + "() {\n")
+ stream.write (" return (presenceMask[presenceByte_%s] & presenceMask_%s) != 0;\n" % (varName, varName))
+ stream.write (" }\n")
+ elif self.accessor == "counter":
+ stream.write (" inline void inc_" + varName + " (" + self.asArg + " by = 1) {\n");
+ if not self.perThread:
+ stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
+ stream.write (" " + prefix + varName + " += by;\n")
+ if self.style == "wm":
+ stream.write (" if (" + varName + "High < " + varName + ")\n")
+ stream.write (" " + varName + "High = " + varName + ";\n")
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n");
+ stream.write (" inline void dec_" + varName + " (" + self.asArg + " by = 1) {\n");
+ if not self.perThread:
+ stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
+ stream.write (" " + prefix + varName + " -= by;\n")
+ if self.style == "wm":
+ stream.write (" if (" + varName + "Low > " + varName + ")\n")
+ stream.write (" " + varName + "Low = " + varName + ";\n")
+ if changeFlag != None:
+ stream.write (" " + changeFlag + " = true;\n")
+ stream.write (" }\n");
+
+ def genHiLoStatResets (self, stream, varName):
+ if self.style == "wm":
+ stream.write (" " + varName + "High = " + varName + ";\n")
+ stream.write (" " + varName + "Low = " + varName + ";\n")
+ if self.style == "mma":
+ stream.write (" " + varName + "Count = 0;\n")
+ stream.write (" " + varName + "Total = 0;\n")
+ stream.write (" " + varName + "Min = std::numeric_limits<" + self.type.type.cpp + ">::max();\n")
+ stream.write (" " + varName + "Max = std::numeric_limits<" + self.type.type.cpp + ">::min();\n")
+
+ def genPerThreadHiLoStatResets (self, stream, varName, cpptype):
+ if self.style == "mma":
+ stream.write (" threadStats->" + varName + "Count = 0;\n")
+ stream.write (" threadStats->" + varName + "Total = 0;\n")
+ stream.write (" threadStats->" + varName + "Min = std::numeric_limits<" + cpptype + ">::max();\n")
+ stream.write (" threadStats->" + varName + "Max = std::numeric_limits<" + cpptype + ">::min();\n")
+
+ def genRead (self, stream, varName, indent=" "):
+ stream.write(indent + self.decode.replace("@", "buf").replace("#", varName) + ";\n")
+
+ def genUnmap (self, stream, varName, indent=" ", key=None, mapName="_map",
+ _optional=False):
+ if key is None:
+ key = varName
+ stream.write(indent + "if ((_i = " + mapName + ".find(\"" + key + "\")) != " + mapName + ".end()) {\n")
+ stream.write(indent + " " + varName + " = " +
+ self.unmap.replace("#", "_i->second") + ";\n")
+ if _optional:
+ stream.write(indent + " _found = true;\n")
+ stream.write(indent + "}\n")
+
+ def genWrite (self, stream, varName, indent=" "):
+ if self.style != "mma":
+ stream.write (indent + self.encode.replace ("@", "buf").replace ("#", varName) + ";\n")
+ if self.style == "wm":
+ stream.write (indent + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "High") + ";\n")
+ stream.write (indent + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "Low") + ";\n")
+ if self.style == "mma":
+ stream.write (indent + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "Count") + ";\n")
+ stream.write (indent + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "Count ? " + varName + "Min : 0") + ";\n")
+ stream.write (indent + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "Max") + ";\n")
+ stream.write (indent + self.encode.replace ("@", "buf") \
+ .replace ("#", varName + "Count ? " + varName + "Total / " +
+ varName + "Count : 0") + ";\n")
+
+ def genMap (self, stream, varName, indent=" ", key=None, mapName="_map"):
+ if key is None:
+ key = varName
+ if self.style != "mma":
+ var_cast = self.map.replace("#", varName)
+ stream.write(indent + mapName + "[\"" + key + "\"] = ::qpid::types::Variant(" + var_cast + ");\n")
+ if self.style == "wm":
+ var_cast_hi = self.map.replace("#", varName + "High")
+ var_cast_lo = self.map.replace("#", varName + "Low")
+ stream.write(indent + mapName + "[\"" + key + "High\"] = " +
+ "::qpid::types::Variant(" + var_cast_hi + ");\n")
+ stream.write(indent + mapName + "[\"" + key + "Low\"] = " +
+ "::qpid::types::Variant(" + var_cast_lo + ");\n")
+ if self.style == "mma":
+ var_cast = self.map.replace("#", varName + "Count")
+ stream.write(indent + mapName + "[\"" + key + "Count\"] = " + "::qpid::types::Variant(" + var_cast + ");\n")
+ var_cast = self.map.replace("#", varName + "Min")
+ stream.write(indent + mapName + "[\"" + key + "Min\"] = " +
+ "(" + varName + "Count ? ::qpid::types::Variant(" + var_cast + ") : ::qpid::types::Variant(0));\n")
+ var_cast = self.map.replace("#", varName + "Max")
+ stream.write(indent + mapName + "[\"" + key + "Max\"] = " + "::qpid::types::Variant(" + var_cast + ");\n")
+
+ var_cast = self.map.replace("#", "(" + varName + "Total / " + varName + "Count)")
+ stream.write(indent + mapName + "[\"" + key + "Avg\"] = " +
+ "(" + varName + "Count ? ::qpid::types::Variant(" + var_cast + ") : ::qpid::types::Variant(0));\n")
+
+ def getReadCode (self, varName, bufName):
+ result = self.decode.replace ("@", bufName).replace ("#", varName)
+ return result
+
+ def getWriteCode (self, varName, bufName):
+ result = self.encode.replace ("@", bufName).replace ("#", varName)
+ return result
+
+#=====================================================================================
+#
+#=====================================================================================
+class TypeSpec:
+ def __init__ (self, file):
+ self.types = {}
+ dom = parse (file)
+ document = dom.documentElement
+ if document.tagName != 'schema-types':
+ raise ValueError ("Expected 'schema-types' in type file")
+
+ for child in document.childNodes:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'type':
+ stype = SchemaType (child)
+ self.types[stype.getName ()] = stype
+ else:
+ raise ValueError ("Unknown type tag '%s'" % child.nodeName)
+
+ def getType (self, name):
+ return self.types[name]
+
+
+#=====================================================================================
+#
+#=====================================================================================
+class Type:
+ def __init__ (self, name, typespec):
+ self.type = typespec.getType (name)
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaProperty:
+ def __init__ (self, node, typespec):
+ self.name = None
+ self.type = None
+ self.ref = None
+ self.access = "RO"
+ self.isIndex = 0
+ self.isParentRef = 0
+ self.isGeneralRef = 0
+ self.isOptional = 0
+ self.unit = None
+ self.min = None
+ self.max = None
+ self.maxLen = None
+ self.desc = None
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = makeValidCppSymbol(val)
+
+ elif key == 'type':
+ self.type = Type (val, typespec)
+ if self.type.type.accessor != 'direct':
+ raise ValueError ("Class properties must have a type with a direct accessor")
+
+ elif key == 'references':
+ self.ref = val
+
+ elif key == 'access':
+ self.access = val
+
+ elif key == 'index':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in index attribute")
+ self.isIndex = 1
+
+ elif key == 'parentRef':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in parentRef attribute")
+ self.isParentRef = 1
+
+ elif key == 'isGeneralReference':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in isGeneralReference attribute")
+ self.isGeneralRef = 1
+
+ elif key == 'optional':
+ if val != 'y':
+ raise ValueError ("Expected 'y' in optional attribute")
+ self.isOptional = 1
+
+ elif key == 'unit':
+ self.unit = val
+
+ elif key == 'min':
+ self.min = val
+
+ elif key == 'max':
+ self.max = val
+
+ elif key == 'maxlen':
+ self.maxLen = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ else:
+ raise ValueError ("Unknown attribute in property '%s'" % key)
+
+ if self.access == "RC" and self.isOptional == 1:
+ raise ValueError ("Properties with ReadCreate access must not be optional (%s)" % self.name)
+
+ if self.name == None:
+ raise ValueError ("Missing 'name' attribute in property")
+ if self.type == None:
+ raise ValueError ("Missing 'type' attribute in property")
+
+ def getName (self):
+ return self.name
+
+ def isConstructorArg (self):
+ if self.access == "RC" and self.isParentRef == 0:
+ return 1
+ return 0
+
+ def genDeclaration (self, stream, prefix=" "):
+ stream.write (prefix + self.type.type.cpp + " " + self.name + ";\n")
+
+ def genFormalParam (self, stream, variables):
+ stream.write (self.type.type.asArg + " _" + self.name)
+
+ def genAccessor (self, stream):
+ self.type.type.genAccessor (stream, self.name, "configChanged", self.isOptional == 1)
+
+ def genInitialize (self, stream, prefix="", indent=" "):
+ val = self.type.type.init
+ stream.write (indent + prefix + self.name + " = " + val + ";\n")
+
+ def genSchema (self, stream):
+ stream.write (" ft.clear();\n")
+ stream.write (" ft[NAME] = \"" + self.name + "\";\n")
+ stream.write (" ft[TYPE] = TYPE_" + self.type.type.base +";\n")
+ stream.write (" ft[ACCESS] = ACCESS_" + self.access + ";\n")
+ stream.write (" ft[IS_INDEX] = " + str (self.isIndex) + ";\n")
+ stream.write (" ft[IS_OPTIONAL] = " + str (self.isOptional) + ";\n")
+ if self.unit != None:
+ stream.write (" ft[UNIT] = \"" + self.unit + "\";\n")
+ if self.min != None:
+ stream.write (" ft[MIN] = " + self.min + ";\n")
+ if self.max != None:
+ stream.write (" ft[MAX] = " + self.max + ";\n")
+ if self.maxLen != None:
+ stream.write (" ft[MAXLEN] = " + self.maxLen + ";\n")
+ if self.desc != None:
+ stream.write (" ft[DESC] = \"" + self.desc + "\";\n")
+ stream.write (" buf.putMap(ft);\n\n")
+
+
+ def genSchemaMap(self, stream):
+ stream.write (" {\n")
+ stream.write (" ::qpid::types::Variant::Map _value;\n")
+ stream.write (" _value[TYPE] = TYPE_" + self.type.type.base +";\n")
+ stream.write (" _value[ACCESS] = ACCESS_" + self.access + ";\n")
+ stream.write (" _value[IS_INDEX] = " + str (self.isIndex) + ";\n")
+ stream.write (" _value[IS_OPTIONAL] = " + str (self.isOptional) + ";\n")
+ if self.unit != None:
+ stream.write (" _value[UNIT] = \"" + self.unit + "\";\n")
+ if self.min != None:
+ stream.write (" _value[MIN] = " + self.min + ";\n")
+ if self.max != None:
+ stream.write (" _value[MAX] = " + self.max + ";\n")
+ if self.maxLen != None:
+ stream.write (" _value[MAXLEN] = " + self.maxLen + ";\n")
+ if self.desc != None:
+ stream.write (" _value[DESC] = \"" + self.desc + "\";\n")
+ stream.write (" _props[\"" + self.name + "\"] = _value;\n")
+ stream.write (" }\n\n")
+
+
+
+ def genSize (self, stream):
+ indent = " "
+ if self.isOptional:
+ stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
+ indent = " "
+ stream.write("%ssize += %s; // %s\n" % (indent, self.type.type.size.replace("#", self.name), self.name))
+ if self.isOptional:
+ stream.write(" }\n")
+
+ def genRead (self, stream):
+ indent = " "
+ if self.isOptional:
+ stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
+ indent = " "
+ self.type.type.genRead (stream, self.name, indent)
+ if self.isOptional:
+ stream.write(" }\n")
+
+ def genWrite (self, stream):
+ indent = " "
+ if self.isOptional:
+ stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
+ indent = " "
+ self.type.type.genWrite (stream, self.name, indent)
+ if self.isOptional:
+ stream.write(" }\n")
+
+ def genUnmap (self, stream):
+ indent = " "
+ if self.isOptional:
+ stream.write(" _found = false;\n")
+ self.type.type.genUnmap (stream, self.name, indent, _optional=self.isOptional)
+ if self.isOptional:
+ stream.write(" if (_found) {\n")
+ stream.write(" presenceMask[presenceByte_%s] |= presenceMask_%s;\n" %
+ (self.name, self.name))
+ stream.write(" }\n")
+
+ def genMap (self, stream):
+ indent = " "
+ if self.isOptional:
+ stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
+ indent = " "
+ self.type.type.genMap (stream, self.name, indent)
+ if self.isOptional:
+ stream.write(" }\n")
+
+
+ def __repr__(self):
+ m = {}
+ m["name"] = self.name
+ m["type"] = self.type
+ m["ref"] = self.ref
+ m["access"] = self.access
+ m["isIndex"] = self.isIndex
+ m["isParentRef"] = self.isParentRef
+ m["isGeneralRef"] = self.isGeneralRef
+ m["isOptional"] = self.isOptional
+ m["unit"] = self.unit
+ m["min"] = self.min
+ m["max"] = self.max
+ m["maxLen"] = self.maxLen
+ m["desc"] = self.desc
+ return str(m)
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaStatistic:
+ def __init__ (self, node, typespec):
+ self.name = None
+ self.type = None
+ self.unit = None
+ self.desc = None
+ self.assign = None
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = makeValidCppSymbol(val)
+
+ elif key == 'type':
+ self.type = Type (val, typespec)
+
+ elif key == 'unit':
+ self.unit = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ elif key == 'assign':
+ self.assign = val
+
+ else:
+ raise ValueError ("Unknown attribute in statistic '%s'" % key)
+
+ if self.name == None:
+ raise ValueError ("Missing 'name' attribute in statistic")
+ if self.type == None:
+ raise ValueError ("Missing 'type' attribute in statistic")
+
+ def getName (self):
+ return self.name
+
+ def genDeclaration (self, stream, prefix=" "):
+ if self.type.type.style != "mma":
+ stream.write (prefix + self.type.type.cpp + " " + self.name + ";\n")
+ if self.type.type.style == 'wm':
+ stream.write (prefix + self.type.type.cpp + " " + self.name + "High;\n")
+ stream.write (prefix + self.type.type.cpp + " " + self.name + "Low;\n")
+ if self.type.type.style == "mma":
+ stream.write (prefix + self.type.type.cpp + " " + self.name + "Count;\n")
+ stream.write (prefix + "uint64_t " + self.name + "Total;\n")
+ stream.write (prefix + self.type.type.cpp + " " + self.name + "Min;\n")
+ stream.write (prefix + self.type.type.cpp + " " + self.name + "Max;\n")
+
+ def genAccessor (self, stream):
+ self.type.type.genAccessor (stream, self.name, "instChanged")
+
+ def genHiLoStatResets (self, stream):
+ self.type.type.genHiLoStatResets (stream, self.name)
+
+ def genPerThreadHiLoStatResets (self, stream):
+ self.type.type.genPerThreadHiLoStatResets (stream, self.name, self.type.type.cpp)
+
+ def genSchemaText (self, stream, name, desc):
+ stream.write (" ft.clear();\n")
+ stream.write (" ft[NAME] = \"" + name + "\";\n")
+ stream.write (" ft[TYPE] = TYPE_" + self.type.type.base +";\n")
+ if self.unit != None:
+ stream.write (" ft[UNIT] = \"" + self.unit + "\";\n")
+ if desc != None:
+ stream.write (" ft[DESC] = \"" + desc + "\";\n")
+ stream.write (" buf.putMap(ft);\n\n")
+
+ def genSchemaTextMap(self, stream, name, desc):
+ stream.write (" {\n")
+ stream.write (" ::qpid::types::Variant::Map _value;\n")
+ stream.write (" _value[TYPE] = TYPE_" + self.type.type.base +";\n")
+ if self.unit != None:
+ stream.write (" _value[UNIT] = \"" + self.unit + "\";\n")
+ if desc != None:
+ stream.write (" _value[DESC] = \"" + desc + "\";\n")
+ stream.write (" _stats[\"" + self.name + "\"] = _value;\n")
+ stream.write (" }\n\n")
+
+ def genSchema (self, stream):
+ if self.type.type.style != "mma":
+ self.genSchemaText (stream, self.name, self.desc)
+ if self.type.type.style == "wm":
+ descHigh = self.desc
+ descLow = self.desc
+ if self.desc != None:
+ descHigh = descHigh + " (High)"
+ descLow = descLow + " (Low)"
+ self.genSchemaText (stream, self.name + "High", descHigh)
+ self.genSchemaText (stream, self.name + "Low", descLow)
+ if self.type.type.style == "mma":
+ descCount = self.desc
+ descMin = self.desc
+ descMax = self.desc
+ descAverage = self.desc
+ if self.desc != None:
+ descCount = descCount + " (Samples)"
+ descMin = descMin + " (Min)"
+ descMax = descMax + " (Max)"
+ descAverage = descAverage + " (Average)"
+ self.genSchemaText (stream, self.name + "Samples", descCount)
+ self.genSchemaText (stream, self.name + "Min", descMin)
+ self.genSchemaText (stream, self.name + "Max", descMax)
+ self.genSchemaText (stream, self.name + "Average", descAverage)
+
+ def genSchemaMap (self, stream):
+ if self.type.type.style != "mma":
+ self.genSchemaTextMap (stream, self.name, self.desc)
+ if self.type.type.style == "wm":
+ descHigh = self.desc
+ descLow = self.desc
+ if self.desc != None:
+ descHigh = descHigh + " (High)"
+ descLow = descLow + " (Low)"
+ self.genSchemaTextMap (stream, self.name + "High", descHigh)
+ self.genSchemaTextMap (stream, self.name + "Low", descLow)
+ if self.type.type.style == "mma":
+ descCount = self.desc
+ descMin = self.desc
+ descMax = self.desc
+ descAverage = self.desc
+ if self.desc != None:
+ descCount = descCount + " (Samples)"
+ descMin = descMin + " (Min)"
+ descMax = descMax + " (Max)"
+ descAverage = descAverage + " (Average)"
+ self.genSchemaTextMap (stream, self.name + "Samples", descCount)
+ self.genSchemaTextMap (stream, self.name + "Min", descMin)
+ self.genSchemaTextMap (stream, self.name + "Max", descMax)
+ self.genSchemaTextMap (stream, self.name + "Average", descAverage)
+
+ def genAssign (self, stream):
+ if self.assign != None:
+ if self.type.type.perThread:
+ prefix = " threadStats->"
+ else:
+ prefix = ""
+ stream.write (" " + prefix + self.name + " = (" + self.type.type.cpp +
+ ") (" + self.assign + ");\n")
+
+ def genWrite (self, stream):
+ if self.type.type.perThread:
+ self.type.type.genWrite (stream, "totals." + self.name)
+ else:
+ self.type.type.genWrite (stream, self.name)
+
+ def genMap (self, stream):
+ if self.type.type.perThread:
+ self.type.type.genMap(stream, "totals." + self.name, key=self.name)
+ else:
+ self.type.type.genMap(stream, self.name)
+
+ def genInitialize (self, stream, prefix="", indent=" "):
+ val = self.type.type.init
+ if self.type.type.style != "mma":
+ stream.write (indent + prefix + self.name + " = " + val + ";\n")
+ if self.type.type.style == "wm":
+ stream.write (indent + prefix + self.name + "High = " + val + ";\n")
+ stream.write (indent + prefix + self.name + "Low = " + val + ";\n")
+ if self.type.type.style == "mma":
+ stream.write (indent + prefix + self.name + "Count = 0;\n")
+ stream.write (indent + prefix + self.name + "Min = std::numeric_limits<" + self.type.type.cpp + ">::max();\n")
+ stream.write (indent + prefix + self.name + "Max = std::numeric_limits<" + self.type.type.cpp + ">::min();\n")
+ stream.write (indent + prefix + self.name + "Total = 0;\n")
+
+ def genInitializeTotalPerThreadStats (self, stream):
+ if self.type.type.style == "mma":
+ stream.write (" totals->" + self.name + "Count = 0;\n")
+ stream.write (" totals->" + self.name + "Min = std::numeric_limits<" + self.type.type.cpp + ">::max();\n")
+ stream.write (" totals->" + self.name + "Max = std::numeric_limits<" + self.type.type.cpp + ">::min();\n")
+ stream.write (" totals->" + self.name + "Total = 0;\n")
+ else:
+ stream.write (" totals->" + self.name + " = 0;\n")
+
+ def genAggregatePerThreadStats (self, stream):
+ if self.type.type.style == "mma":
+ stream.write (" totals->%sCount += threadStats->%sCount;\n" % (self.name, self.name))
+ stream.write (" if (totals->%sMin > threadStats->%sMin)\n" % (self.name, self.name))
+ stream.write (" totals->%sMin = threadStats->%sMin;\n" % (self.name, self.name))
+ stream.write (" if (totals->%sMax < threadStats->%sMax)\n" % (self.name, self.name))
+ stream.write (" totals->%sMax = threadStats->%sMax;\n" % (self.name, self.name))
+ stream.write (" totals->%sTotal += threadStats->%sTotal;\n" % (self.name, self.name))
+ else:
+ stream.write (" totals->%s += threadStats->%s;\n" % (self.name, self.name))
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaArg:
+ def __init__ (self, node, typespec):
+ self.name = None
+ self.type = None
+ self.unit = None
+ self.dir = "I"
+ self.min = None
+ self.max = None
+ self.maxLen = None
+ self.desc = None
+ self.default = None
+ self.hash = Hash(node)
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = makeValidCppSymbol(val)
+
+ elif key == 'type':
+ self.type = Type (val, typespec)
+
+ elif key == 'unit':
+ self.unit = val
+
+ elif key == 'dir':
+ self.dir = val.upper ()
+
+ elif key == 'min':
+ self.min = val
+
+ elif key == 'max':
+ self.max = val
+
+ elif key == 'maxlen':
+ self.maxLen = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ elif key == 'default':
+ self.default = val
+
+ else:
+ raise ValueError ("Unknown attribute in arg '%s'" % key)
+
+ if self.name == None:
+ raise ValueError ("Missing 'name' attribute in arg")
+ if self.type == None:
+ raise ValueError ("Missing 'type' attribute in arg")
+
+ def getName (self):
+ return self.name
+
+ def getDir (self):
+ return self.dir
+
+ def genSchema (self, stream, event=False):
+ stream.write (" ft.clear();\n")
+ stream.write (" ft[NAME] = \"" + self.name + "\";\n")
+ stream.write (" ft[TYPE] = TYPE_" + self.type.type.base +";\n")
+ if (not event):
+ stream.write (" ft[DIR] = \"" + self.dir + "\";\n")
+ if self.unit != None:
+ stream.write (" ft[UNIT] = \"" + self.unit + "\";\n")
+ if not event:
+ if self.min != None:
+ stream.write (" ft[MIN] = " + self.min + ";\n")
+ if self.max != None:
+ stream.write (" ft[MAX] = " + self.max + ";\n")
+ if self.maxLen != None:
+ stream.write (" ft[MAXLEN] = " + self.maxLen + ";\n")
+ if self.default != None:
+ stream.write (" ft[DEFAULT] = \"" + self.default + "\";\n")
+ if self.desc != None:
+ stream.write (" ft[DESC] = \"" + self.desc + "\";\n")
+ stream.write (" buf.putMap(ft);\n\n")
+
+ def genSchemaMap (self, stream, event=False):
+ stream.write (" {\n")
+ stream.write (" ::qpid::types::Variant::Map _avalue;\n")
+ stream.write (" _avalue[TYPE] = TYPE_" + self.type.type.base +";\n")
+ if (not event):
+ stream.write (" _avalue[DIR] = \"" + self.dir + "\";\n")
+ if self.unit != None:
+ stream.write (" _avalue[UNIT] = \"" + self.unit + "\";\n")
+ if not event:
+ if self.min != None:
+ stream.write (" _avalue[MIN] = " + self.min + ";\n")
+ if self.max != None:
+ stream.write (" _avalue[MAX] = " + self.max + ";\n")
+ if self.maxLen != None:
+ stream.write (" _avalue[MAXLEN] = " + self.maxLen + ";\n")
+ if self.default != None:
+ stream.write (" _avalue[DEFAULT] = \"" + self.default + "\";\n")
+ if self.desc != None:
+ stream.write (" _avalue[DESC] = \"" + self.desc + "\";\n")
+ stream.write (" _args[\"" + self.name + "\"] = _avalue;\n")
+ stream.write (" }\n")
+
+
+
+ def genFormalParam (self, stream, variables):
+ stream.write ("%s _%s" % (self.type.type.asArg, self.name))
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaMethod:
+ def __init__ (self, parent, node, typespec):
+ self.parent = parent
+ self.name = None
+ self.desc = None
+ self.args = []
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = makeValidCppSymbol(val)
+
+ elif key == 'desc':
+ self.desc = val
+
+ else:
+ raise ValueError ("Unknown attribute in method '%s'" % key)
+
+ for child in node.childNodes:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'arg':
+ arg = SchemaArg (child, typespec)
+ self.args.append (arg)
+ else:
+ raise ValueError ("Unknown method tag '%s'" % child.nodeName)
+
+ def getName (self):
+ return self.name
+
+ def getFullName (self):
+ return capitalize(self.parent.getName()) + self.name[0:1].upper() +\
+ self.name[1:]
+
+ def getArgCount (self):
+ return len (self.args)
+
+ #===================================================================================
+ # Code Generation Functions. The names of these functions (minus the leading "gen")
+ # match the substitution keywords in the template files.
+ #===================================================================================
+ def genNameUpper (self, stream, variables):
+ stream.write (self.getFullName ().upper ())
+
+ def genNameCamel (self, stream, variables):
+ stream.write (self.getFullName ())
+
+ def genOpenNamespaces (self, stream, variables):
+ self.parent.genOpenNamespaces(stream, variables)
+
+ def genCloseNamespaces (self, stream, variables):
+ self.parent.genCloseNamespaces(stream, variables)
+
+ def genArguments (self, stream, variables):
+ for arg in self.args:
+ ctype = arg.type.type.cpp
+ dirTag = arg.dir.lower() + "_"
+ stream.write (" " + ctype + " " + dirTag + arg.getName () + ";\n")
+
+ def genNamePackageLower (self, stream, variables):
+ self.parent.genNamePackageLower(stream, variables)
+
+ def genSchema (self, stream, variables):
+ stream.write (" ft.clear();\n")
+ stream.write (" ft[NAME] = \"" + self.name + "\";\n")
+ stream.write (" ft[ARGCOUNT] = " + str (len (self.args)) + ";\n")
+ if self.desc != None:
+ stream.write (" ft[DESC] = \"" + self.desc + "\";\n")
+ stream.write (" buf.putMap(ft);\n\n")
+ for arg in self.args:
+ arg.genSchema (stream)
+
+ def genSchemaMap (self, stream, variables):
+ stream.write (" {\n")
+ stream.write (" ::qpid::types::Variant::Map _value;\n")
+ stream.write (" ::qpid::types::Variant::Map _args;\n")
+ stream.write (" _value[ARGCOUNT] = " + str(len(self.args)) + ";\n")
+ if self.desc != None:
+ stream.write (" _value[DESC] = \"" + self.desc + "\";\n")
+
+ for arg in self.args:
+ arg.genSchemaMap (stream)
+
+ stream.write (" if (!_args.empty())\n")
+ stream.write (" _value[ARGS] = _args;\n")
+
+
+ stream.write (" _methods[\"" + self.name + "\"] = _value;\n")
+ stream.write (" }\n\n")
+
+#=====================================================================================
+#
+#=====================================================================================
+class SchemaEvent:
+ def __init__ (self, package, node, typespec, argset):
+ self.packageName = package
+ self.name = None
+ self.desc = None
+ self.sevText = "inform"
+ self.args = []
+ self.hash = Hash(node)
+
+ attrs = node.attributes
+ for idx in range (attrs.length):
+ key = attrs.item(idx).nodeName
+ val = attrs.item(idx).nodeValue
+ if key == 'name':
+ self.name = val
+
+ elif key == 'desc':
+ self.desc = val
+
+ elif key == 'sev':
+ self.sevText = val
+
+ elif key == 'args':
+ list = val.replace(" ", "").split(",")
+ for item in list:
+ if item not in argset.args:
+ raise Exception("undefined argument '%s' in event" % item)
+ self.args.append(argset.args[item])
+ self.hash.addSubHash(argset.args[item].hash)
+
+ else:
+ raise ValueError ("Unknown attribute in event '%s'" % key)
+
+ if self.sevText == "emerg" : self.sev = 0
+ elif self.sevText == "alert" : self.sev = 1
+ elif self.sevText == "crit" : self.sev = 2
+ elif self.sevText == "error" : self.sev = 3
+ elif self.sevText == "warn" : self.sev = 4
+ elif self.sevText == "notice" : self.sev = 5
+ elif self.sevText == "inform" : self.sev = 6
+ elif self.sevText == "debug" : self.sev = 7
+ else:
+ raise ValueError("Unknown severity '%s' in event '%s'" % (self.sevText, self.name))
+
+ def getName (self):
+ return self.name
+
+ def getNameCap(self):
+ return capitalize(self.name)
+
+ def getFullName (self):
+ return capitalize(self.package + capitalize(self.name))
+
+ def genAgentHeaderLocation (self, stream, variables):
+ stream.write(variables["agentHeaderDir"])
+
+ def getArgCount (self):
+ return len (self.args)
+
+ def genArgCount (self, stream, variables):
+ stream.write("%d" % len(self.args))
+
+ def genArgDeclarations(self, stream, variables):
+ for arg in self.args:
+ if arg.type.type.byRef:
+ ref = "&"
+ else:
+ ref = ""
+ stream.write(" const %s%s %s;\n" % (arg.type.type.cpp, ref, arg.name))
+
+ def genCloseNamespaces (self, stream, variables):
+ for item in self.packageName.split("."):
+ stream.write ("}")
+
+ def genConstructorArgs(self, stream, variables):
+ pre = ""
+ for arg in self.args:
+ if arg.type.type.byRef:
+ ref = "&"
+ else:
+ ref = ""
+ stream.write("%sconst %s%s _%s" % (pre, arg.type.type.cpp, ref, arg.name))
+ pre = ",\n "
+
+ def genConstructorInits(self, stream, variables):
+ pre = ""
+ for arg in self.args:
+ stream.write("%s%s(_%s)" % (pre, arg.name, arg.name))
+ pre = ",\n "
+
+ def genName(self, stream, variables):
+ stream.write(self.name)
+
+ def genNameCap(self, stream, variables):
+ stream.write(capitalize(self.name))
+
+ def genNamespace (self, stream, variables):
+ stream.write("::".join(self.packageName.split(".")))
+
+ def genNameLower(self, stream, variables):
+ stream.write(self.name.lower())
+
+ def genNameUpper(self, stream, variables):
+ stream.write(self.name.upper())
+
+ def genNamePackageLower(self, stream, variables):
+ stream.write(self.packageName.lower())
+
+ def genOpenNamespaces (self, stream, variables):
+ for item in self.packageName.split("."):
+ stream.write ("namespace %s {\n" % item)
+
+ def genSeverity(self, stream, variables):
+ stream.write("%d" % self.sev)
+
+ def genArgEncodes(self, stream, variables):
+ for arg in self.args:
+ stream.write(" " + arg.type.type.encode.replace("@", "buf").replace("#", arg.name) + ";\n")
+
+ def genArgMap(self, stream, variables):
+ for arg in self.args:
+ arg.type.type.genMap(stream, arg.name, " ", mapName="map")
+ #stream.write(" " + arg.type.type.encode.replace("@", "buf").replace("#", arg.name) + ";\n")
+
+
+ def genArgSchema(self, stream, variables):
+ for arg in self.args:
+ arg.genSchema(stream, True)
+
+ def genArgSchemaMap(self, stream, variables):
+ for arg in self.args:
+ arg.genSchemaMap(stream, True)
+
+ def genSchemaMD5(self, stream, variables):
+ sum = self.hash.getDigest()
+ for idx in range (len (sum)):
+ if idx != 0:
+ stream.write (",")
+ stream.write (hex (ord (sum[idx])))
+
+
+class SchemaClass:
+ def __init__ (self, package, node, typespec, fragments, options):
+ self.packageName = package
+ self.properties = []
+ self.statistics = []
+ self.methods = []
+ self.events = []
+ self.options = options
+ self.hash = Hash(node)
+
+ attrs = node.attributes
+ self.name = makeValidCppSymbol(attrs['name'].nodeValue)
+
+ children = node.childNodes
+ for child in children:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'property':
+ sub = SchemaProperty (child, typespec)
+ self.properties.append (sub)
+
+ elif child.nodeName == 'statistic':
+ sub = SchemaStatistic (child, typespec)
+ self.statistics.append (sub)
+
+ elif child.nodeName == 'method':
+ sub = SchemaMethod (self, child, typespec)
+ self.methods.append (sub)
+
+ elif child.nodeName == 'group':
+ self.expandFragment (child, fragments)
+
+ else:
+ raise ValueError ("Unknown class tag '%s'" % child.nodeName)
+
+ # Adjust the 'assign' attributes for each statistic
+ for stat in self.statistics:
+ if stat.assign != None and stat.type.type.perThread:
+ stat.assign = self.adjust (stat.assign, self.statistics)
+
+ def adjust (self, text, statistics):
+ result = text
+ start = 0
+ while True:
+ next = None
+ for stat in statistics:
+ pos = result.find (stat.name, start)
+ if pos != -1 and (next == None or pos < next[0]):
+ next = (pos, stat.name)
+ if next == None:
+ return result
+ pos = next[0]
+ result = result[0:pos] + "threadStats->" + result[pos:]
+ start = pos + 9 + len(next[1])
+
+ def expandFragment (self, node, fragments):
+ attrs = node.attributes
+ name = attrs['name'].nodeValue
+ for fragment in fragments:
+ if fragment.name == name:
+ self.hash.addSubHash(fragment.hash)
+ for config in fragment.properties:
+ self.properties.append (config)
+ for inst in fragment.statistics:
+ self.statistics.append (inst)
+ for method in fragment.methods:
+ self.methods.append (method)
+ for event in fragment.events:
+ self.events.append (event)
+ return
+ raise ValueError ("Undefined group '%s'" % name)
+
+ def getName (self):
+ return self.name
+
+ def getNameCap (self):
+ return capitalize(self.name)
+
+ def getMethods (self):
+ return self.methods
+
+ def getEvents (self):
+ return self.events
+
+ def getPackageNameCap (self):
+ return capitalize(self.packageName)
+
+ #===================================================================================
+ # Code Generation Functions. The names of these functions (minus the leading "gen")
+ # match the substitution keywords in the template files.
+ #===================================================================================
+ def testExistOptionals (self, variables):
+ for prop in self.properties:
+ if prop.isOptional == 1:
+ return True
+ return False
+
+ def testExistPerThreadStats (self, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread:
+ return True
+ return False
+
+ def testExistPerThreadAssign (self, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread and inst.assign != None:
+ return True
+ return False
+
+ def testExistPerThreadResets (self, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread and inst.type.type.style == "mma":
+ return True
+ return False
+
+ def testNoStatistics (self, variables):
+ return len (self.statistics) == 0
+
+ def genAccessorMethods (self, stream, variables):
+ for config in self.properties:
+ if config.access != "RC":
+ config.genAccessor (stream)
+ for inst in self.statistics:
+ if inst.assign == None:
+ inst.genAccessor (stream)
+
+ def genAgentHeaderLocation (self, stream, variables):
+ stream.write(variables["agentHeaderDir"])
+
+ def genCloseNamespaces (self, stream, variables):
+ for item in self.packageName.split("."):
+ stream.write ("}")
+
+ def genConfigCount (self, stream, variables):
+ stream.write ("%d" % len (self.properties))
+
+ def genConfigDeclarations (self, stream, variables):
+ for element in self.properties:
+ element.genDeclaration (stream)
+
+ def genConstructorArgs (self, stream, variables):
+ # Constructor args are config elements with read-create access
+ result = ""
+ for element in self.properties:
+ if element.isConstructorArg ():
+ stream.write (", ")
+ element.genFormalParam (stream, variables)
+
+ def genConstructorInits (self, stream, variables):
+ for element in self.properties:
+ if element.isConstructorArg ():
+ stream.write ("," + element.getName () + "(_" + element.getName () + ")")
+
+ def genDoMethodArgs (self, stream, variables):
+ methodCount = 0
+ inArgCount = 0
+ for method in self.methods:
+ methodCount = methodCount + 1
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ inArgCount = inArgCount + 1
+
+ if methodCount == 0:
+ stream.write ("string&, const string&, string& outStr, const string&")
+ else:
+ if inArgCount == 0:
+ stream.write ("string& methodName, const string&, string& outStr, const string& userId")
+ else:
+ stream.write ("string& methodName, const string& inStr, string& outStr, const string& userId")
+
+
+ def genDoMapMethodArgs (self, stream, variables):
+ methodCount = 0
+ inArgCount = 0
+ for method in self.methods:
+ methodCount = methodCount + 1
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ inArgCount = inArgCount + 1
+
+ if methodCount == 0:
+ stream.write ("string&," +
+ " const ::qpid::types::Variant::Map&," +
+ " ::qpid::types::Variant::Map& outMap, const string&")
+ else:
+ if inArgCount == 0:
+ stream.write ("string& methodName," +
+ " const ::qpid::types::Variant::Map&," +
+ " ::qpid::types::Variant::Map& outMap, const string& userId")
+ else:
+ stream.write ("string& methodName," +
+ " const ::qpid::types::Variant::Map& inMap," +
+ " ::qpid::types::Variant::Map& outMap, const string& userId")
+
+ def genHiLoStatResets (self, stream, variables):
+ for inst in self.statistics:
+ if not inst.type.type.perThread:
+ inst.genHiLoStatResets (stream)
+
+ def genPerThreadHiLoStatResets (self, stream, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread:
+ inst.genPerThreadHiLoStatResets (stream)
+
+ def genInitializeElements (self, stream, variables):
+ for prop in self.properties:
+ if not prop.isConstructorArg() and not prop.isParentRef:
+ prop.genInitialize(stream)
+ for inst in self.statistics:
+ if not inst.type.type.perThread:
+ inst.genInitialize (stream)
+
+ def genInitializePerThreadElements (self, stream, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread:
+ inst.genInitialize (stream, "threadStats->", " ")
+
+ def genInitializeTotalPerThreadStats (self, stream, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread:
+ inst.genInitializeTotalPerThreadStats (stream)
+
+ def genAggregatePerThreadStats (self, stream, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread:
+ inst.genAggregatePerThreadStats (stream)
+
+ def genInstCount (self, stream, variables):
+ count = 0
+ for inst in self.statistics:
+ count = count + 1
+ if inst.type.type.style == "wm":
+ count = count + 2
+ if inst.type.type.style == "mma":
+ count = count + 3
+ stream.write ("%d" % count)
+
+ def genInstDeclarations (self, stream, variables):
+ for element in self.statistics:
+ if not element.type.type.perThread:
+ element.genDeclaration (stream)
+
+ def genPerThreadDeclarations (self, stream, variables):
+ for element in self.statistics:
+ if element.type.type.perThread:
+ element.genDeclaration (stream, " ")
+
+ def genPrimaryKey (self, stream, variables):
+ first = 1
+ for prop in self.properties:
+ # deliberately leave out the "vhostRef" fields since there's only one vhost,
+ # this serves to shorten the keys without compromising uniqueness
+ if prop.getName() != "vhostRef":
+ if prop.isIndex == 1:
+ if first:
+ first = None
+ else:
+ stream.write(" << \",\";\n")
+ var = prop.type.type.stream.replace("#", prop.getName())
+ stream.write(" key << %s" % var)
+ if not first:
+ stream.write(";")
+
+ def genNamespace (self, stream, variables):
+ stream.write("::".join(self.packageName.split(".")))
+
+ def genMethodArgIncludes (self, stream, variables):
+ for method in self.methods:
+ if method.getArgCount () > 0:
+ stream.write ("#include \"Args" + method.getFullName () + ".h\"\n")
+
+ def genMethodCount (self, stream, variables):
+ stream.write ("%d" % len (self.methods))
+
+ def genMethodHandlers (self, stream, variables):
+ inArgs = False
+ for method in self.methods:
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ inArgs = True;
+ break
+
+ if inArgs:
+ stream.write("\n")
+ stream.write(" char *_tmpBuf = new char[inStr.length()];\n")
+ stream.write(" memcpy(_tmpBuf, inStr.data(), inStr.length());\n")
+ stream.write(" ::qpid::management::Buffer inBuf(_tmpBuf, inStr.length());\n")
+
+ for method in self.methods:
+ stream.write ("\n if (methodName == \"" + method.getName () + "\") {\n")
+ stream.write (" _matched = true;\n")
+ if method.getArgCount () == 0:
+ stream.write (" ::qpid::management::ArgsNone ioArgs;\n")
+ else:
+ stream.write (" Args" + method.getFullName () + " ioArgs;\n")
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ stream.write (" " +\
+ arg.type.type.getReadCode ("ioArgs." +\
+ arg.dir.lower () + "_" +\
+ arg.name, "inBuf") + ";\n")
+
+ stream.write (" bool allow = coreObject->AuthorizeMethod(METHOD_" +\
+ method.getName().upper() + ", ioArgs, userId);\n")
+ stream.write (" if (allow)\n")
+ stream.write (" status = coreObject->ManagementMethod (METHOD_" +\
+ method.getName().upper() + ", ioArgs, text);\n")
+ stream.write (" else\n")
+ stream.write (" status = Manageable::STATUS_FORBIDDEN;\n")
+ stream.write (" outBuf.putLong (status);\n")
+ stream.write (" outBuf.putMediumString(::qpid::management::Manageable::StatusText (status, text));\n")
+ for arg in method.args:
+ if arg.getDir () == "O" or arg.getDir () == "IO":
+ stream.write (" " +\
+ arg.type.type.getWriteCode ("ioArgs." +\
+ arg.dir.lower () + "_" +\
+ arg.name, "outBuf") + ";\n")
+ stream.write(" }\n")
+
+ if inArgs:
+ stream.write ("\n delete [] _tmpBuf;\n")
+
+
+
+ def genMapMethodHandlers (self, stream, variables):
+ for method in self.methods:
+ stream.write ("\n if (methodName == \"" + method.getName () + "\") {\n")
+ if method.getArgCount () == 0:
+ stream.write (" ::qpid::management::ArgsNone ioArgs;\n")
+ else:
+ stream.write (" Args" + method.getFullName () + " ioArgs;\n")
+ stream.write (" ::qpid::types::Variant::Map::const_iterator _i;\n")
+
+ # decode each input argument from the input map
+ for arg in method.args:
+ if arg.getDir () == "I" or arg.getDir () == "IO":
+ arg.type.type.genUnmap(stream,
+ "ioArgs." + arg.dir.lower () + "_" + arg.name,
+ " ",
+ arg.name,
+ "inMap")
+
+ stream.write (" bool allow = coreObject->AuthorizeMethod(METHOD_" +\
+ method.getName().upper() + ", ioArgs, userId);\n")
+ stream.write (" if (allow)\n")
+ stream.write (" status = coreObject->ManagementMethod (METHOD_" +\
+ method.getName().upper() + ", ioArgs, text);\n")
+ stream.write (" else\n")
+ stream.write (" status = Manageable::STATUS_FORBIDDEN;\n")
+ stream.write (" outMap[\"_status_code\"] = (uint32_t) status;\n")
+ stream.write (" outMap[\"_status_text\"] = ::qpid::management::Manageable::StatusText(status, text);\n")
+ for arg in method.args:
+ if arg.getDir () == "O" or arg.getDir () == "IO":
+ arg.type.type.genMap(stream,
+ "ioArgs." + arg.dir.lower () + "_" + arg.name,
+ " ",
+ arg.name,
+ "outMap")
+ stream.write (" return;\n }\n")
+
+ def genOpenNamespaces (self, stream, variables):
+ for item in self.packageName.split("."):
+ stream.write ("namespace %s {\n" % item)
+
+ def genPresenceMaskBytes (self, stream, variables):
+ count = 0
+ for prop in self.properties:
+ if prop.isOptional == 1:
+ count += 1
+ if count == 0:
+ stream.write("0")
+ else:
+ stream.write (str(((count - 1) / 8) + 1))
+
+ def genPresenceMaskConstants (self, stream, variables):
+ count = 0
+ for prop in self.properties:
+ if prop.isOptional == 1:
+ stream.write(" static const uint8_t presenceByte_%s = %d;\n" % (prop.name, count / 8))
+ stream.write(" static const uint8_t presenceMask_%s = %d;\n" % (prop.name, 1 << (count % 8)))
+ count += 1
+
+ def genPropertySchema (self, stream, variables):
+ for prop in self.properties:
+ prop.genSchema (stream)
+
+ def genPropertySchemaMap (self, stream, variables):
+ for prop in self.properties:
+ prop.genSchemaMap(stream)
+
+ def genSetGeneralReferenceDeclaration (self, stream, variables):
+ for prop in self.properties:
+ if prop.isGeneralRef:
+ stream.write ("void setReference(::qpid::management::ObjectId objectId) { " + prop.name + " = objectId; }\n")
+
+ def genStatisticSchema (self, stream, variables):
+ for stat in self.statistics:
+ stat.genSchema (stream)
+
+ def genStatisticSchemaMap (self, stream, variables):
+ for stat in self.statistics:
+ stat.genSchemaMap(stream)
+
+ def genMethodIdDeclarations (self, stream, variables):
+ number = 1
+ for method in self.methods:
+ stream.write (" static const uint32_t METHOD_" + method.getName().upper() +\
+ " = %d;\n" % number)
+ number = number + 1
+
+ def genMethodSchema (self, stream, variables):
+ for method in self.methods:
+ method.genSchema (stream, variables)
+
+ def genMethodSchemaMap(self, stream, variables):
+ for method in self.methods:
+ method.genSchemaMap(stream, variables)
+
+ def genName (self, stream, variables):
+ stream.write (self.name)
+
+ def genNameCap (self, stream, variables):
+ stream.write (capitalize(self.name))
+
+ def genNameLower (self, stream, variables):
+ stream.write (self.name.lower ())
+
+ def genNamePackageCap (self, stream, variables):
+ stream.write (self.getPackageNameCap ())
+
+ def genNamePackageLower (self, stream, variables):
+ stream.write (self.packageName.lower ())
+
+ def genNameUpper (self, stream, variables):
+ stream.write (self.name.upper ())
+
+ def genParentArg (self, stream, variables):
+ for config in self.properties:
+ if config.isParentRef == 1:
+ stream.write (", ::qpid::management::Manageable* _parent")
+ return
+
+ def genParentRefAssignment (self, stream, variables):
+ for config in self.properties:
+ if config.isParentRef == 1:
+ stream.write (config.getName () + \
+ " = _parent->GetManagementObject ()->getObjectId ();")
+ return
+
+ def genSchemaMD5 (self, stream, variables):
+ sum = self.hash.getDigest()
+ for idx in range (len (sum)):
+ if idx != 0:
+ stream.write (",")
+ stream.write (hex (ord (sum[idx])))
+
+ def genAssign (self, stream, variables):
+ for inst in self.statistics:
+ if not inst.type.type.perThread:
+ inst.genAssign (stream)
+
+ def genPerThreadAssign (self, stream, variables):
+ for inst in self.statistics:
+ if inst.type.type.perThread:
+ inst.genAssign (stream)
+
+ def genSizeProperties (self, stream, variables):
+ for prop in self.properties:
+ prop.genSize (stream)
+
+ def genReadProperties (self, stream, variables):
+ for prop in self.properties:
+ prop.genRead (stream)
+
+ def genWriteProperties (self, stream, variables):
+ for prop in self.properties:
+ prop.genWrite (stream)
+
+ def genWriteStatistics (self, stream, variables):
+ for stat in self.statistics:
+ stat.genWrite (stream)
+
+ def genMapEncodeProperties(self, stream, variables):
+ for prop in self.properties:
+ prop.genMap (stream)
+
+ def genMapEncodeStatistics (self, stream, variables):
+ for stat in self.statistics:
+ stat.genMap (stream)
+
+ def genMapDecodeProperties (self, stream, variables):
+ for prop in self.properties:
+ prop.genUnmap (stream)
+
+class SchemaEventArgs:
+ def __init__(self, package, node, typespec, fragments, options):
+ self.packageName = package
+ self.options = options
+ self.args = {}
+
+ children = node.childNodes
+ for child in children:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'arg':
+ arg = SchemaArg(child, typespec)
+ self.args[arg.name] = arg
+ else:
+ raise Exception("Unknown tag '%s' in <eventArguments>" % child.nodeName)
+
+class SchemaPackage:
+ def __init__ (self, typefile, schemafile, options):
+
+ self.classes = []
+ self.fragments = []
+ self.typespec = TypeSpec (typefile)
+ self.eventArgSet = None
+ self.events = []
+
+ dom = parse (schemafile)
+ document = dom.documentElement
+ if document.tagName != 'schema':
+ raise ValueError ("Expected 'schema' node")
+ attrs = document.attributes
+ pname = attrs['package'].nodeValue
+ namelist = pname.split('.')
+ self.packageName = ".".join(namelist)
+
+ children = document.childNodes
+ for child in children:
+ if child.nodeType == Node.ELEMENT_NODE:
+ if child.nodeName == 'class':
+ cls = SchemaClass (self.packageName, child, self.typespec,
+ self.fragments, options)
+ self.classes.append (cls)
+
+ elif child.nodeName == 'group':
+ cls = SchemaClass (self.packageName, child, self.typespec,
+ self.fragments, options)
+ self.fragments.append (cls)
+
+ elif child.nodeName == 'eventArguments':
+ if self.eventArgSet:
+ raise Exception("Only one <eventArguments> may appear in a package")
+ self.eventArgSet = SchemaEventArgs(self.packageName, child, self.typespec, self.fragments, options)
+
+ elif child.nodeName == 'event':
+ event = SchemaEvent(self.packageName, child, self.typespec, self.eventArgSet)
+ self.events.append(event)
+
+ else:
+ raise ValueError ("Unknown schema tag '%s'" % child.nodeName)
+
+ def getPackageName (self):
+ return self.packageName
+
+ def getPackageNameCap (self):
+ return capitalize(self.packageName)
+
+ def getPackageNameLower (self):
+ return self.packageName.lower()
+
+ def getClasses (self):
+ return self.classes
+
+ def getEvents(self):
+ return self.events
+
+ def genAgentHeaderLocation (self, stream, variables):
+ stream.write(variables["agentHeaderDir"])
+
+ def genCloseNamespaces (self, stream, variables):
+ for item in self.packageName.split("."):
+ stream.write ("}")
+
+ def genNamespace (self, stream, variables):
+ stream.write("::".join(self.packageName.split(".")))
+
+ def genOpenNamespaces (self, stream, variables):
+ for item in self.packageName.split("."):
+ stream.write ("namespace %s {\n" % item)
+
+ def genPackageNameUpper (self, stream, variables):
+ up = "_".join(self.packageName.split("."))
+ stream.write (up.upper())
+
+ def genPackageName (self, stream, variables):
+ stream.write(self.packageName)
+
+ def genNamePackageLower (self, stream, variables):
+ stream.write (self.packageName.lower ())
+
+ def genClassIncludes (self, stream, variables):
+ for _class in self.classes:
+ stream.write ("#include \"")
+ _class.genNameCap (stream, variables)
+ stream.write (".h\"\n")
+ for _event in self.events:
+ stream.write ("#include \"Event")
+ _event.genNameCap(stream, variables)
+ stream.write (".h\"\n")
+
+ def genClassRegisters(self, stream, variables):
+ for _class in self.classes:
+ stream.write(" ")
+ _class.genNameCap(stream, variables)
+ stream.write("::registerSelf(agent);\n")
+ for _event in self.events:
+ stream.write(" Event")
+ _event.genNameCap(stream, variables)
+ stream.write("::registerSelf(agent);\n")
+
+ def genV2ClassMembers(self, stream, variables):
+ for _class in self.classes:
+ stream.write(" ::qmf::Schema data_%s;\n" % _class.name)
+ for _event in self.events:
+ stream.write(" ::qmf::Schema event_%s;\n" % _event.name)
+
+ def genV2ClassDefines(self, stream, variables):
+ for _class in self.classes:
+ stream.write("\n //\n // Data: %s\n //\n" % _class.name)
+ stream.write(" data_%s = qmf::Schema(SCHEMA_TYPE_DATA, package, \"%s\");\n" % (_class.name, _class.name))
+
+ for prop in _class.properties:
+ typeName, subType = self.qmfv2Type(prop.type)
+ access = self.qmfv2Access(prop.access)
+ stream.write(" {\n")
+ stream.write(" qmf::SchemaProperty prop(\"%s\", %s);\n" % (prop.name, typeName))
+ if subType:
+ stream.write(" prop.setSubtype(\"%s\");\n" % subType)
+ stream.write(" prop.setAccess(%s);\n" % access)
+ if prop.isIndex == 1:
+ stream.write(" prop.setIndex(true);\n")
+ if prop.isOptional == 1:
+ stream.write(" prop.setOptional(true);\n")
+ if prop.unit:
+ stream.write(" prop.setUnit(\"%s\");\n" % prop.unit)
+ if prop.desc:
+ stream.write(" prop.setDesc(\"%s\");\n" % prop.desc)
+ stream.write(" data_%s.addProperty(prop);\n" % _class.name)
+ stream.write(" }\n\n")
+
+ for stat in _class.statistics:
+ typeName, subType = self.qmfv2Type(stat.type)
+ stream.write(" {\n")
+ stream.write(" qmf::SchemaProperty prop(\"%s\", %s);\n" % (stat.name, typeName))
+ if subType:
+ stream.write(" prop.setSubtype(\"%s\");\n" % subType)
+ if stat.unit:
+ stream.write(" prop.setUnit(\"%s\");\n" % stat.unit)
+ if stat.desc:
+ stream.write(" prop.setDesc(\"%s\");\n" % stat.desc)
+ stream.write(" data_%s.addProperty(prop);\n" % _class.name)
+ stream.write(" }\n\n")
+
+ for method in _class.methods:
+ stream.write(" {\n")
+ stream.write(" qmf::SchemaMethod method(\"%s\");\n" % method.name)
+ if method.desc:
+ stream.write(" method.setDesc(\"%s\");\n" % method.desc)
+
+ for arg in method.args:
+ typeName, subType = self.qmfv2Type(arg.type)
+ stream.write(" {\n")
+ stream.write(" qmf::SchemaProperty arg(\"%s\", %s);\n" % (arg.name, typeName))
+ if subType:
+ stream.write(" arg.setSubtype(\"%s\");\n" % subType)
+ if arg.unit:
+ stream.write(" arg.setUnit(\"%s\");\n" % arg.unit)
+ if arg.desc:
+ stream.write(" arg.setDesc(\"%s\");\n" % arg.desc)
+ stream.write(" arg.setDirection(%s);\n" % self.qmfv2Dir(arg.dir))
+ stream.write(" method.addArgument(arg);\n")
+ stream.write(" }\n\n")
+
+ stream.write(" data_%s.addMethod(method);\n" % _class.name)
+ stream.write(" }\n\n")
+
+ stream.write(" session.registerSchema(data_%s);\n" % _class.name)
+
+ for _event in self.events:
+ stream.write("\n //\n // Event: %s\n //\n" % _event.name)
+ stream.write(" event_%s = qmf::Schema(SCHEMA_TYPE_EVENT, package, \"%s\");\n" % (_event.name, _event.name))
+ stream.write(" event_%s.setDefaultSeverity(%s);\n" % (_event.name, self.qmfv2Severity(_event.sev)))
+ for prop in _event.args:
+ typeName, subType = self.qmfv2Type(prop.type)
+ stream.write(" {\n")
+ stream.write(" qmf::SchemaProperty prop(\"%s\", %s);\n" % (prop.name, typeName))
+ if subType:
+ stream.write(" prop.setSubtype(\"%s\");\n" % subType)
+ if prop.unit:
+ stream.write(" prop.setUnit(\"%s\");\n" % prop.unit)
+ if prop.desc:
+ stream.write(" prop.setDesc(\"%s\");\n" % prop.desc)
+ stream.write(" event_%s.addProperty(prop);\n" % _event.name)
+ stream.write(" }\n\n")
+
+ stream.write(" session.registerSchema(event_%s);\n" % _event.name)
+
+
+ def qmfv2Type(self, typecode):
+ base = typecode.type.base
+ if base == "REF" : return ("qmf::SCHEMA_DATA_MAP", "reference")
+ if base == "U8" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "U16" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "U32" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "U64" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "S8" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "S16" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "S32" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "S64" : return ("qmf::SCHEMA_DATA_INT", None)
+ if base == "BOOL" : return ("qmf::SCHEMA_DATA_BOOL", None)
+ if base == "SSTR" : return ("qmf::SCHEMA_DATA_STRING", None)
+ if base == "LSTR" : return ("qmf::SCHEMA_DATA_STRING", None)
+ if base == "ABSTIME" : return ("qmf::SCHEMA_DATA_INT", "abstime")
+ if base == "DELTATIME" : return ("qmf::SCHEMA_DATA_INT", "deltatime")
+ if base == "FLOAT" : return ("qmf::SCHEMA_DATA_FLOAT", None)
+ if base == "DOUBLE" : return ("qmf::SCHEMA_DATA_FLOAT", None)
+ if base == "UUID" : return ("qmf::SCHEMA_DATA_UUID", None)
+ if base == "FTABLE" : return ("qmf::SCHEMA_DATA_MAP", None)
+ if base == "LIST" : return ("qmf::SCHEMA_DATA_LIST", None)
+ raise ValueError("Unknown base type %s" % base)
+
+ def qmfv2Access(self, code):
+ if code == "RC": return "qmf::ACCESS_READ_CREATE"
+ if code == "RO": return "qmf::ACCESS_READ_ONLY"
+ if code == "RW": return "qmf::ACCESS_READ_WRITE"
+ raise ValueError("Unknown access type %s" % code)
+
+ def qmfv2Dir(self, code):
+ if code == "I" : return "qmf::DIR_IN"
+ if code == "O" : return "qmf::DIR_OUT"
+ if code == "IO": return "qmf::DIR_IN_OUT"
+ raise ValueError("Unknown direction type %s" % code)
+
+ def qmfv2Severity(self, code):
+ if code == 0 : return "qmf::SEV_EMERG"
+ if code == 1 : return "qmf::SEV_ALERT"
+ if code == 2 : return "qmf::SEV_CRIT"
+ if code == 3 : return "qmf::SEV_ERROR"
+ if code == 4 : return "qmf::SEV_WARN"
+ if code == 5 : return "qmf::SEV_NOTICE"
+ if code == 6 : return "qmf::SEV_INFORM"
+ if code == 7 : return "qmf::SEV_DEBUG"
+ raise ValueError("Out of Range Severity %d" % code)
+
+#=====================================================================================
+# Utility Functions
+#=====================================================================================
+
+# Create a valid C++ symbol from the input string so that it can be
+# used in generated C++ source. For instance, change "qpid.mgmt" to
+# "qpidMgmt".
+#
+# Input: Raw string (str) to process
+# Output: String (str) suitable for use as a C++ symbol
+#
+# Limitations: Currently, only strips periods ('.') from strings,
+# eventually should strip :'s and ,'s and ''s, oh my!
+def makeValidCppSymbol(input):
+ output = str()
+ capitalize = False
+
+ for char in input:
+ skip = False
+
+ if char == ".":
+ capitalize = True
+ skip = True
+
+ if not skip:
+ output += capitalize and char.upper() or char
+
+ capitalize = False
+
+ return output
+
+# Capitalize a string by /only/ forcing the first character to be
+# uppercase. The rest of the string is left alone. This is different
+# from str.capitalize(), which forces the first character to uppercase
+# and the rest to lowercase.
+#
+# Input: A string (str) to capitalize
+# Output: A string (str) with the first character as uppercase
+def capitalize(input):
+ return input[0].upper() + input[1:]
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Args.h b/qpid/cpp/managementgen/qmfgen/templates/Args.h
new file mode 100644
index 0000000000..89a5bec9b9
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Args.h
@@ -0,0 +1,40 @@
+/*MGEN:commentPrefix=//*/
+#ifndef _ARGS_/*MGEN:Method.NameUpper*/_
+#define _ARGS_/*MGEN:Method.NameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/Args.h"
+#include <string>
+
+namespace qmf {
+/*MGEN:Method.OpenNamespaces*/
+
+ class Args/*MGEN:Method.NameCamel*/ : public ::qpid::management::Args
+{
+ public:
+/*MGEN:Method.Arguments*/
+};
+
+}/*MGEN:Method.CloseNamespaces*/
+
+#endif /*!_ARGS_/*MGEN:Method.NameUpper*/_*/
diff --git a/qpid/cpp/managementgen/qmfgen/templates/CMakeLists.cmake b/qpid/cpp/managementgen/qmfgen/templates/CMakeLists.cmake
new file mode 100644
index 0000000000..d8a3b91b10
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/CMakeLists.cmake
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+/*MGEN:commentPrefix=#*/
+/*MGEN:Root.Disclaimer*/
+/*MGEN:IF(CMakeLists.QpidBroker)*/
+/*MGEN:mgenDir=${mgen_dir}*/
+/*MGEN:specDir=${qpid-cpp_SOURCE_DIR}/../specs*/
+
+set(mgen_generator /*MGEN:CMakeLists.GenSources*/)
+
+set(mgen_broker_cpp /*MGEN:CMakeLists.GenCppFiles*/)
+
+# Header file install rules.
+#/*MGEN:CMakeLists.HeaderInstalls*/
+#if GENERATE
+#$(srcdir)/managementgen.mk: $(mgen_generator)
+# $(mgen_cmd)
+#
+#$(mgen_generator):
+#endif
+#/*MGEN:ENDIF*/
+
+set(qmfgen_sources /*MGEN:CMakeLists.GeneratedFiles*/)
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Class.cpp b/qpid/cpp/managementgen/qmfgen/templates/Class.cpp
new file mode 100644
index 0000000000..fc0b9c8177
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Class.cpp
@@ -0,0 +1,339 @@
+/*MGEN:commentPrefix=//*/
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/Manageable.h"
+#include "qpid/management/Buffer.h"
+#include "qpid/types/Variant.h"
+#include "qpid/amqp_0_10/Codecs.h"
+#include "qpid//*MGEN:Class.AgentHeaderLocation*//ManagementAgent.h"
+#include "/*MGEN:Class.NameCap*/.h"
+/*MGEN:Class.MethodArgIncludes*/
+#include <iostream>
+#include <sstream>
+
+using namespace qmf::/*MGEN:Class.Namespace*/;
+using qpid::management::ManagementAgent;
+using qpid::management::Manageable;
+using qpid::management::ManagementObject;
+using qpid::management::Args;
+using qpid::management::Mutex;
+using std::string;
+
+string /*MGEN:Class.NameCap*/::packageName = string ("/*MGEN:Class.NamePackageLower*/");
+string /*MGEN:Class.NameCap*/::className = string ("/*MGEN:Class.NameLower*/");
+uint8_t /*MGEN:Class.NameCap*/::md5Sum[MD5_LEN] =
+ {/*MGEN:Class.SchemaMD5*/};
+
+/*MGEN:Class.NameCap*/::/*MGEN:Class.NameCap*/ (ManagementAgent*, Manageable* _core/*MGEN:Class.ParentArg*//*MGEN:Class.ConstructorArgs*/) :
+ ManagementObject(_core)/*MGEN:Class.ConstructorInits*/
+{
+ /*MGEN:Class.ParentRefAssignment*/
+/*MGEN:Class.InitializeElements*/
+/*MGEN:IF(Class.ExistOptionals)*/
+ // Optional properties start out not-present
+ for (uint8_t idx = 0; idx < /*MGEN:Class.PresenceMaskBytes*/; idx++)
+ presenceMask[idx] = 0;
+/*MGEN:ENDIF*/
+/*MGEN:IF(Class.ExistPerThreadStats)*/
+ perThreadStatsArray = new struct PerThreadStats*[maxThreads];
+ for (int idx = 0; idx < maxThreads; idx++)
+ perThreadStatsArray[idx] = 0;
+/*MGEN:ENDIF*/
+}
+
+/*MGEN:Class.NameCap*/::~/*MGEN:Class.NameCap*/ ()
+{
+/*MGEN:IF(Class.ExistPerThreadStats)*/
+ for (int idx = 0; idx < maxThreads; idx++)
+ if (perThreadStatsArray[idx] != 0)
+ delete perThreadStatsArray[idx];
+ delete[] perThreadStatsArray;
+/*MGEN:ENDIF*/
+}
+
+namespace {
+ const string NAME("name");
+ const string TYPE("type");
+ const string ACCESS("access");
+ const string IS_INDEX("index");
+ const string IS_OPTIONAL("optional");
+ const string UNIT("unit");
+ const string MIN("min");
+ const string MAX("max");
+ const string MAXLEN("maxlen");
+ const string DESC("desc");
+ const string ARGCOUNT("argCount");
+ const string ARGS("args");
+ const string DIR("dir");
+ const string DEFAULT("default");
+}
+
+void /*MGEN:Class.NameCap*/::registerSelf(ManagementAgent* agent)
+{
+ agent->registerClass(packageName, className, md5Sum, writeSchema);
+}
+
+void /*MGEN:Class.NameCap*/::writeSchema (std::string& schema)
+{
+ const int _bufSize=65536;
+ char _msgChars[_bufSize];
+ ::qpid::management::Buffer buf(_msgChars, _bufSize);
+ ::qpid::types::Variant::Map ft;
+
+ // Schema class header:
+ buf.putOctet (CLASS_KIND_TABLE);
+ buf.putShortString (packageName); // Package Name
+ buf.putShortString (className); // Class Name
+ buf.putBin128 (md5Sum); // Schema Hash
+ buf.putShort (/*MGEN:Class.ConfigCount*/); // Config Element Count
+ buf.putShort (/*MGEN:Class.InstCount*/); // Inst Element Count
+ buf.putShort (/*MGEN:Class.MethodCount*/); // Method Count
+
+ // Properties
+/*MGEN:Class.PropertySchema*/
+ // Statistics
+/*MGEN:Class.StatisticSchema*/
+ // Methods
+/*MGEN:Class.MethodSchema*/
+ {
+ uint32_t _len = buf.getPosition();
+ buf.reset();
+ buf.getRawData(schema, _len);
+ }
+}
+
+/*MGEN:IF(Class.ExistPerThreadStats)*/
+void /*MGEN:Class.NameCap*/::aggregatePerThreadStats(struct PerThreadStats* totals) const
+{
+/*MGEN:Class.InitializeTotalPerThreadStats*/
+ for (int idx = 0; idx < maxThreads; idx++) {
+ struct PerThreadStats* threadStats = perThreadStatsArray[idx];
+ if (threadStats != 0) {
+/*MGEN:Class.AggregatePerThreadStats*/
+ }
+ }
+}
+/*MGEN:ENDIF*/
+
+/*MGEN:IF(Root.GenQMFv1)*/
+uint32_t /*MGEN:Class.NameCap*/::writePropertiesSize() const
+{
+ uint32_t size = writeTimestampsSize();
+/*MGEN:IF(Class.ExistOptionals)*/
+ size += /*MGEN:Class.PresenceMaskBytes*/;
+/*MGEN:ENDIF*/
+/*MGEN:Class.SizeProperties*/
+ return size;
+}
+
+void /*MGEN:Class.NameCap*/::readProperties (const std::string& _sBuf)
+{
+ char *_tmpBuf = new char[_sBuf.length()];
+ memcpy(_tmpBuf, _sBuf.data(), _sBuf.length());
+ ::qpid::management::Buffer buf(_tmpBuf, _sBuf.length());
+ Mutex::ScopedLock mutex(accessLock);
+
+ {
+ std::string _tbuf;
+ buf.getRawData(_tbuf, writeTimestampsSize());
+ readTimestamps(_tbuf);
+ }
+
+/*MGEN:IF(Class.ExistOptionals)*/
+ for (uint8_t idx = 0; idx < /*MGEN:Class.PresenceMaskBytes*/; idx++)
+ presenceMask[idx] = buf.getOctet();
+/*MGEN:ENDIF*/
+/*MGEN:Class.ReadProperties*/
+
+ delete [] _tmpBuf;
+}
+
+void /*MGEN:Class.NameCap*/::writeProperties (std::string& _sBuf) const
+{
+ const int _bufSize=65536;
+ char _msgChars[_bufSize];
+ ::qpid::management::Buffer buf(_msgChars, _bufSize);
+
+ Mutex::ScopedLock mutex(accessLock);
+ configChanged = false;
+
+ {
+ std::string _tbuf;
+ writeTimestamps(_tbuf);
+ buf.putRawData(_tbuf);
+ }
+
+
+/*MGEN:IF(Class.ExistOptionals)*/
+ for (uint8_t idx = 0; idx < /*MGEN:Class.PresenceMaskBytes*/; idx++)
+ buf.putOctet(presenceMask[idx]);
+/*MGEN:ENDIF*/
+/*MGEN:Class.WriteProperties*/
+
+ uint32_t _bufLen = buf.getPosition();
+ buf.reset();
+
+ buf.getRawData(_sBuf, _bufLen);
+}
+
+void /*MGEN:Class.NameCap*/::writeStatistics (std::string& _sBuf, bool skipHeaders)
+{
+ const int _bufSize=65536;
+ char _msgChars[_bufSize];
+ ::qpid::management::Buffer buf(_msgChars, _bufSize);
+
+ Mutex::ScopedLock mutex(accessLock);
+ instChanged = false;
+/*MGEN:IF(Class.ExistPerThreadAssign)*/
+ for (int idx = 0; idx < maxThreads; idx++) {
+ struct PerThreadStats* threadStats = perThreadStatsArray[idx];
+ if (threadStats != 0) {
+/*MGEN:Class.PerThreadAssign*/
+ }
+ }
+/*MGEN:ENDIF*/
+/*MGEN:IF(Class.ExistPerThreadStats)*/
+ struct PerThreadStats totals;
+ aggregatePerThreadStats(&totals);
+/*MGEN:ENDIF*/
+/*MGEN:Class.Assign*/
+ if (!skipHeaders) {
+ std::string _tbuf;
+ writeTimestamps (_tbuf);
+ buf.putRawData(_tbuf);
+ }
+
+/*MGEN:Class.WriteStatistics*/
+
+ // Maintenance of hi-lo statistics
+/*MGEN:Class.HiLoStatResets*/
+/*MGEN:IF(Class.ExistPerThreadResets)*/
+ for (int idx = 0; idx < maxThreads; idx++) {
+ struct PerThreadStats* threadStats = perThreadStatsArray[idx];
+ if (threadStats != 0) {
+/*MGEN:Class.PerThreadHiLoStatResets*/
+ }
+ }
+/*MGEN:ENDIF*/
+
+ uint32_t _bufLen = buf.getPosition();
+ buf.reset();
+
+ buf.getRawData(_sBuf, _bufLen);
+}
+
+void /*MGEN:Class.NameCap*/::doMethod (/*MGEN:Class.DoMethodArgs*/)
+{
+ Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD;
+ std::string text;
+
+ bool _matched = false;
+
+ const int _bufSize=65536;
+ char _msgChars[_bufSize];
+ ::qpid::management::Buffer outBuf(_msgChars, _bufSize);
+
+/*MGEN:Class.MethodHandlers*/
+
+ if (!_matched) {
+ outBuf.putLong(status);
+ outBuf.putShortString(Manageable::StatusText(status, text));
+ }
+
+ uint32_t _bufLen = outBuf.getPosition();
+ outBuf.reset();
+
+ outBuf.getRawData(outStr, _bufLen);
+}
+/*MGEN:ENDIF*/
+std::string /*MGEN:Class.NameCap*/::getKey() const
+{
+ std::stringstream key;
+
+/*MGEN:Class.PrimaryKey*/
+ return key.str();
+}
+
+
+
+void /*MGEN:Class.NameCap*/::mapEncodeValues (::qpid::types::Variant::Map& _map,
+ bool includeProperties,
+ bool includeStatistics)
+{
+ using namespace ::qpid::types;
+ Mutex::ScopedLock mutex(accessLock);
+
+ if (includeProperties) {
+ configChanged = false;
+/*MGEN:Class.MapEncodeProperties*/
+ }
+
+ if (includeStatistics) {
+ instChanged = false;
+/*MGEN:IF(Class.ExistPerThreadAssign)*/
+ for (int idx = 0; idx < maxThreads; idx++) {
+ struct PerThreadStats* threadStats = perThreadStatsArray[idx];
+ if (threadStats != 0) {
+/*MGEN:Class.PerThreadAssign*/
+ }
+ }
+/*MGEN:ENDIF*/
+/*MGEN:IF(Class.ExistPerThreadStats)*/
+ struct PerThreadStats totals;
+ aggregatePerThreadStats(&totals);
+/*MGEN:ENDIF*/
+/*MGEN:Class.Assign*/
+
+/*MGEN:Class.MapEncodeStatistics*/
+
+ // Maintenance of hi-lo statistics
+/*MGEN:Class.HiLoStatResets*/
+/*MGEN:IF(Class.ExistPerThreadResets)*/
+ for (int idx = 0; idx < maxThreads; idx++) {
+ struct PerThreadStats* threadStats = perThreadStatsArray[idx];
+ if (threadStats != 0) {
+/*MGEN:Class.PerThreadHiLoStatResets*/
+ }
+ }
+/*MGEN:ENDIF*/
+ }
+}
+
+void /*MGEN:Class.NameCap*/::mapDecodeValues (const ::qpid::types::Variant::Map& _map)
+{
+ ::qpid::types::Variant::Map::const_iterator _i;
+ Mutex::ScopedLock mutex(accessLock);
+/*MGEN:IF(Class.ExistOptionals)*/
+ bool _found;
+/*MGEN:ENDIF*/
+/*MGEN:Class.MapDecodeProperties*/
+}
+
+void /*MGEN:Class.NameCap*/::doMethod (/*MGEN:Class.DoMapMethodArgs*/)
+{
+ Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD;
+ std::string text;
+
+/*MGEN:Class.MapMethodHandlers*/
+ outMap["_status_code"] = (uint32_t) status;
+ outMap["_status_text"] = Manageable::StatusText(status, text);
+}
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Class.h b/qpid/cpp/managementgen/qmfgen/templates/Class.h
new file mode 100644
index 0000000000..4bcd423a26
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Class.h
@@ -0,0 +1,122 @@
+/*MGEN:commentPrefix=//*/
+#ifndef _MANAGEMENT_/*MGEN:Class.NameUpper*/_
+#define _MANAGEMENT_/*MGEN:Class.NameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/ManagementObject.h"
+
+namespace qpid {
+ namespace management {
+ class ManagementAgent;
+ }
+}
+
+namespace qmf {
+/*MGEN:Class.OpenNamespaces*/
+
+class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject
+{
+ private:
+
+ static std::string packageName;
+ static std::string className;
+ static uint8_t md5Sum[MD5_LEN];
+/*MGEN:IF(Class.ExistOptionals)*/
+ uint8_t presenceMask[/*MGEN:Class.PresenceMaskBytes*/];
+/*MGEN:Class.PresenceMaskConstants*/
+/*MGEN:ENDIF*/
+
+ // Properties
+/*MGEN:Class.ConfigDeclarations*/
+ // Statistics
+/*MGEN:Class.InstDeclarations*/
+/*MGEN:IF(Class.ExistPerThreadStats)*/
+ // Per-Thread Statistics
+ struct PerThreadStats {
+/*MGEN:Class.PerThreadDeclarations*/
+ };
+
+ struct PerThreadStats** perThreadStatsArray;
+
+ inline struct PerThreadStats* getThreadStats() {
+ int idx = getThreadIndex();
+ struct PerThreadStats* threadStats = perThreadStatsArray[idx];
+ if (threadStats == 0) {
+ threadStats = new(PerThreadStats);
+ perThreadStatsArray[idx] = threadStats;
+/*MGEN:Class.InitializePerThreadElements*/
+ }
+ return threadStats;
+ }
+
+ void aggregatePerThreadStats(struct PerThreadStats*) const;
+/*MGEN:ENDIF*/
+ public:
+ static void writeSchema(std::string& schema);
+ void mapEncodeValues(::qpid::types::Variant::Map& map,
+ bool includeProperties=true,
+ bool includeStatistics=true);
+ void mapDecodeValues(const ::qpid::types::Variant::Map& map);
+ void doMethod(std::string& methodName,
+ const ::qpid::types::Variant::Map& inMap,
+ ::qpid::types::Variant::Map& outMap,
+ const std::string& userId);
+ std::string getKey() const;
+/*MGEN:IF(Root.GenQMFv1)*/
+ uint32_t writePropertiesSize() const;
+ void readProperties(const std::string& buf);
+ void writeProperties(std::string& buf) const;
+ void writeStatistics(std::string& buf, bool skipHeaders = false);
+ void doMethod(std::string& methodName,
+ const std::string& inBuf,
+ std::string& outBuf,
+ const std::string& userId);
+/*MGEN:ENDIF*/
+
+ writeSchemaCall_t getWriteSchemaCall() { return writeSchema; }
+/*MGEN:IF(Class.NoStatistics)*/
+ // Stub for getInstChanged. There are no statistics in this class.
+ bool getInstChanged() { return false; }
+ bool hasInst() { return false; }
+/*MGEN:ENDIF*/
+
+ /*MGEN:Class.NameCap*/(::qpid::management::ManagementAgent* agent,
+ ::qpid::management::Manageable* coreObject/*MGEN:Class.ParentArg*//*MGEN:Class.ConstructorArgs*/);
+ ~/*MGEN:Class.NameCap*/();
+
+ /*MGEN:Class.SetGeneralReferenceDeclaration*/
+
+ static void registerSelf(::qpid::management::ManagementAgent* agent);
+ std::string& getPackageName() const { return packageName; }
+ std::string& getClassName() const { return className; }
+ uint8_t* getMd5Sum() const { return md5Sum; }
+
+ // Method IDs
+/*MGEN:Class.MethodIdDeclarations*/
+ // Accessor Methods
+/*MGEN:Class.AccessorMethods*/
+};
+
+}/*MGEN:Class.CloseNamespaces*/
+
+#endif /*!_MANAGEMENT_/*MGEN:Class.NameUpper*/_*/
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Event.cpp b/qpid/cpp/managementgen/qmfgen/templates/Event.cpp
new file mode 100644
index 0000000000..a8fdd0bd92
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Event.cpp
@@ -0,0 +1,101 @@
+/*MGEN:commentPrefix=//*/
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/Manageable.h"
+#include "qpid/management/Buffer.h"
+#include "qpid/types/Variant.h"
+#include "qpid/amqp_0_10/Codecs.h"
+#include "qpid//*MGEN:Event.AgentHeaderLocation*//ManagementAgent.h"
+#include "Event/*MGEN:Event.NameCap*/.h"
+
+using namespace qmf::/*MGEN:Event.Namespace*/;
+using qpid::management::ManagementAgent;
+using qpid::management::Manageable;
+using qpid::management::ManagementObject;
+using qpid::management::Args;
+using qpid::management::Mutex;
+using std::string;
+
+string Event/*MGEN:Event.NameCap*/::packageName = string ("/*MGEN:Event.NamePackageLower*/");
+string Event/*MGEN:Event.NameCap*/::eventName = string ("/*MGEN:Event.Name*/");
+uint8_t Event/*MGEN:Event.NameCap*/::md5Sum[16] =
+ {/*MGEN:Event.SchemaMD5*/};
+
+Event/*MGEN:Event.NameCap*/::Event/*MGEN:Event.NameCap*/ (/*MGEN:Event.ConstructorArgs*/) :
+ /*MGEN:Event.ConstructorInits*/
+{}
+
+namespace {
+ const string NAME("name");
+ const string TYPE("type");
+ const string DESC("desc");
+ const string ARGCOUNT("argCount");
+ const string ARGS("args");
+}
+
+void Event/*MGEN:Event.NameCap*/::registerSelf(ManagementAgent* agent)
+{
+ agent->registerEvent(packageName, eventName, md5Sum, writeSchema);
+}
+
+void Event/*MGEN:Event.NameCap*/::writeSchema (std::string& schema)
+{
+ const int _bufSize = 65536;
+ char _msgChars[_bufSize];
+ ::qpid::management::Buffer buf(_msgChars, _bufSize);
+ ::qpid::types::Variant::Map ft;
+
+ // Schema class header:
+ buf.putOctet (CLASS_KIND_EVENT);
+ buf.putShortString (packageName); // Package Name
+ buf.putShortString (eventName); // Event Name
+ buf.putBin128 (md5Sum); // Schema Hash
+ buf.putShort (/*MGEN:Event.ArgCount*/); // Argument Count
+
+ // Arguments
+/*MGEN:Event.ArgSchema*/
+ {
+ uint32_t _len = buf.getPosition();
+ buf.reset();
+ buf.getRawData(schema, _len);
+ }
+}
+
+void Event/*MGEN:Event.NameCap*/::encode(std::string& _sBuf) const
+{
+ const int _bufSize=65536;
+ char _msgChars[_bufSize];
+ ::qpid::management::Buffer buf(_msgChars, _bufSize);
+
+/*MGEN:Event.ArgEncodes*/
+
+ uint32_t _bufLen = buf.getPosition();
+ buf.reset();
+
+ buf.getRawData(_sBuf, _bufLen);
+}
+
+void Event/*MGEN:Event.NameCap*/::mapEncode(::qpid::types::Variant::Map& map) const
+{
+ using namespace ::qpid::types;
+/*MGEN:Event.ArgMap*/
+}
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Event.h b/qpid/cpp/managementgen/qmfgen/templates/Event.h
new file mode 100644
index 0000000000..4f912cf220
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Event.h
@@ -0,0 +1,58 @@
+/*MGEN:commentPrefix=//*/
+#ifndef _MANAGEMENT_/*MGEN:Event.NameUpper*/_
+#define _MANAGEMENT_/*MGEN:Event.NameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid/management/ManagementEvent.h"
+
+namespace qmf {
+/*MGEN:Event.OpenNamespaces*/
+
+class Event/*MGEN:Event.NameCap*/ : public ::qpid::management::ManagementEvent
+{
+ private:
+ static void writeSchema (std::string& schema);
+ static std::string packageName;
+ static std::string eventName;
+ static uint8_t md5Sum[MD5_LEN];
+
+/*MGEN:Event.ArgDeclarations*/
+
+ public:
+ writeSchemaCall_t getWriteSchemaCall(void) { return writeSchema; }
+
+ Event/*MGEN:Event.NameCap*/(/*MGEN:Event.ConstructorArgs*/);
+ ~Event/*MGEN:Event.NameCap*/() {};
+
+ static void registerSelf(::qpid::management::ManagementAgent* agent);
+ std::string& getPackageName() const { return packageName; }
+ std::string& getEventName() const { return eventName; }
+ uint8_t* getMd5Sum() const { return md5Sum; }
+ uint8_t getSeverity() const { return /*MGEN:Event.Severity*/; }
+ void encode(std::string& buffer) const;
+ void mapEncode(::qpid::types::Variant::Map& map) const;
+};
+
+}/*MGEN:Event.CloseNamespaces*/
+
+#endif /*!_MANAGEMENT_/*MGEN:Event.NameUpper*/_*/
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Makefile.mk b/qpid/cpp/managementgen/qmfgen/templates/Makefile.mk
new file mode 100644
index 0000000000..b9adb4a2d2
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Makefile.mk
@@ -0,0 +1,40 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+/*MGEN:commentPrefix=#*/
+/*MGEN:Root.Disclaimer*/
+/*MGEN:IF(Makefile.QpidBroker)*/
+/*MGEN:mgenDir=$(mgen_dir)*/
+/*MGEN:specDir=$(top_srcdir)/../specs*/
+
+mgen_generator=/*MGEN:Makefile.GenSources*/
+
+mgen_broker_cpp=/*MGEN:Makefile.GenCppFiles*/
+
+# Header file install rules.
+/*MGEN:Makefile.HeaderInstalls*/
+if GENERATE
+$(srcdir)/managementgen.mk: $(mgen_generator)
+ $(mgen_cmd)
+
+$(mgen_generator):
+endif
+/*MGEN:ENDIF*/
+
+qmfgen_sources=/*MGEN:Makefile.GeneratedFiles*/
+
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Package.cpp b/qpid/cpp/managementgen/qmfgen/templates/Package.cpp
new file mode 100644
index 0000000000..f6bd7f4654
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Package.cpp
@@ -0,0 +1,32 @@
+/*MGEN:commentPrefix=//*/
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "Package.h"
+/*MGEN:Schema.ClassIncludes*/
+
+using namespace qmf::/*MGEN:Schema.Namespace*/;
+
+Package::Package (::qpid::management::ManagementAgent* agent)
+{
+/*MGEN:Schema.ClassRegisters*/
+}
+
diff --git a/qpid/cpp/managementgen/qmfgen/templates/Package.h b/qpid/cpp/managementgen/qmfgen/templates/Package.h
new file mode 100644
index 0000000000..569c7cfb33
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/Package.h
@@ -0,0 +1,41 @@
+/*MGEN:commentPrefix=//*/
+#ifndef _MANAGEMENT_PACKAGE_/*MGEN:Schema.PackageNameUpper*/_
+#define _MANAGEMENT_PACKAGE_/*MGEN:Schema.PackageNameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "qpid//*MGEN:Class.AgentHeaderLocation*//ManagementAgent.h"
+
+namespace qmf {
+/*MGEN:Class.OpenNamespaces*/
+
+class Package
+{
+ public:
+ Package (::qpid::management::ManagementAgent* agent);
+ ~Package () {}
+};
+
+}/*MGEN:Class.CloseNamespaces*/
+
+
+#endif /*!_MANAGEMENT_PACKAGE_/*MGEN:Schema.PackageNameUpper*/_*/
diff --git a/qpid/cpp/managementgen/qmfgen/templates/V2Package.cpp b/qpid/cpp/managementgen/qmfgen/templates/V2Package.cpp
new file mode 100644
index 0000000000..2b6e231fe9
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/V2Package.cpp
@@ -0,0 +1,37 @@
+/*MGEN:commentPrefix=//*/
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include "QmfPackage.h"
+#include <qmf/Schema.h>
+#include <qmf/SchemaProperty.h>
+#include <qmf/SchemaMethod.h>
+#include <string>
+
+using namespace std;
+using namespace qmf::/*MGEN:Schema.Namespace*/;
+
+void PackageDefinition::configure(::qmf::AgentSession& session)
+{
+ string package("/*MGEN:Schema.PackageName*/");
+/*MGEN:Schema.V2ClassDefines*/
+}
+
diff --git a/qpid/cpp/managementgen/qmfgen/templates/V2Package.h b/qpid/cpp/managementgen/qmfgen/templates/V2Package.h
new file mode 100644
index 0000000000..1d4f907ab3
--- /dev/null
+++ b/qpid/cpp/managementgen/qmfgen/templates/V2Package.h
@@ -0,0 +1,46 @@
+/*MGEN:commentPrefix=//*/
+#ifndef _QMF_PACKAGE_/*MGEN:Schema.PackageNameUpper*/_
+#define _QMF_PACKAGE_/*MGEN:Schema.PackageNameUpper*/_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+/*MGEN:Root.Disclaimer*/
+
+#include <qmf/AgentSession.h>
+#include <qmf/Schema.h>
+#include <qmf/Data.h>
+#include <qmf/DataAddr.h>
+
+namespace qmf {
+/*MGEN:Class.OpenNamespaces*/
+
+class PackageDefinition
+{
+ public:
+ ~PackageDefinition() {}
+ void configure(::qmf::AgentSession& session);
+
+/*MGEN:Schema.V2ClassMembers*/
+};
+
+}/*MGEN:Class.CloseNamespaces*/
+
+
+#endif /*!_QMF_PACKAGE_/*MGEN:Schema.PackageNameUpper*/_*/