modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/DefaultImportConfigurationDescriptor.java
| 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/ExportingInputStream.java
| 100 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationConstants.java
| 112 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationManagerBean.java
| 81 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
| 10
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
| 23
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
| 9
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java
| 534 ++++++++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
| 5
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtil.java
| 650 ++++++----
modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtilTest.java
| 212 +++
modules/helpers/perftest-support/data.sh
| 2
modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/Exporter.java
| 13
modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbsetup/DbSetup.java
| 15
modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbunit/EntityRelationshipFilter.java
| 98 +
modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/jpa/mapping/MappingTranslator.java
| 4
modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java
| 8
17 files changed, 1471 insertions(+), 407 deletions(-)
New commits:
commit 72430377515c26d205d7664485fcb69d19db14e4
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Sep 9 16:25:55 2011 +0200
BZ-735810 - make sure to reload the system config cache after its update.
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
index 86b690a..0dd0e72 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
@@ -269,8 +269,6 @@ public class SystemManagerBean implements SystemManagerLocal,
SystemManagerRemot
existingConfigMap.put(config.getPropertyKey(), config);
}
- Properties newCacheProperties = new Properties(); // create our own object - we
don't want to reuse the caller's
-
// verify each new setting and persist them to the database
// note that if a new setting is the same as the old one, we do nothing - leave
the old entity as is
for (Object key : properties.keySet()) {
@@ -281,8 +279,6 @@ public class SystemManagerBean implements SystemManagerLocal,
SystemManagerRemot
verifyNewSystemConfigurationProperty(name, value, properties);
}
- newCacheProperties.setProperty(name, value);
-
SystemConfiguration existingConfig = existingConfigMap.get(name);
if (existingConfig == null) {
existingConfig = new SystemConfiguration(name, value);
@@ -301,7 +297,11 @@ public class SystemManagerBean implements SystemManagerLocal,
SystemManagerRemot
}
}
- systemConfigurationCache = newCacheProperties;
+ //let the cache be reloaded once it's needed.
+ //we can't assume that the caller provided the full set of properties we
+ //have in the database, so let's just make sure we reinit the cache
+ //from there...
+ systemConfigurationCache = null;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
commit 23dbbe7d190dca3d25016ae0fdc0b833512ba806
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Sep 27 21:49:45 2011 +0200
Some amendments to the perftest-support database state export algorithms:
In case of no IDs specified from a table, explicitly read all the PK values from it.
Don't try to optimize using "load-all" flag, because it just doesn't
work well with figuring out relationships.
Some small optimizations to speed the slow data export process a little bit up.
Correctly handle @OneToOne
diff --git a/modules/helpers/perftest-support/data.sh
b/modules/helpers/perftest-support/data.sh
index e7cccdf..b69805f 100755
--- a/modules/helpers/perftest-support/data.sh
+++ b/modules/helpers/perftest-support/data.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-java -cp 'target/dependency/*':target/perftest-support-4.0.0-SNAPSHOT.jar
org.rhq.helpers.perftest.support.Main $@
+java $JAVA_OPTS -cp
'target/dependency/*':target/perftest-support-4.1.0-SNAPSHOT.jar
org.rhq.helpers.perftest.support.Main $@
diff --git
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/Exporter.java
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/Exporter.java
index e5cf3db..7e3c8fb 100644
---
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/Exporter.java
+++
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/Exporter.java
@@ -23,6 +23,8 @@ import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -36,6 +38,7 @@ import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.stream.DataSetProducerAdapter;
import org.dbunit.dataset.stream.IDataSetConsumer;
+
import org.rhq.helpers.perftest.support.config.Entity;
import org.rhq.helpers.perftest.support.config.ExportConfiguration;
import org.rhq.helpers.perftest.support.dbunit.DbUnitUtil;
@@ -104,16 +107,14 @@ public class Exporter {
Set<ColumnValues> ret = new HashSet<ColumnValues>();
- if (query == null) {
- return null;
- }
-
IDataSet data = connection.createDataSet(new String[] { table });
-
Column[] tablePks = data.getTableMetaData(table).getPrimaryKeys();
-
String pkName = tablePks[0].getColumnName();
+ if (query == null) {
+ query = "SELECT " + pkName + " FROM " + table;
+ }
+
//the connection shouldn't be closed here, because we're just reusing an
already existing one.
Connection jdbcConnection = connection.getConnection();
diff --git
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbsetup/DbSetup.java
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbsetup/DbSetup.java
index 3059c58..69ad14d 100644
---
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbsetup/DbSetup.java
+++
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbsetup/DbSetup.java
@@ -136,14 +136,17 @@ public class DbSetup {
private void setup() throws Exception {
DBSetup dbSetup = new DBSetup(connection);
- File schema = getFileFromResource(MINIMAL_VERSION_OF_SCHEMA,
getClass().getClassLoader());
-
+ File minimalSchema = getFileFromResource(MINIMAL_VERSION_OF_SCHEMA,
getClass().getClassLoader());
+ File currentSchema = getFileFromDbUtils("db-schema-combined.xml");
+
try {
- replaceTokensInFile(schema);
- dbSetup.uninstall(schema.getAbsolutePath());
- dbSetup.setup(schema.getAbsolutePath());
+ replaceTokensInFile(minimalSchema);
+ replaceTokensInFile(currentSchema);
+ dbSetup.uninstall(currentSchema.getAbsolutePath());
+ dbSetup.setup(minimalSchema.getAbsolutePath());
} finally {
- schema.delete();
+ minimalSchema.delete();
+ currentSchema.delete();
}
File data = getFileFromResource(MINIMAL_VERSION_OF_DATA,
getClass().getClassLoader());
diff --git
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbunit/EntityRelationshipFilter.java
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbunit/EntityRelationshipFilter.java
index 0d6bf9a..e21719c 100644
---
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbunit/EntityRelationshipFilter.java
+++
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/dbunit/EntityRelationshipFilter.java
@@ -23,6 +23,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -177,7 +178,9 @@ public class EntityRelationshipFilter extends DatabaseSequenceFilter
{
}
}
-
resolvedPks.getOrCreate(node.getTranslation().getTableName()).addAll(unresolvedPks);
+ if (unresolvedPks != null) {
+
resolvedPks.getOrCreate(node.getTranslation().getTableName()).addAll(unresolvedPks);
+ }
for (Edge e : node.getOutgoingEdges()) {
//only include the dependents if the relationship
@@ -271,6 +274,24 @@ public class EntityRelationshipFilter extends DatabaseSequenceFilter
{
}
}
+ //now translate the foreign keys into primary keys
+ //but first check if we even need to do it by comparing the column names
+ boolean columnsDiffer = false;
+ Set<String> pkColumns = new
HashSet<String>(Arrays.asList(edge.getTo().getTranslation().getPkColumns()));
+
+ for(String col : translation.getToColumns()) {
+ if (!pkColumns.contains(col)) {
+ columnsDiffer = true;
+ break;
+ }
+ }
+
+ if (columnsDiffer) {
+ columnValues =
+ getValuesFromTable(connection,
edge.getTo().getTranslation().getTableName(), edge.getTo()
+ .getTranslation().getPkColumns(),
removeValuesWithNullColumn(columnValues));
+ }
+
Set<ColumnValues> ret = getValuesFromTable(connection,
edge.getTo().getTranslation().getTableName(), edge
.getTo().getTranslation().getPkColumns(), columnValues);
@@ -299,11 +320,25 @@ public class EntityRelationshipFilter extends DatabaseSequenceFilter
{
}
}
- //now translate the foreign keys into primary keys
EntityTranslation fromTranslation = edge.getFrom().getTranslation();
- columnValues = getValuesFromTable(connection,
fromTranslation.getTableName(),
- fromTranslation.getPkColumns(),
removeValuesWithNullColumn(columnValues));
+ //now translate the foreign keys into primary keys
+ //but first check if we even need to do it by comparing the column names
+ boolean columnsDiffer = false;
+ Set<String> pkColumns = new
HashSet<String>(Arrays.asList(fromTranslation.getPkColumns()));
+
+ for(String col : translation.getFromColumns()) {
+ if (!pkColumns.contains(col)) {
+ columnsDiffer = true;
+ break;
+ }
+ }
+
+ if (columnsDiffer) {
+ columnValues = getValuesFromTable(connection,
fromTranslation.getTableName(),
+ fromTranslation.getPkColumns(),
removeValuesWithNullColumn(columnValues));
+ }
+
return removeValuesWithNullColumn(columnValues);
} else {
//only bother with one-to-many relationships. A many-to-many
@@ -408,47 +443,50 @@ public class EntityRelationshipFilter extends DatabaseSequenceFilter
{
private static Set<ColumnValues> getValuesFromTable(IDatabaseConnection
connection, String tableName,
String[] valueColumns, Set<ColumnValues> knownlColumns) throws SQLException
{
- //I know, doing this one by one is super lame, but prevents the 1000 IN clause
members limit of Oracle
- StringBuilder sqlCommon = new StringBuilder("SELECT
").append(colNamesToSql(valueColumns)).append(" FROM ")
+ StringBuilder sql = new StringBuilder("SELECT
").append(colNamesToSql(valueColumns)).append(" FROM ")
.append(tableName).append(" WHERE ");
Set<ColumnValues> ret = new HashSet<ColumnValues>();
-
+
for (ColumnValues cols : knownlColumns) {
- StringBuilder sql = new StringBuilder(sqlCommon);
+ sql.append("(");
for (ColumnValues.Column c : cols) {
sql.append(c.getName()).append(" = ? AND ");
}
- sql.replace(sql.length() - 4, sql.length(), "");
-
- PreparedStatement st = null;
- try {
- st = connection.getConnection().prepareStatement(sql.toString());
- int idx = 1;
+ sql.replace(sql.length() - 5, sql.length(), ") OR ");
+ }
+
+ sql.replace(sql.length() - 4, sql.length(), "");
+
+ PreparedStatement st = null;
+ try {
+ st = connection.getConnection().prepareStatement(sql.toString());
+ int idx = 1;
+ for (ColumnValues cols : knownlColumns) {
for (ColumnValues.Column c : cols) {
st.setObject(idx++, c.getValue());
}
+ }
+
+ ResultSet rs = st.executeQuery();
- ResultSet rs = st.executeQuery();
-
- ResultSetMetaData rsmd = rs.getMetaData();
-
- while (rs.next()) {
- ColumnValues vals = new ColumnValues();
+ ResultSetMetaData rsmd = rs.getMetaData();
- for (int i = 1; i <= rsmd.getColumnCount(); ++i) {
- String columnName = rsmd.getColumnName(i);
- Object value = rs.getObject(i);
- vals.add(columnName, value);
- }
+ while (rs.next()) {
+ ColumnValues vals = new ColumnValues();
- ret.add(vals);
- }
- } finally {
- if (st != null) {
- st.close();
+ for (int i = 1; i <= rsmd.getColumnCount(); ++i) {
+ String columnName = rsmd.getColumnName(i);
+ Object value = rs.getObject(i);
+ vals.add(columnName, value);
}
+
+ ret.add(vals);
+ }
+ } finally {
+ if (st != null) {
+ st.close();
}
}
diff --git
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/jpa/mapping/MappingTranslator.java
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/jpa/mapping/MappingTranslator.java
index 2d7f566..4a15734 100644
---
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/jpa/mapping/MappingTranslator.java
+++
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/jpa/mapping/MappingTranslator.java
@@ -304,8 +304,8 @@ public class MappingTranslator {
}
} else if (refCol.isEmpty()) {
//bidirectional with no referenced column definition.
- //the fkey is in the target table
- tCols[i] = fkey;
+ //the fkey is in the from table, referencing the pk in the target table
+ fCols[i] = fkey;
} else {
//bidirectional with referenced column definition.
//the fkey is in the from table, referencing the refCol
diff --git
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java
index 52d0565..c4c7b8a 100644
---
a/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java
+++
b/modules/helpers/perftest-support/src/main/java/org/rhq/helpers/perftest/support/testng/DatabaseSetupInterceptor.java
@@ -168,6 +168,12 @@ public class DatabaseSetupInterceptor implements
IInvokedMethodListener {
}
}
+/* Dropping the tables explicitly is a workaround around a problem in the perf tests
+ * but otherwise it should not be necessary at all.
+ * Even then, dropping the table in the beforeInvocation() should be enough and we
+ * shouldn't have to drop it again in the afterInvocation(). That is going to leave
+ * the database corrupted because it is going to miss this table altogether.
+ */
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
DatabaseState state = getRequiredDatabaseState(method);
@@ -202,7 +208,7 @@ public class DatabaseSetupInterceptor implements
IInvokedMethodListener {
}
-
+
/**
* Obtain the required database state by looking for the @DatabaseState annotation.
* Lookup is first done at method level and if not found done at class level.
commit 263a0f5cb9ba3eb562cc924460494f7f30757a8c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Sep 27 21:12:18 2011 +0200
Added support for using the import configuration specified in the export
file during import.
To achieve that the export file schema now includes a new
"configuration-instance" schema, which is a combination of the existing
configuration definition schema and an ability to specify values
conforming to that definition.
Added unit tests and refactored the constants from ExportingInputStream
into a separate file so that they are in a more logical place.
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/DefaultImportConfigurationDescriptor.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/DefaultImportConfigurationDescriptor.java
index 6b13150..f19aa18 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/DefaultImportConfigurationDescriptor.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/DefaultImportConfigurationDescriptor.java
@@ -28,7 +28,7 @@ import
org.rhq.enterprise.server.xmlschema.generated.configuration.instance.Conf
*
* @author Lukas Krejci
*/
-@XmlRootElement(name = "default-configuration", namespace =
ExportingInputStream.EXPORT_NAMESPACE)
+@XmlRootElement(name = "default-configuration", namespace =
SynchronizationConstants.EXPORT_NAMESPACE)
public class DefaultImportConfigurationDescriptor extends ConfigurationInstanceDescriptor
{
public DefaultImportConfigurationDescriptor() {
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/ExportingInputStream.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/ExportingInputStream.java
index 49dc6bf..19734f6 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/ExportingInputStream.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/ExportingInputStream.java
@@ -26,15 +26,11 @@ import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
-import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@@ -66,20 +62,6 @@ public class ExportingInputStream extends InputStream {
private static final Log LOG = LogFactory.getLog(ExportingInputStream.class);
- public static final String CONFIGURATION_NAMESPACE =
"urn:xmlns:rhq-configuration";
- public static final String EXPORT_NAMESPACE =
"urn:xmlns:rhq-configuration-export";
-
- public static final String CONFIGURATION_EXPORT_ELEMENT =
"configuration-export";
- public static final String ENTITIES_EXPORT_ELEMENT = "entities";
- public static final String ENTITY_EXPORT_ELEMENT = "entity";
- public static final String ERROR_MESSAGE_ELEMENT = "error-message";
- public static final String NOTES_ELEMENT = "notes";
- public static final String DATA_ELEMENT = "data";
- public static final String VALIDATOR_ELEMENT = "validator";
- public static final String DEFAULT_CONFIGURATION_ELEMENT =
"default-configuration";
- public static final String ID_ATTRIBUTE = "id";
- public static final String CLASS_ATTRIBUTE = "class";
-
private Set<Synchronizer<?, ?>> synchronizers;
private Map<String, ExporterMessages> messagesPerExporter;
private PipedInputStream inputStream;
@@ -255,67 +237,19 @@ public class ExportingInputStream extends InputStream {
* @throws XMLStreamException
*/
private void exportPrologue(XMLStreamWriter wrt) throws XMLStreamException {
- wrt.setDefaultNamespace(EXPORT_NAMESPACE);
- wrt.setPrefix(XMLConstants.DEFAULT_NS_PREFIX, EXPORT_NAMESPACE);
- wrt.setPrefix("ci",
ConfigurationInstanceDescriptorUtil.NS_CONFIGURATION_INSTANCE);
- wrt.setPrefix("c", CONFIGURATION_NAMESPACE);
+ wrt.setDefaultNamespace(SynchronizationConstants.EXPORT_NAMESPACE);
+ wrt.setPrefix(SynchronizationConstants.EXPORT_NAMESPACE_PREFIX,
SynchronizationConstants.EXPORT_NAMESPACE);
+ wrt.setPrefix(SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE_PREFIX,
SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE);
+ wrt.setPrefix(SynchronizationConstants.CONFIGURATION_NAMESPACE_PREFIX,
SynchronizationConstants.CONFIGURATION_NAMESPACE);
- NamespaceContext nsContext = new NamespaceContext() {
-
- //this map has to correspond to the namespaces defined in the code above
- private final Map<String, String> PREFIXES = new HashMap<String,
String>();
- {
- PREFIXES.put(XMLConstants.DEFAULT_NS_PREFIX, EXPORT_NAMESPACE);
- PREFIXES.put("ci",
ConfigurationInstanceDescriptorUtil.NS_CONFIGURATION_INSTANCE);
- PREFIXES.put("c", CONFIGURATION_NAMESPACE);
- }
-
- @Override
- public Iterator<String> getPrefixes(String namespaceURI) {
- String prefix = getPrefix(namespaceURI);
- if (prefix == null) {
- return Collections.<String> emptySet().iterator();
- } else {
- return Collections.singleton(prefix).iterator();
- }
- }
-
- @Override
- public String getPrefix(String namespaceURI) {
- if (namespaceURI == null) {
- throw new IllegalArgumentException();
- } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) {
- return XMLConstants.XMLNS_ATTRIBUTE;
- } else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) {
- return XMLConstants.XML_NS_PREFIX;
- } else {
- String prefix = null;
- for (Map.Entry<String, String> e : PREFIXES.entrySet()) {
- String p = e.getKey();
- String namespace = e.getValue();
-
- if (namespaceURI.equals(namespace)) {
- prefix = p;
- break;
- }
- }
-
- return prefix;
- }
- }
-
- @Override
- public String getNamespaceURI(String prefix) {
- return PREFIXES.get(prefix);
- }
- };
+ NamespaceContext nsContext =
SynchronizationConstants.createConfigurationExportNamespaceContext();
wrt.setNamespaceContext(nsContext);
wrt.writeStartDocument();
- wrt.writeStartElement(EXPORT_NAMESPACE, CONFIGURATION_EXPORT_ELEMENT);
- wrt.writeNamespace("ci",
ConfigurationInstanceDescriptorUtil.NS_CONFIGURATION_INSTANCE);
- wrt.writeNamespace("c", CONFIGURATION_NAMESPACE);
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.CONFIGURATION_EXPORT_ELEMENT);
+
wrt.writeNamespace(SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE_PREFIX,
ConfigurationInstanceDescriptorUtil.NS_CONFIGURATION_INSTANCE);
+ wrt.writeNamespace(SynchronizationConstants.CONFIGURATION_NAMESPACE_PREFIX,
SynchronizationConstants.CONFIGURATION_NAMESPACE);
writeValidators(wrt);
}
@@ -331,8 +265,8 @@ public class ExportingInputStream extends InputStream {
}
for (ConsistencyValidator cv : allValidators) {
- wrt.writeStartElement(VALIDATOR_ELEMENT);
- wrt.writeAttribute(CLASS_ATTRIBUTE, cv.getClass().getName());
+ wrt.writeStartElement(SynchronizationConstants.VALIDATOR_ELEMENT);
+ wrt.writeAttribute(SynchronizationConstants.CLASS_ATTRIBUTE,
cv.getClass().getName());
cv.exportState(new ExportWriter(wrt));
wrt.writeEndElement();
}
@@ -357,8 +291,8 @@ public class ExportingInputStream extends InputStream {
messagesPerExporter.put(syn.getClass().getName(), messages);
- wrt.writeStartElement(EXPORT_NAMESPACE, ENTITIES_EXPORT_ELEMENT);
- wrt.writeAttribute(ID_ATTRIBUTE, syn.getClass().getName());
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
+ wrt.writeAttribute(SynchronizationConstants.ID_ATTRIBUTE,
syn.getClass().getName());
Exporter<?, ?> exp = syn.getExporter();
ExportingIterator<?> it = exp.getExportingIterator();
@@ -379,9 +313,9 @@ public class ExportingInputStream extends InputStream {
while (it.hasNext()) {
it.next();
- wrt.writeStartElement(EXPORT_NAMESPACE, ENTITY_EXPORT_ELEMENT);
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.ENTITY_EXPORT_ELEMENT);
- wrt.writeStartElement(EXPORT_NAMESPACE, DATA_ELEMENT);
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.DATA_ELEMENT);
Exception exportError = null;
try {
@@ -400,14 +334,14 @@ public class ExportingInputStream extends InputStream {
if (notes != null) {
messages.getPerEntityNotes().add(notes);
- wrt.writeStartElement(EXPORT_NAMESPACE, NOTES_ELEMENT);
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.NOTES_ELEMENT);
wrt.writeCharacters(notes);
wrt.writeEndElement();
}
} else {
String message = ThrowableUtil.getStackAsString(exportError);
messages.getPerEntityErrorMessages().add(message);
- wrt.writeStartElement(EXPORT_NAMESPACE, ERROR_MESSAGE_ELEMENT);
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
wrt.writeCharacters(message);
wrt.writeEndElement();
}
@@ -420,7 +354,7 @@ public class ExportingInputStream extends InputStream {
messages.setExporterNotes(notes);
if (notes != null) {
- wrt.writeStartElement(EXPORT_NAMESPACE, NOTES_ELEMENT);
+ wrt.writeStartElement(SynchronizationConstants.EXPORT_NAMESPACE,
SynchronizationConstants.NOTES_ELEMENT);
wrt.writeCharacters(notes);
wrt.writeEndElement();
}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationConstants.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationConstants.java
new file mode 100644
index 0000000..c8be2dd
--- /dev/null
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationConstants.java
@@ -0,0 +1,112 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.sync;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+
+import org.rhq.enterprise.server.xmlschema.ConfigurationInstanceDescriptorUtil;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public final class SynchronizationConstants {
+
+ public static final String CONFIGURATION_NAMESPACE =
"urn:xmlns:rhq-configuration";
+ public static final String CONFIGURATION_NAMESPACE_PREFIX = "c";
+ public static final String CONFIGURATION_INSTANCE_NAMESPACE =
+ ConfigurationInstanceDescriptorUtil.NS_CONFIGURATION_INSTANCE;
+ public static final String CONFIGURATION_INSTANCE_NAMESPACE_PREFIX = "ci";
+ public static final String EXPORT_NAMESPACE =
"urn:xmlns:rhq-configuration-export";
+ public static final String EXPORT_NAMESPACE_PREFIX = XMLConstants.DEFAULT_NS_PREFIX;
+ public static final String CONFIGURATION_EXPORT_ELEMENT =
"configuration-export";
+ public static final String ENTITIES_EXPORT_ELEMENT = "entities";
+ public static final String ENTITY_EXPORT_ELEMENT = "entity";
+ public static final String ERROR_MESSAGE_ELEMENT = "error-message";
+ public static final String NOTES_ELEMENT = "notes";
+ public static final String DATA_ELEMENT = "data";
+ public static final String VALIDATOR_ELEMENT = "validator";
+ public static final String DEFAULT_CONFIGURATION_ELEMENT =
"default-configuration";
+ public static final String ID_ATTRIBUTE = "id";
+ public static final String CLASS_ATTRIBUTE = "class";
+
+ private SynchronizationConstants() {
+
+ }
+
+ public static NamespaceContext createConfigurationExportNamespaceContext() {
+ return new NamespaceContext() {
+
+ //this map has to correspond to the namespaces defined in the code above
+ private final Map<String, String> PREFIXES = new HashMap<String,
String>();
+ {
+ PREFIXES.put(EXPORT_NAMESPACE_PREFIX, EXPORT_NAMESPACE);
+ PREFIXES.put(CONFIGURATION_INSTANCE_NAMESPACE_PREFIX,
CONFIGURATION_INSTANCE_NAMESPACE);
+ PREFIXES.put(CONFIGURATION_NAMESPACE_PREFIX, CONFIGURATION_NAMESPACE);
+ }
+
+ @Override
+ public Iterator<String> getPrefixes(String namespaceURI) {
+ String prefix = getPrefix(namespaceURI);
+ if (prefix == null) {
+ return Collections.<String> emptySet().iterator();
+ } else {
+ return Collections.singleton(prefix).iterator();
+ }
+ }
+
+ @Override
+ public String getPrefix(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) {
+ return XMLConstants.XMLNS_ATTRIBUTE;
+ } else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) {
+ return XMLConstants.XML_NS_PREFIX;
+ } else {
+ String prefix = null;
+ for (Map.Entry<String, String> e : PREFIXES.entrySet()) {
+ String p = e.getKey();
+ String namespace = e.getValue();
+
+ if (namespaceURI.equals(namespace)) {
+ prefix = p;
+ break;
+ }
+ }
+
+ return prefix;
+ }
+ }
+
+ @Override
+ public String getNamespaceURI(String prefix) {
+ return PREFIXES.get(prefix);
+ }
+ };
+ }
+}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationManagerBean.java
index c036dd6..af848b1 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/sync/SynchronizationManagerBean.java
@@ -42,6 +42,9 @@ import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
@@ -66,6 +69,7 @@ import org.rhq.enterprise.server.sync.importers.ExportedEntityMatcher;
import org.rhq.enterprise.server.sync.importers.Importer;
import org.rhq.enterprise.server.sync.validators.ConsistencyValidator;
import org.rhq.enterprise.server.sync.validators.InconsistentStateException;
+import org.rhq.enterprise.server.xmlschema.ConfigurationInstanceDescriptorUtil;
/**
*
@@ -80,6 +84,16 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
+ private JAXBContext defaultImportConfigurationJAXBContext;
+
+ public SynchronizationManagerBean() {
+ try {
+ defaultImportConfigurationJAXBContext =
JAXBContext.newInstance(DefaultImportConfigurationDescriptor.class);
+ } catch (JAXBException e) {
+ throw new IllegalStateException("Failed to create
DefaultImportConfigurationDescriptor unmarshaller. This should never happen.");
+ }
+ }
+
@Override
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@RequiredPermission(Permission.MANAGE_INVENTORY)
@@ -241,9 +255,9 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
switch (rdr.next()) {
case XMLStreamConstants.START_ELEMENT:
String tagName = rdr.getName().getLocalPart();
- if (ExportingInputStream.VALIDATOR_ELEMENT.equals(tagName)) {
+ if (SynchronizationConstants.VALIDATOR_ELEMENT.equals(tagName)) {
ConsistencyValidator validator = null;
- String validatorClass = rdr.getAttributeValue(null,
ExportingInputStream.CLASS_ATTRIBUTE);
+ String validatorClass = rdr.getAttributeValue(null,
SynchronizationConstants.CLASS_ATTRIBUTE);
try {
validator = validateSingle(rdr, subject);
} catch (Exception e) {
@@ -253,10 +267,10 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
if (validator != null) {
executedValidators.add(validator);
}
- } else if
(ExportingInputStream.ENTITIES_EXPORT_ELEMENT.equals(tagName)) {
+ } else if
(SynchronizationConstants.ENTITIES_EXPORT_ELEMENT.equals(tagName)) {
//all the validators preceed the importers in the export file so
we can now check if the
//validator was already run
- String synchronizerClass = rdr.getAttributeValue(null,
ExportingInputStream.ID_ATTRIBUTE);
+ String synchronizerClass = rdr.getAttributeValue(null,
SynchronizationConstants.ID_ATTRIBUTE);
try {
failures.addAll(validateEntities(rdr, subject,
executedValidators));
} catch (Exception e) {
@@ -278,7 +292,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
private Set<ConsistencyValidatorFailureReport> validateEntities(XMLStreamReader
rdr, Subject subject,
Set<ConsistencyValidator> executedValidators) throws Exception {
- String synchronizerClass = rdr.getAttributeValue(null,
ExportingInputStream.ID_ATTRIBUTE);
+ String synchronizerClass = rdr.getAttributeValue(null,
SynchronizationConstants.ID_ATTRIBUTE);
HashSet<ConsistencyValidatorFailureReport> ret = new
HashSet<ConsistencyValidatorFailureReport>();
Synchronizer<?, ?> synchronizer = instantiate(synchronizerClass,
Synchronizer.class,
@@ -309,7 +323,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
boolean bailout = false;
switch (rdr.next()) {
case XMLStreamConstants.START_ELEMENT:
- if
(ExportingInputStream.DATA_ELEMENT.equals(rdr.getName().getLocalPart())) {
+ if
(SynchronizationConstants.DATA_ELEMENT.equals(rdr.getName().getLocalPart())) {
rdr.nextTag();
Object exportedEntity = importer.unmarshallExportedEntity(new
ExportReader(rdr));
Class<?> exportedEntityClass = exportedEntity.getClass();
@@ -340,7 +354,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
}
break;
case XMLStreamConstants.END_ELEMENT:
- if
(ExportingInputStream.ENTITIES_EXPORT_ELEMENT.equals(rdr.getName().getLocalPart())) {
+ if
(SynchronizationConstants.ENTITIES_EXPORT_ELEMENT.equals(rdr.getName().getLocalPart())) {
bailout = true;
}
}
@@ -361,7 +375,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
switch (rdr.next()) {
case XMLStreamReader.START_ELEMENT:
String tagName = rdr.getName().getLocalPart();
- if (ExportingInputStream.ENTITIES_EXPORT_ELEMENT.equals(tagName)) {
+ if (SynchronizationConstants.ENTITIES_EXPORT_ELEMENT.equals(tagName)) {
try {
importSingle(subject, importerConfigs, rdr);
} catch (Exception e) {
@@ -380,7 +394,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
private ConsistencyValidator validateSingle(XMLStreamReader rdr, Subject subject)
throws InstantiationException,
IllegalAccessException, ClassNotFoundException, XMLStreamException,
InconsistentStateException {
- String validatorClassName = rdr.getAttributeValue(null,
ExportingInputStream.CLASS_ATTRIBUTE);
+ String validatorClassName = rdr.getAttributeValue(null,
SynchronizationConstants.CLASS_ATTRIBUTE);
ConsistencyValidator validator = instantiate(
validatorClassName,
ConsistencyValidator.class,
@@ -398,7 +412,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
private <E, X> void importSingle(Subject subject, Map<String,
Configuration> importConfigs, XMLStreamReader rdr)
throws Exception {
- String synchronizerClassName = rdr.getAttributeValue(null,
ExportingInputStream.ID_ATTRIBUTE);
+ String synchronizerClassName = rdr.getAttributeValue(null,
SynchronizationConstants.ID_ATTRIBUTE);
@SuppressWarnings("unchecked")
Synchronizer<E, X> synchronizer = instantiate(synchronizerClassName,
Synchronizer.class,
@@ -407,15 +421,39 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
synchronizer.initialize(subject, entityManager);
Importer<E, X> importer = synchronizer.getImporter();
- importer.configure(importConfigs.get(synchronizerClassName));
- ExportedEntityMatcher<E, X> matcher = importer.getExportedEntityMatcher();
+ ExportedEntityMatcher<E, X> matcher = null; //this will be initialized once
the importer is configured
+ boolean configured = false;
+ Configuration importConfiguration = importConfigs.get(synchronizerClassName);
+
+ //the passed in configuration has precedence over the default one inlined in
+ //the config file.
+ if (importConfiguration != null) {
+ importer.configure(importConfiguration);
+ matcher = importer.getExportedEntityMatcher();
+ configured = true;
+ }
+
while (rdr.hasNext()) {
boolean bailout = false;
switch (rdr.next()) {
case XMLStreamConstants.START_ELEMENT:
- if
(ExportingInputStream.DATA_ELEMENT.equals(rdr.getName().getLocalPart())) {
+ if
(SynchronizationConstants.DEFAULT_CONFIGURATION_ELEMENT.equals(rdr.getName().getLocalPart()))
{
+ if (!configured) {
+ importConfiguration = getDefaultConfiguration(rdr);
+ }
+ } else if
(SynchronizationConstants.DATA_ELEMENT.equals(rdr.getName().getLocalPart())) {
+
+ //first check if the configure method has been called
+ if (!configured) {
+ importer.configure(importConfiguration);
+ matcher = importer.getExportedEntityMatcher();
+ configured = true;
+ }
+
+ //now do the import
+
rdr.nextTag();
X exportedEntity = importer.unmarshallExportedEntity(new
ExportReader(rdr));
E entity = matcher == null ? null :
matcher.findMatch(exportedEntity);
@@ -423,7 +461,7 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
}
break;
case XMLStreamConstants.END_ELEMENT:
- if
(ExportingInputStream.ENTITIES_EXPORT_ELEMENT.equals(rdr.getName().getLocalPart())) {
+ if
(SynchronizationConstants.ENTITIES_EXPORT_ELEMENT.equals(rdr.getName().getLocalPart())) {
bailout = true;
}
}
@@ -433,6 +471,12 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
}
}
+ //we might have had no data and because we configure the importer lazily, it
might
+ //be left unconfigured by the above loop.
+ if (!configured) {
+ importer.configure(importConfiguration);
+ }
+
importer.finishImport();
}
@@ -466,4 +510,13 @@ public class SynchronizationManagerBean implements
SynchronizationManagerLocal,
return ret;
}
+
+ private Configuration getDefaultConfiguration(XMLStreamReader rdr) throws
JAXBException {
+ Unmarshaller unmarshaller =
defaultImportConfigurationJAXBContext.createUnmarshaller();
+ DefaultImportConfigurationDescriptor descriptor =
(DefaultImportConfigurationDescriptor) unmarshaller.unmarshal(rdr);
+
+ ConfigurationInstanceDescriptorUtil.ConfigurationAndDefinition ccd =
ConfigurationInstanceDescriptorUtil.createConfigurationAndDefinition(descriptor);
+
+ return ccd.configuration;
+ }
}
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
index 1359bee..975e6d3 100644
---
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
@@ -57,6 +57,7 @@ import org.rhq.enterprise.server.sync.ExportReader;
import org.rhq.enterprise.server.sync.ExportWriter;
import org.rhq.enterprise.server.sync.ExportingInputStream;
import org.rhq.enterprise.server.sync.NoSingleEntity;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
import org.rhq.enterprise.server.sync.Synchronizer;
import org.rhq.enterprise.server.sync.exporters.AbstractDelegatingExportingIterator;
import org.rhq.enterprise.server.sync.exporters.Exporter;
@@ -207,9 +208,9 @@ public class ExportingInputStreamTest extends JMockTest {
Element root = doc.getDocumentElement();
- assertEquals(ExportingInputStream.CONFIGURATION_EXPORT_ELEMENT,
root.getNodeName());
+ assertEquals(SynchronizationConstants.CONFIGURATION_EXPORT_ELEMENT,
root.getNodeName());
- NodeList entities =
root.getElementsByTagName(ExportingInputStream.ENTITIES_EXPORT_ELEMENT);
+ NodeList entities =
root.getElementsByTagName(SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
assertEquals(entities.getLength(), 2, "Unexpected number of entities
elements");
Element export1 = (Element) entities.item(0);
@@ -228,32 +229,32 @@ public class ExportingInputStreamTest extends JMockTest {
Element entitiesElement = (Element) node;
- assertEquals(entitiesElement.getNodeName(),
ExportingInputStream.ENTITIES_EXPORT_ELEMENT);
+ assertEquals(entitiesElement.getNodeName(),
SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
- NodeList errorMessages =
entitiesElement.getElementsByTagName(ExportingInputStream.ERROR_MESSAGE_ELEMENT);
+ NodeList errorMessages =
entitiesElement.getElementsByTagName(SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
assertEquals(errorMessages.getLength(), 0, "Unexpected number of error
message elements in an entities export.");
- Node note = getDirectChildByTagName(entitiesElement,
ExportingInputStream.NOTES_ELEMENT);
+ Node note = getDirectChildByTagName(entitiesElement,
SynchronizationConstants.NOTES_ELEMENT);
assertNotNull(note, "Couldn't find exporter notes.");
String notesText = ((Element)note).getTextContent();
assertEquals(notesText, expectedNotes[elementIndex], "Unexpected notes
for entities.");
- NodeList entityElements =
entitiesElement.getElementsByTagName(ExportingInputStream.ENTITY_EXPORT_ELEMENT);
+ NodeList entityElements =
entitiesElement.getElementsByTagName(SynchronizationConstants.ENTITY_EXPORT_ELEMENT);
assertEquals(entityElements.getLength(), 3, "Unexpected number of
exported entities.");
for(int j = 0; j < entityElements.getLength(); ++j) {
Element entityElement = (Element) entityElements.item(j);
- errorMessages =
entityElement.getElementsByTagName(ExportingInputStream.ERROR_MESSAGE_ELEMENT);
+ errorMessages =
entityElement.getElementsByTagName(SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
assertEquals(errorMessages.getLength(), 0, "Unexpected number of
error message elements in an entity.");
- note = getDirectChildByTagName(entityElement,
ExportingInputStream.NOTES_ELEMENT);
+ note = getDirectChildByTagName(entityElement,
SynchronizationConstants.NOTES_ELEMENT);
assertNotNull(note, "Could not find notes for an exported
entity.");
- Node data = getDirectChildByTagName(entityElement,
ExportingInputStream.DATA_ELEMENT);
+ Node data = getDirectChildByTagName(entityElement,
SynchronizationConstants.DATA_ELEMENT);
assertNotNull(data, "Could not find data element in the
entity.");
String dataText = ((Element)data).getTextContent();
@@ -404,13 +405,13 @@ public class ExportingInputStreamTest extends JMockTest {
Element root = doc.getDocumentElement();
- NodeList entities =
root.getElementsByTagName(ExportingInputStream.ENTITY_EXPORT_ELEMENT);
+ NodeList entities =
root.getElementsByTagName(SynchronizationConstants.ENTITY_EXPORT_ELEMENT);
assertEquals(entities.getLength(), 2, "Unexpected number of exported
elements");
//get the entity with the error
Element failedEntity = (Element) entities.item(1);
- Node errorMessage = getDirectChildByTagName(failedEntity,
ExportingInputStream.ERROR_MESSAGE_ELEMENT);
+ Node errorMessage = getDirectChildByTagName(failedEntity,
SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
assertNotNull(errorMessage, "Could not find the error-message element at the
entity that failed to export.");
}
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
index 70819af..34de39e 100644
---
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
@@ -60,6 +60,7 @@ import
org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal;
import org.rhq.enterprise.server.sync.ExportingInputStream;
import org.rhq.enterprise.server.sync.MetricTemplateSynchronizer;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
import org.rhq.enterprise.server.sync.Synchronizer;
import org.rhq.enterprise.server.sync.validators.ConsistencyValidator;
import org.rhq.test.JMockTest;
@@ -131,14 +132,14 @@ public class MetricTemplateExporterTest extends JMockTest {
Element root = doc.getDocumentElement();
- List<Node> validators = getDirectChildrenByTagName(root,
ExportingInputStream.VALIDATOR_ELEMENT);
+ List<Node> validators = getDirectChildrenByTagName(root,
SynchronizationConstants.VALIDATOR_ELEMENT);
Set<ConsistencyValidator> declaredValidators =
exporter.getRequiredValidators();
assertEquals(validators.size(), declaredValidators.size(), "Unexpected
number of validators in the export xml");
for (Node v : validators) {
Element validator = (Element) v;
- String cls = validator.getAttribute(ExportingInputStream.CLASS_ATTRIBUTE);
+ String cls =
validator.getAttribute(SynchronizationConstants.CLASS_ATTRIBUTE);
boolean found = false;
for (ConsistencyValidator dv : declaredValidators) {
@@ -152,9 +153,9 @@ public class MetricTemplateExporterTest extends JMockTest {
+ ", but one such appeared in the export");
}
- Element entities = (Element) getFirstDirectChildByTagName(root,
ExportingInputStream.ENTITIES_EXPORT_ELEMENT);
+ Element entities = (Element) getFirstDirectChildByTagName(root,
SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
- assertEquals(entities.getAttribute(ExportingInputStream.ID_ATTRIBUTE),
MetricTemplateSynchronizer.class.getName(), "Unexpected id of the entities
element.");
+ assertEquals(entities.getAttribute(SynchronizationConstants.ID_ATTRIBUTE),
MetricTemplateSynchronizer.class.getName(), "Unexpected id of the entities
element.");
NodeList metricTemplates =
entities.getElementsByTagName("metricTemplate");
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java
new file mode 100644
index 0000000..5338913
--- /dev/null
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java
@@ -0,0 +1,534 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.sync.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.persistence.EntityManager;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.MeasurementDefinitionCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.sync.ExportReport;
+import org.rhq.core.domain.sync.ImportConfiguration;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.sync.MetricTemplateSynchronizer;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
+import org.rhq.enterprise.server.sync.SynchronizationManagerLocal;
+import org.rhq.enterprise.server.sync.SystemSettingsSynchronizer;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Tests the SynchronizationManagerBean on a live dataset.
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class SynchronizationManagerBeanTest extends AbstractEJB3Test {
+
+ private SynchronizationManagerLocal synchronizationManager;
+ private Subject user;
+ private ExportReport export;
+
+ private static final String RESOURCE_TYPE_NAME =
"SynchronizationManagerBeanTest";
+ private static final String PLUGIN_NAME =
"SynchronizationManagerBeanTest";
+ private static final String METRIC_NAME =
"SynchronizationManagerBeanTest";
+
+ private static class DBChanges {
+ public Properties systemSettings;
+ public ResourceType fakeType;
+ public Resource fakePlatform;
+ }
+
+ private DBChanges dbChanges;
+
+ //I just don't get why this can't be a @BeforeTest
+ //but when it was declared as such (together with tearDown() being an @AfterTest)
+ //no tests would work. I have no idea why...
+ private void setup() throws Exception {
+ dbChanges = new DBChanges();
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ //add our new metric template that we are going to perform the tests with
+ dbChanges.fakeType = new ResourceType(RESOURCE_TYPE_NAME, PLUGIN_NAME,
ResourceCategory.PLATFORM, null);
+
+ MeasurementDefinition mdef =
+ new MeasurementDefinition(METRIC_NAME, MeasurementCategory.PERFORMANCE,
MeasurementUnits.NONE,
+ DataType.MEASUREMENT, true, 600000, DisplayType.SUMMARY);
+ dbChanges.fakeType.addMetricDefinition(mdef);
+
+ em.persist(dbChanges.fakeType);
+
+ dbChanges.fakePlatform = new Resource(RESOURCE_TYPE_NAME, RESOURCE_TYPE_NAME,
dbChanges.fakeType);
+ dbChanges.fakePlatform.setUuid(UUID.randomUUID().toString());
+ dbChanges.fakePlatform.setInventoryStatus(InventoryStatus.COMMITTED);
+
+ MeasurementSchedule sched = new MeasurementSchedule(mdef,
dbChanges.fakePlatform);
+ sched.setInterval(600000);
+
+ dbChanges.fakePlatform.addSchedule(sched);
+
+ em.persist(dbChanges.fakePlatform);
+
+ em.persist(sched);
+
+ em.flush();
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ synchronizationManager = LookupUtil.getSynchronizationManager();
+
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ //make sure the system manager is in sync w/ the db we just changed in dbsetup
+ systemManager.loadSystemConfigurationCache();
+
+ dbChanges.systemSettings = systemManager.getSystemConfiguration(freshUser());
+ export = synchronizationManager.exportAllSubsystems(freshUser());
+ }
+
+ private void tearDown() throws Exception {
+ getTransactionManager().begin();
+ try {
+ LookupUtil.getSystemManager().setSystemConfiguration(freshUser(),
dbChanges.systemSettings, true);
+
+ EntityManager em = getEntityManager();
+
+ MeasurementSchedule sched =
+ em.find(MeasurementSchedule.class,
dbChanges.fakePlatform.getSchedules().iterator().next().getId());
+ em.remove(sched);
+
+ Resource attachedPlatform = em.find(Resource.class,
dbChanges.fakePlatform.getId());
+ em.remove(attachedPlatform);
+
+ ResourceType attachedType = em.find(ResourceType.class,
dbChanges.fakeType.getId());
+ em.remove(attachedType);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ export = null;
+ dbChanges = null;
+ synchronizationManager = null;
+ }
+
+ public void testExport() throws Exception {
+ setup();
+ try {
+ assertNull("Export shouldn't generate an error message.",
export.getErrorMessage());
+ assertTrue("The export should contain some data.",
export.getExportFile().length > 0);
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testImportWithDefaultConfiguration() throws Exception {
+ setup();
+
+ try {
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ MeasurementDefinitionManagerLocal measurementDefinitionManager =
+ LookupUtil.getMeasurementDefinitionManager();
+
+ Properties beforeSystemSettings =
systemManager.getSystemConfiguration(freshUser());
+ MeasurementDefinitionCriteria criteria = new
MeasurementDefinitionCriteria();
+ criteria.setPageControl(PageControl.getUnlimitedInstance());
+ criteria.fetchResourceType(true);
+
+ List<MeasurementDefinition> beforeMeasurementDefinitions =
+
measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(), criteria);
+
+ synchronizationManager.importAllSubsystems(freshUser(),
export.getExportFile(), null);
+
+ //this is to work around BZ 735810
+ systemManager.loadSystemConfigurationCache();
+
+ Properties afterSystemSettings =
systemManager.getSystemConfiguration(freshUser());
+ List<MeasurementDefinition> afterMeasurementDefinitions =
+
measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(), criteria);
+
+ assertEquals("System settings unexpectedly differ",
beforeSystemSettings, afterSystemSettings);
+
+ //make sure we don't fail on simple order differences, which are not
important here..
+ Set<MeasurementDefinition> beforeDefsToCheck =
+ new HashSet<MeasurementDefinition>(beforeMeasurementDefinitions);
+ Set<MeasurementDefinition> afterDefsToCheck =
+ new HashSet<MeasurementDefinition>(afterMeasurementDefinitions);
+ assertEquals("Measurement definitions unexpectedly differ",
beforeDefsToCheck, afterDefsToCheck);
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testImportWithRedefinedConfigurationInExportFile() throws Exception {
+ setup();
+
+ try {
+ String exportXML = getExportData();
+
+ exportXML = updateSystemSettingsImportConfiguration(exportXML);
+ exportXML = updateMetricTemplatesImportConfiguration(exportXML);
+
+ ByteArrayOutputStream compressed = new ByteArrayOutputStream();
+ OutputStreamWriter wrt = new OutputStreamWriter(new
GZIPOutputStream(compressed), "UTF-8");
+ try {
+ wrt.write(exportXML);
+ } finally {
+ wrt.close();
+ }
+
+ InputStream exportData = new ByteArrayInputStream(compressed.toByteArray());
+
+ try {
+ synchronizationManager.importAllSubsystems(freshUser(), exportData,
null);
+ } finally {
+ exportData.close();
+ }
+
+ //now check that everything got imported according to the changed
configuration
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ Properties settings = systemManager.getSystemConfiguration(freshUser());
+
+ assertEquals(settings.getProperty("CAM_BASE_URL"),
"http://testing.domain:7080");
+
+ MeasurementDefinitionManagerLocal measurementDefinitionManager =
+ LookupUtil.getMeasurementDefinitionManager();
+ MeasurementDefinitionCriteria crit = new MeasurementDefinitionCriteria();
+ crit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ crit.addFilterName(METRIC_NAME);
+ MeasurementDefinition mdef =
+
measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(),
crit).get(0);
+
+ assertEquals("The " + METRIC_NAME + " metric should have been
updated with default interval of 30s",
+ Long.valueOf(30000), new Long(mdef.getDefaultInterval()));
+
+ //ok, and now test that the platform resource schedule was updated as well
+
+ //get the resource id first
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ ResourceCriteria rcrit = new ResourceCriteria();
+ rcrit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ List<Resource> platforms =
resourceManager.findResourcesByCriteria(freshUser(), rcrit);
+
+ assertEquals("Unexpected number of platform resources found.", 1,
platforms.size());
+
+ int platformResourceId = platforms.get(0).getId();
+
+ //now find the schedule for the measurement
+ MeasurementScheduleManagerLocal measurementScheduleManager =
LookupUtil.getMeasurementScheduleManager();
+ List<MeasurementSchedule> schedules =
+
measurementScheduleManager.findSchedulesByResourceIdAndDefinitionIds(freshUser(),
platformResourceId,
+ new int[] { mdef.getId() });
+
+ assertEquals("Unexpected number of '" + METRIC_NAME +
"' schedules found.", 1, schedules.size());
+
+ assertEquals("The schedule should have been updated along with the
definition during the config sync",
+ 30000, schedules.get(0).getInterval());
+
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testManuallyPassedImportConfigurationHasPrecendenceOverTheInlinedOne()
throws Exception {
+ setup();
+
+ try {
+ //let's read the original values from the database, so that we know what
to compare against
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ Properties settings = systemManager.getSystemConfiguration(freshUser());
+
+ String originalBaseUrl = settings.getProperty("CAM_BASE_URL");
+
+ MeasurementDefinitionManagerLocal measurementDefinitionManager =
+ LookupUtil.getMeasurementDefinitionManager();
+ MeasurementDefinitionCriteria crit = new MeasurementDefinitionCriteria();
+ crit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ crit.addFilterName(METRIC_NAME);
+ MeasurementDefinition distroNameDef =
+
measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(),
crit).get(0);
+
+ long originalInterval = distroNameDef.getDefaultInterval();
+
+ //now modify the default configuration in the export file
+ String exportXML = getExportData();
+
+ exportXML = updateSystemSettingsImportConfiguration(exportXML);
+ exportXML = updateMetricTemplatesImportConfiguration(exportXML);
+
+ ByteArrayOutputStream compressed = new ByteArrayOutputStream();
+ OutputStreamWriter wrt = new OutputStreamWriter(new
GZIPOutputStream(compressed), "UTF-8");
+ try {
+ wrt.write(exportXML);
+ } finally {
+ wrt.close();
+ }
+
+ InputStream exportData = new ByteArrayInputStream(compressed.toByteArray());
+
+ //let's just use the default configs so that we don't apply the
changes suggested in
+ //the changed default configs created above
+ ImportConfiguration systemSettingsConfiguration =
+ new ImportConfiguration(SystemSettingsSynchronizer.class.getName(), new
SystemSettingsSynchronizer()
+
.getImporter().getImportConfigurationDefinition().getDefaultTemplate().createConfiguration());
+ ImportConfiguration metricTemplatesConfiguration =
+ new ImportConfiguration(MetricTemplateSynchronizer.class.getName(), new
MetricTemplateSynchronizer()
+
.getImporter().getImportConfigurationDefinition().getDefaultTemplate().createConfiguration());
+
+ try {
+ synchronizationManager.importAllSubsystems(freshUser(), exportData,
+ Arrays.asList(systemSettingsConfiguration,
metricTemplatesConfiguration));
+ } finally {
+ exportData.close();
+ }
+
+ //now check that we import using the manually create configurations, not the
inlined ones
+ settings = systemManager.getSystemConfiguration(freshUser());
+
+ assertEquals(settings.getProperty("CAM_BASE_URL"),
originalBaseUrl);
+
+ measurementDefinitionManager = LookupUtil.getMeasurementDefinitionManager();
+ distroNameDef =
measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(),
crit).get(0);
+
+ //the definition should have been updated by the data from the export file
+ assertEquals("The " + METRIC_NAME + " metric shouldn't
have changed its default interval", 30000,
+ distroNameDef.getDefaultInterval());
+
+ //ok, and now test that the platform resource schedule was NOT updated
because it was configured not to.
+
+ //get the resource id first
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ ResourceCriteria rcrit = new ResourceCriteria();
+ rcrit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ List<Resource> platforms =
resourceManager.findResourcesByCriteria(freshUser(), rcrit);
+
+ assertEquals("Unexpected number of platform resources found.", 1,
platforms.size());
+
+ int platformResourceId = platforms.get(0).getId();
+
+ //now find the schedule for the measurement
+ MeasurementScheduleManagerLocal measurementScheduleManager =
LookupUtil.getMeasurementScheduleManager();
+ List<MeasurementSchedule> schedules =
+
measurementScheduleManager.findSchedulesByResourceIdAndDefinitionIds(freshUser(),
platformResourceId,
+ new int[] { distroNameDef.getId() });
+
+ assertEquals("Unexpected number of '" + METRIC_NAME +
"' schedules found.", 1, schedules.size());
+
+ assertEquals("The schedule should have been updated along with the
definition during the config sync",
+ originalInterval, schedules.get(0).getInterval());
+
+ } finally {
+ tearDown();
+ }
+ }
+
+ private String getExportData() throws IOException {
+ InputStreamReader str =
+ new InputStreamReader(new GZIPInputStream(new
ByteArrayInputStream(export.getExportFile())), "UTF-8");
+ try {
+ char[] buf = new char[32768];
+ StringBuilder bld = new StringBuilder();
+
+ int cnt = 0;
+ while ((cnt = str.read(buf)) >= 0) {
+ bld.append(buf, 0, cnt);
+ }
+
+ return bld.toString();
+ } finally {
+ str.close();
+ }
+ }
+
+ private static String documentToString(Document document) throws
TransformerFactoryConfigurationError,
+ TransformerException, IOException {
+
+ StringWriter ret = new StringWriter();
+ try {
+ Source source = new DOMSource(document);
+ Result result = new StreamResult(ret);
+
+ Transformer xformer = TransformerFactory.newInstance().newTransformer();
+ xformer.transform(source, result);
+
+ return ret.toString();
+ } finally {
+ ret.close();
+ }
+ }
+
+ private String updateSystemSettingsImportConfiguration(String exportXML) throws
Exception {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+
xpath.setNamespaceContext(SynchronizationConstants.createConfigurationExportNamespaceContext());
+
+ XPathExpression systemSettingsConfigurationPath =
+ xpath
+
.compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.SystemSettingsSynchronizer']/:default-configuration/ci:simple-property[@name='propertiesToImport']");
+
+ XPathExpression baseUrlSettingPath =
+ xpath
+
.compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.SystemSettingsSynchronizer']/:entity/:data/systemSettings/entry[@key='CAM_BASE_URL']");
+
+ Element systemSettingsConfiguration =
+ (Element) systemSettingsConfigurationPath.evaluate(new InputSource(new
StringReader(exportXML)),
+ XPathConstants.NODE);
+ String propsToImport =
systemSettingsConfiguration.getAttribute("value");
+
+ propsToImport += ", CAM_BASE_URL";
+
+ systemSettingsConfiguration.setAttribute("value", propsToImport);
+
+ exportXML = documentToString(systemSettingsConfiguration.getOwnerDocument());
+
+ Element baseUrlSetting =
+ (Element) baseUrlSettingPath.evaluate(new InputSource(new
StringReader(exportXML)), XPathConstants.NODE);
+
+ baseUrlSetting.setTextContent("http://testing.domain:7080");
+
+ return documentToString(baseUrlSetting.getOwnerDocument());
+ }
+
+ private String updateMetricTemplatesImportConfiguration(String exportXML) throws
Exception {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+
xpath.setNamespaceContext(SynchronizationConstants.createConfigurationExportNamespaceContext());
+
+ XPathExpression overridesPath =
+ xpath
+
.compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.MetricTemplateSynchronizer']/:default-configuration/ci:list-property[@name='metricUpdateOverrides']");
+
+ Element overrides =
+ (Element) overridesPath.evaluate(new InputSource(new
StringReader(exportXML)), XPathConstants.NODE);
+
+ Document doc = overrides.getOwnerDocument();
+
+ String ns = SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE;
+ String prefix =
SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE_PREFIX;
+
+ Element values = doc.createElementNS(ns, prefix + ":values");
+ overrides.appendChild(values);
+
+ Element mapValue = doc.createElementNS(ns, prefix + ":map-value");
+ values.appendChild(mapValue);
+
+ addSimpleValue(mapValue, "metricName", METRIC_NAME);
+ addSimpleValue(mapValue, "resourceTypeName", RESOURCE_TYPE_NAME);
+ addSimpleValue(mapValue, "resourceTypePlugin", PLUGIN_NAME);
+ addSimpleValue(mapValue, "updateSchedules", "true");
+
+ exportXML = documentToString(doc);
+
+ //now redefine the collection interval of the above metric so that we can see the
change after the import
+ XPathExpression distroNameMetricPath =
+ xpath
+
.compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.MetricTemplateSynchronizer']/:entity/:data/metricTemplate[@metricName='"
+ + METRIC_NAME + "']");
+
+ Element metric =
+ (Element) distroNameMetricPath.evaluate(new InputSource(new
StringReader(exportXML)), XPathConstants.NODE);
+
+ doc = metric.getOwnerDocument();
+
+ metric.setAttribute("defaultInterval", "30000");
+
+ return documentToString(doc);
+ }
+
+ private static void addSimpleValue(Element parent, String propertyName, String value)
{
+ String ns = SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE;
+ String prefix =
SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE_PREFIX;
+ Element simpleValue = parent.getOwnerDocument().createElementNS(ns, prefix +
":simple-value");
+ simpleValue.setAttribute("property-name", propertyName);
+ simpleValue.setAttribute("value", value);
+
+ parent.appendChild(simpleValue);
+ }
+
+ private Subject freshUser() {
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+
+ if (user != null) {
+ try {
+ subjectManager.logout(user);
+ } catch (PermissionException e) {
+ //we can safely ignore a permission exception during logout...
+ }
+ }
+
+ user = subjectManager.getOverlord();
+ return user;
+ }
+}
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
index 2f8aa26..2837982 100644
---
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
@@ -49,6 +49,7 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.sync.ExporterMessages;
import org.rhq.core.domain.sync.entity.SystemSettings;
import org.rhq.enterprise.server.sync.ExportingInputStream;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
import org.rhq.enterprise.server.sync.Synchronizer;
import org.rhq.enterprise.server.sync.SystemSettingsSynchronizer;
import org.rhq.enterprise.server.system.SystemManagerLocal;
@@ -105,9 +106,9 @@ public class SystemSettingsExporterTest extends JMockTest {
Element root = doc.getDocumentElement();
- Element entities = (Element) getFirstDirectChildByTagName(root,
ExportingInputStream.ENTITIES_EXPORT_ELEMENT);
+ Element entities = (Element) getFirstDirectChildByTagName(root,
SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
- assertEquals(entities.getAttribute(ExportingInputStream.ID_ATTRIBUTE),
SystemSettingsSynchronizer.class.getName(),
+ assertEquals(entities.getAttribute(SynchronizationConstants.ID_ATTRIBUTE),
SystemSettingsSynchronizer.class.getName(),
"Unexpected id of the entities element.");
NodeList systemSettings =
entities.getElementsByTagName("systemSettings");
diff --git
a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtil.java
b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtil.java
index b2f9ae3..56abf6b 100644
---
a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtil.java
+++
b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtil.java
@@ -31,6 +31,9 @@ import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
+import org.rhq.core.clientapi.agent.metadata.InvalidPluginDescriptorException;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
import org.rhq.core.clientapi.descriptor.configuration.ListProperty;
import org.rhq.core.clientapi.descriptor.configuration.MapProperty;
@@ -78,61 +81,12 @@ public class ConfigurationInstanceDescriptorUtil {
}
- /**
- * A configuration instance is a combination of a configuration definition and a
concrete
- * configuration instance with defined values. This is used during the config
synchronization
- * to output the default configuration of an importer directly in the export file so
that the
- * users have an easy way of modifying that configuration.
- *
- * @param definition
- * @param configuration
- * @return
- */
- public static ConfigurationInstanceDescriptor
createConfigurationInstance(ConfigurationDefinition definition,
- Configuration configuration) {
-
- ConfigurationInstanceDescriptor ret = new ConfigurationInstanceDescriptor();
-
- addAll(ret.getConfigurationProperty(), definition.getPropertyDefinitions(),
configuration.getMap());
-
- return ret;
- }
-
- private static void addAll(List<JAXBElement<?>> descriptors,
Map<String, PropertyDefinition> defs, Map<String, Property> props) {
- for(Map.Entry<String, PropertyDefinition> e : defs.entrySet()) {
- String propName = e.getKey();
- PropertyDefinition def = e.getValue();
- Property prop = props.get(propName);
-
- addSingle(descriptors, def, prop);
- }
- }
-
- private static void addSingle(List<JAXBElement<?>> descriptors,
PropertyDefinition def, Property prop) {
- ConfigurationProperty descriptor = null;
- QName tagName = null;
-
- descriptor = createDescriptor(def, prop);
- tagName = getTagName(descriptor);
-
- addToJAXBElementList(descriptors, Object.class, descriptor, tagName);
+ public static class ConfigurationAndDefinition {
+ public Configuration configuration;
+ public ConfigurationDefinition definition;
}
- private static ConfigurationProperty createDescriptor(PropertyDefinition def,
Property prop) {
- ConfigurationProperty ret = null;
-
- if (def instanceof PropertyDefinitionSimple) {
- ret = createSimple((PropertyDefinitionSimple) def, (PropertySimple) prop);
- } else if (def instanceof PropertyDefinitionList) {
- ret = createList((PropertyDefinitionList) def, (PropertyList) prop);
- } else if (def instanceof PropertyDefinitionMap) {
- ret = createMap((PropertyDefinitionMap) def, (PropertyMap) prop);
- }
-
- return ret;
- }
-
- private static QName getTagName(ConfigurationProperty descriptor) {
+ protected static QName getTagName(ConfigurationProperty descriptor) {
if (descriptor instanceof SimplePropertyInstanceDescriptor) {
return new QName(NS_CONFIGURATION_INSTANCE, "simple-property");
} else if (descriptor instanceof ListPropertyInstanceDescriptor) {
@@ -161,246 +115,460 @@ public class ConfigurationInstanceDescriptorUtil {
throw new IllegalArgumentException("Unknown value descriptor type: " +
value.getClass());
}
-
- private static SimplePropertyInstanceDescriptor createSimple(PropertyDefinitionSimple
def, PropertySimple prop) {
- SimplePropertyInstanceDescriptor ret = new SimplePropertyInstanceDescriptor();
- setCommonProps(ret, def, true);
- //these are prohibited, because they make no sense on the property instance
- //ret.setDefaultValue(def.getDefaultValue());
- //ret.setInitialValue(prop.getStringValue());
- //ret.setActivationPolicy(pds.getActivationPolicy());
- ret.setPropertyOptions(convert(def.getEnumeratedValues()));
- ret.setType(convert(def.getType()));
- ret.setUnits(convert(def.getUnits()));
+ private static class ToDescriptor {
- if (prop != null) {
- ret.setValue(prop.getStringValue());
+ public static ConfigurationInstanceDescriptor
createConfigurationInstance(ConfigurationDefinition definition,
+ Configuration configuration) {
+
+ ConfigurationInstanceDescriptor ret = new ConfigurationInstanceDescriptor();
+
+ addAll(ret.getConfigurationProperty(), definition.getPropertyDefinitions(),
configuration.getMap());
+
+ return ret;
}
- return ret;
- }
-
- private static ListPropertyInstanceDescriptor createList(PropertyDefinitionList def,
PropertyList prop) {
- ListPropertyInstanceDescriptor ret = new ListPropertyInstanceDescriptor();
+ private static void addAll(List<JAXBElement<?>> descriptors,
Map<String, PropertyDefinition> defs, Map<String, Property> props) {
+ for(Map.Entry<String, PropertyDefinition> e : defs.entrySet()) {
+ String propName = e.getKey();
+ PropertyDefinition def = e.getValue();
+ Property prop = props.get(propName);
+
+ addSingle(descriptors, def, prop);
+ }
+ }
- setCommonProps(ret, def, true);
+ private static void addSingle(List<JAXBElement<?>> descriptors,
PropertyDefinition def, Property prop) {
+ ConfigurationProperty descriptor = null;
+ QName tagName = null;
+
+ descriptor = createDescriptor(def, prop);
+ tagName = getTagName(descriptor);
+
+ addToJAXBElementList(descriptors, Object.class, descriptor, tagName);
+ }
- ConfigurationProperty memberDef = convertDefinition(def.getMemberDefinition());
- ret.setConfigurationProperty(new
JAXBElement<ConfigurationProperty>(getTagName(memberDef),
ConfigurationProperty.class, memberDef));
+ private static ConfigurationProperty createDescriptor(PropertyDefinition def,
Property prop) {
+ ConfigurationProperty ret = null;
+
+ if (def instanceof PropertyDefinitionSimple) {
+ ret = createSimple((PropertyDefinitionSimple) def, (PropertySimple)
prop);
+ } else if (def instanceof PropertyDefinitionList) {
+ ret = createList((PropertyDefinitionList) def, (PropertyList) prop);
+ } else if (def instanceof PropertyDefinitionMap) {
+ ret = createMap((PropertyDefinitionMap) def, (PropertyMap) prop);
+ }
+
+ return ret;
+ }
- if (prop != null) {
- PropertyValuesDescriptor values = new PropertyValuesDescriptor();
+ private static SimplePropertyInstanceDescriptor
createSimple(PropertyDefinitionSimple def, PropertySimple prop) {
+ SimplePropertyInstanceDescriptor ret = new
SimplePropertyInstanceDescriptor();
+ setCommonProps(ret, def, true);
- ret.setValues(values);
+ //these are prohibited, because they make no sense on the property instance
+ //ret.setDefaultValue(def.getDefaultValue());
+ //ret.setInitialValue(prop.getStringValue());
+ //ret.setActivationPolicy(pds.getActivationPolicy());
+ ret.setPropertyOptions(convert(def.getEnumeratedValues()));
+ ret.setType(convert(def.getType()));
+ ret.setUnits(convert(def.getUnits()));
- for(Property el : prop.getList()) {
- ComplexValueDescriptor value = convertValue(el);
+ if (prop != null) {
+ ret.setValue(prop.getStringValue());
+ }
+
+ return ret;
+ }
+
+ private static ListPropertyInstanceDescriptor createList(PropertyDefinitionList
def, PropertyList prop) {
+ ListPropertyInstanceDescriptor ret = new ListPropertyInstanceDescriptor();
+
+ setCommonProps(ret, def, true);
+
+ ConfigurationProperty memberDef =
convertDefinition(def.getMemberDefinition());
+ ret.setConfigurationProperty(new
JAXBElement<ConfigurationProperty>(getTagName(memberDef),
ConfigurationProperty.class, memberDef));
+
+ if (prop != null) {
+ PropertyValuesDescriptor values = new PropertyValuesDescriptor();
- //we don't need the property-name in lists, because the list has just
a single member definition
- value.setPropertyName(null);
+ ret.setValues(values);
- addToJAXBElementList(values.getComplexValue(), Object.class, value,
getTagName(value));
+ for(Property el : prop.getList()) {
+ ComplexValueDescriptor value = convertValue(el);
+
+ //we don't need the property-name in lists, because the list has
just a single member definition
+ value.setPropertyName(null);
+
+ addToJAXBElementList(values.getComplexValue(), Object.class, value,
getTagName(value));
+ }
}
+
+ return ret;
}
- return ret;
- }
-
- private static MapPropertyInstanceDescriptor createMap(PropertyDefinitionMap def,
PropertyMap prop) {
- MapPropertyInstanceDescriptor ret = new MapPropertyInstanceDescriptor();
-
- setCommonProps(ret, def, true);
+ private static MapPropertyInstanceDescriptor createMap(PropertyDefinitionMap def,
PropertyMap prop) {
+ MapPropertyInstanceDescriptor ret = new MapPropertyInstanceDescriptor();
+
+ setCommonProps(ret, def, true);
+
+ for(PropertyDefinition mem : def.getPropertyDefinitions().values()) {
+ ConfigurationProperty memDef = convertDefinition(mem);
+
+ addToJAXBElementList(ret.getConfigurationProperty(),
ConfigurationProperty.class, memDef, getTagName(memDef));
+ }
+
+ if (prop != null) {
+ PropertyValuesDescriptor values = new PropertyValuesDescriptor();
+
+ ret.setValues(values);
- for(PropertyDefinition mem : def.getPropertyDefinitions().values()) {
- ConfigurationProperty memDef = convertDefinition(mem);
+ for(Property el : prop.getMap().values()) {
+ ComplexValueDescriptor value = convertValue(el);
+ addToJAXBElementList(values.getComplexValue(), Object.class, value,
getTagName(value));
+ }
+ }
- addToJAXBElementList(ret.getConfigurationProperty(),
ConfigurationProperty.class, memDef, getTagName(memDef));
+ return ret;
}
- if (prop != null) {
- PropertyValuesDescriptor values = new PropertyValuesDescriptor();
+ private static void setCommonProps(ConfigurationProperty target,
PropertyDefinition source, boolean creatingInstance) {
+ target.setName(source.getName());
+ //let's always use long description
+ //target.setDescription(source.getDescription());
+ target.setLongDescription(source.getDescription());
+ target.setDisplayName(source.getDisplayName());
- ret.setValues(values);
-
- for(Property el : prop.getMap().values()) {
- ComplexValueDescriptor value = convertValue(el);
- addToJAXBElementList(values.getComplexValue(), Object.class, value,
getTagName(value));
+ //these are prohibited on the instance because they make no sense there
+ if (!creatingInstance) {
+ target.setRequired(source.isRequired());
+ target.setReadOnly(source.isReadOnly());
+ target.setSummary(source.isSummary());
}
}
- return ret;
- }
-
- private static void setCommonProps(ConfigurationProperty target, PropertyDefinition
source, boolean creatingInstance) {
- target.setName(source.getName());
- //let's always use long description
- //target.setDescription(source.getDescription());
- target.setLongDescription(source.getDescription());
- target.setDisplayName(source.getDisplayName());
-
- //these are prohibited on the instance because they make no sense there
- if (!creatingInstance) {
- target.setRequired(source.isRequired());
- target.setReadOnly(source.isReadOnly());
- target.setSummary(source.isSummary());
- }
- }
-
- private static PropertyOptions convert(List<PropertyDefinitionEnumeration>
options) {
- if (options.isEmpty()) {
- return null;
+ private static PropertyOptions convert(List<PropertyDefinitionEnumeration>
options) {
+ if (options.isEmpty()) {
+ return null;
+ }
+
+ PropertyOptions ret = new PropertyOptions();
+
+ ArrayList<PropertyDefinitionEnumeration> opts = new
ArrayList<PropertyDefinitionEnumeration>(options);
+
+ Collections.sort(opts, new Comparator<PropertyDefinitionEnumeration>()
{
+ public int compare(PropertyDefinitionEnumeration o1,
PropertyDefinitionEnumeration o2) {
+ return o1.getOrderIndex() - o2.getOrderIndex();
+ }
+ });
+
+ for(PropertyDefinitionEnumeration option : opts) {
+ ret.getOption().add(convert(option));
+ }
+
+ return ret;
}
- PropertyOptions ret = new PropertyOptions();
-
- ArrayList<PropertyDefinitionEnumeration> opts = new
ArrayList<PropertyDefinitionEnumeration>(options);
+ private static Option convert(PropertyDefinitionEnumeration option) {
+ Option ret = new Option();
+ ret.setName(option.getName());
+ ret.setValue(option.getValue());
+ return ret;
+ }
- Collections.sort(opts, new Comparator<PropertyDefinitionEnumeration>() {
- public int compare(PropertyDefinitionEnumeration o1,
PropertyDefinitionEnumeration o2) {
- return o1.getOrderIndex() - o2.getOrderIndex();
+ private static PropertyType convert(PropertySimpleType type) {
+ if (type == null) {
+ return null;
+ }
+
+ try {
+ return PropertyType.valueOf(type.name());
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Failed to convert a PropertySimpleType instance
'" + type.name() + "' into a PropertyType.", e);
+ throw e;
}
- });
-
- for(PropertyDefinitionEnumeration option : opts) {
- ret.getOption().add(convert(option));
}
- return ret;
- }
-
- private static Option convert(PropertyDefinitionEnumeration option) {
- Option ret = new Option();
- ret.setName(option.getName());
- ret.setValue(option.getValue());
- return ret;
- }
-
- private static PropertyType convert(PropertySimpleType type) {
- if (type == null) {
- return null;
+ private static MeasurementUnitsDescriptor convert(MeasurementUnits unit) {
+ //XXX there actually are some differences in the available values for these
+ //two enums:
+ //Missing in MeasurementUnitsDescriptor:
+ //MeasurementUnits.JIFFY, MeasurementUnits.PETA_BYTES
+
+ if (unit == null) {
+ return null;
+ }
+
+ String value = unit.name();
+
+ try {
+ return MeasurementUnitsDescriptor.valueOf(value);
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Failed to convert a MeasurementUnits instance '"
+ unit.getName() + "' into a MeasurementUnitsDescriptor.", e);
+ throw e;
+ }
}
- try {
- return PropertyType.valueOf(type.name());
- } catch (IllegalArgumentException e) {
- LOG.warn("Failed to convert a PropertySimpleType instance '" +
type.name() + "' into a PropertyType.", e);
- throw e;
+ private static ConfigurationProperty convertDefinition(PropertyDefinition def) {
+ if (def instanceof PropertyDefinitionSimple) {
+ return convertSimple((PropertyDefinitionSimple) def);
+ } else if (def instanceof PropertyDefinitionList) {
+ return convertList((PropertyDefinitionList) def);
+ } else if (def instanceof PropertyDefinitionMap) {
+ return convertMap((PropertyDefinitionMap) def);
+ }
+
+ throw new IllegalArgumentException("Unsupported property definition
type: " + def.getClass());
}
- }
-
- private static MeasurementUnitsDescriptor convert(MeasurementUnits unit) {
- //XXX there actually are some differences in the available values for these
- //two enums:
- //Missing in MeasurementUnitsDescriptor:
- //MeasurementUnits.JIFFY, MeasurementUnits.PETA_BYTES
- if (unit == null) {
- return null;
+ private static SimpleProperty convertSimple(PropertyDefinitionSimple def) {
+ SimpleProperty ret = new SimpleProperty();
+ setCommonProps(ret, def, false);
+ ret.setDefaultValue(def.getDefaultValue());
+ ret.setPropertyOptions(convert(def.getEnumeratedValues()));
+ ret.setType(convert(def.getType()));
+ ret.setUnits(convert(def.getUnits()));
+
+ return ret;
}
- String value = unit.name();
-
- try {
- return MeasurementUnitsDescriptor.valueOf(value);
- } catch (IllegalArgumentException e) {
- LOG.warn("Failed to convert a MeasurementUnits instance '" +
unit.getName() + "' into a MeasurementUnitsDescriptor.", e);
- throw e;
- }
- }
-
- private static ConfigurationProperty convertDefinition(PropertyDefinition def) {
- if (def instanceof PropertyDefinitionSimple) {
- return convertSimple((PropertyDefinitionSimple) def);
- } else if (def instanceof PropertyDefinitionList) {
- return convertList((PropertyDefinitionList) def);
- } else if (def instanceof PropertyDefinitionMap) {
- return convertMap((PropertyDefinitionMap) def);
+ private static ListProperty convertList(PropertyDefinitionList def) {
+ ListProperty ret = new ListProperty();
+ setCommonProps(ret, def, false);
+ ConfigurationProperty memberDefinition =
convertDefinition(def.getMemberDefinition());
+ ret.setConfigurationProperty(new
JAXBElement<ConfigurationProperty>(getTagName(memberDefinition),
ConfigurationProperty.class, memberDefinition));
+
+ return ret;
}
- throw new IllegalArgumentException("Unsupported property definition type:
" + def.getClass());
- }
-
- private static SimpleProperty convertSimple(PropertyDefinitionSimple def) {
- SimpleProperty ret = new SimpleProperty();
- setCommonProps(ret, def, false);
- ret.setDefaultValue(def.getDefaultValue());
- ret.setPropertyOptions(convert(def.getEnumeratedValues()));
- ret.setType(convert(def.getType()));
- ret.setUnits(convert(def.getUnits()));
+ private static MapProperty convertMap(PropertyDefinitionMap def) {
+ MapProperty ret = new MapProperty();
+ setCommonProps(ret, def, false);
+
+ List<JAXBElement<? extends ConfigurationProperty>> elements =
ret.getConfigurationProperty();
+ for(PropertyDefinition el : def.getPropertyDefinitions().values()) {
+ ConfigurationProperty prop = convertDefinition(el);
+ QName tagName = getTagName(prop);
+ addToJAXBElementList(elements, ConfigurationProperty.class, prop,
tagName);
+ }
+
+ return ret;
+ }
- return ret;
- }
-
- private static ListProperty convertList(PropertyDefinitionList def) {
- ListProperty ret = new ListProperty();
- setCommonProps(ret, def, false);
- ConfigurationProperty memberDefinition =
convertDefinition(def.getMemberDefinition());
- ret.setConfigurationProperty(new
JAXBElement<ConfigurationProperty>(getTagName(memberDefinition),
ConfigurationProperty.class, memberDefinition));
+ private static ComplexValueDescriptor convertValue(Property prop) {
+ if (prop instanceof PropertySimple) {
+ return convertSimpleValue((PropertySimple) prop);
+ } else if (prop instanceof PropertyList) {
+ return convertListValue((PropertyList) prop);
+ } else if (prop instanceof PropertyMap) {
+ return convertMapValue((PropertyMap) prop);
+ }
+
+ throw new IllegalArgumentException("Unsupported property type to convert
to a value descriptor: " + prop.getClass());
+ }
- return ret;
- }
-
- private static MapProperty convertMap(PropertyDefinitionMap def) {
- MapProperty ret = new MapProperty();
- setCommonProps(ret, def, false);
+ private static ComplexValueSimpleDescriptor convertSimpleValue(PropertySimple
prop) {
+ ComplexValueSimpleDescriptor ret = new ComplexValueSimpleDescriptor();
+ ret.setPropertyName(prop.getName());
+ ret.setValue(prop.getStringValue());
+
+ return ret;
+ }
- List<JAXBElement<? extends ConfigurationProperty>> elements =
ret.getConfigurationProperty();
- for(PropertyDefinition el : def.getPropertyDefinitions().values()) {
- ConfigurationProperty prop = convertDefinition(el);
- QName tagName = getTagName(prop);
- addToJAXBElementList(elements, ConfigurationProperty.class, prop, tagName);
+ private static ComplexValueListDescriptor convertListValue(PropertyList prop) {
+ ComplexValueListDescriptor ret = new ComplexValueListDescriptor();
+ ret.setPropertyName(prop.getName());
+
+ for(Property el : prop.getList()) {
+ ComplexValueDescriptor value = convertValue(el);
+ addToJAXBElementList(ret.getComplexValue(), Object.class, value,
getTagName(value));
+ }
+
+ return ret;
}
- return ret;
- }
-
- private static ComplexValueDescriptor convertValue(Property prop) {
- if (prop instanceof PropertySimple) {
- return convertSimpleValue((PropertySimple) prop);
- } else if (prop instanceof PropertyList) {
- return convertListValue((PropertyList) prop);
- } else if (prop instanceof PropertyMap) {
- return convertMapValue((PropertyMap) prop);
+ private static ComplexValueMapDescriptor convertMapValue(PropertyMap prop) {
+ ComplexValueMapDescriptor ret = new ComplexValueMapDescriptor();
+ ret.setPropertyName(prop.getName());
+
+ for (Property el : prop.getMap().values()) {
+ ComplexValueDescriptor value = convertValue(el);
+ addToJAXBElementList(ret.getComplexValue(), Object.class, value,
getTagName(value));
+ }
+
+ return ret;
}
- throw new IllegalArgumentException("Unsupported property type to convert to
a value descriptor: " + prop.getClass());
+ private static <T> void addToJAXBElementList(List<JAXBElement<?
extends T>> list, Class<T> baseClass, T property, QName tagName) {
+ JAXBElement<? extends T> el = new JAXBElement<T>(tagName,
baseClass, property);
+ list.add(el);
+ }
}
- private static ComplexValueSimpleDescriptor convertSimpleValue(PropertySimple prop)
{
- ComplexValueSimpleDescriptor ret = new ComplexValueSimpleDescriptor();
- ret.setPropertyName(prop.getName());
- ret.setValue(prop.getStringValue());
+ private static class ToConfigurationAndDefinition {
- return ret;
- }
-
- private static ComplexValueListDescriptor convertListValue(PropertyList prop) {
- ComplexValueListDescriptor ret = new ComplexValueListDescriptor();
- ret.setPropertyName(prop.getName());
+ public static ConfigurationAndDefinition
createConfigurationAndDefinition(ConfigurationInstanceDescriptor descriptor) {
+ ConfigurationAndDefinition ret = new ConfigurationAndDefinition();
+ Configuration configuration = new Configuration();
+ ConfigurationDefinition definition = new ConfigurationDefinition(null,
null);
+
+ ret.configuration = configuration;
+ ret.definition = definition;
+
+ for(JAXBElement<?> el : descriptor.getConfigurationProperty()) {
+ Object childDescriptor = el.getValue();
+ add(definition, configuration, null, null, childDescriptor);
+ }
+
+ return ret;
+ }
- for(Property el : prop.getList()) {
- ComplexValueDescriptor value = convertValue(el);
- addToJAXBElementList(ret.getComplexValue(), Object.class, value,
getTagName(value));
+ private static void add(ConfigurationDefinition configurationDefinition,
Configuration configuration, PropertyDefinition parentDef, Property parentProp, Object
propertyInstance) {
+ Property prop = null;
+ PropertyDefinition def = null;
+
+ if (propertyInstance instanceof SimplePropertyInstanceDescriptor) {
+ def = convert((ConfigurationProperty)propertyInstance);
+ def.setConfigurationDefinition(configurationDefinition);
+
+ SimplePropertyInstanceDescriptor simpleInstance =
(SimplePropertyInstanceDescriptor) propertyInstance;
+
+ PropertySimple simpleProp = new PropertySimple(simpleInstance.getName(),
simpleInstance.getValue());
+ prop = simpleProp;
+ } else if (propertyInstance instanceof ListPropertyInstanceDescriptor) {
+ def = convert((ConfigurationProperty)propertyInstance);
+ def.setConfigurationDefinition(configurationDefinition);
+
+ ListPropertyInstanceDescriptor listInstance =
(ListPropertyInstanceDescriptor) propertyInstance;
+ PropertyList listProp = new PropertyList(listInstance.getName());
+
+ PropertyDefinition memberDefinition =
((PropertyDefinitionList)def).getMemberDefinition();
+
+ if (listInstance.getValues() != null) {
+ for(JAXBElement<?> val :
listInstance.getValues().getComplexValue()) {
+ ComplexValueDescriptor valDesc = (ComplexValueDescriptor)
val.getValue();
+ Property child = convert(memberDefinition, valDesc);
+ listProp.add(child);
+ }
+ }
+
+ prop = listProp;
+ } else if (propertyInstance instanceof MapPropertyInstanceDescriptor) {
+ def = convert((ConfigurationProperty)propertyInstance);
+ def.setConfigurationDefinition(configurationDefinition);
+
+ MapPropertyInstanceDescriptor mapInstance =
(MapPropertyInstanceDescriptor) propertyInstance;
+ PropertyMap mapProp = new PropertyMap(mapInstance.getName());
+
+ if (mapInstance.getValues() != null) {
+ for(JAXBElement<?> val :
mapInstance.getValues().getComplexValue()) {
+ ComplexValueDescriptor valueDesc = (ComplexValueDescriptor)
val.getValue();
+ PropertyDefinition valueDefinition =
((PropertyDefinitionMap)def).get(valueDesc.getPropertyName());
+
+ Property child = convert(valueDefinition, valueDesc);
+ mapProp.put(child);
+ }
+ }
+
+ prop = mapProp;
+ } else {
+ throw new IllegalArgumentException("Unsupported property instance
type: " + propertyInstance.getClass());
+ }
+
+ if (parentDef != null) {
+ if (parentDef instanceof PropertyDefinitionList) {
+ def.setParentPropertyListDefinition((PropertyDefinitionList)
parentDef);
+ } else if (parentDef instanceof PropertyDefinitionMap) {
+ def.setParentPropertyMapDefinition((PropertyDefinitionMap)
parentDef);
+ }
+ } else {
+ configurationDefinition.put(def);
+ }
+
+ prop.setConfiguration(configuration);
+ if (parentProp != null) {
+ if (parentProp instanceof PropertyList) {
+ prop.setParentList((PropertyList) parentProp);
+ } else if (parentProp instanceof PropertyMap) {
+ prop.setParentMap((PropertyMap) parentProp);
+ }
+ } else {
+ configuration.put(prop);
+ }
+ }
+
+ private static PropertyDefinition convert(ConfigurationProperty def) {
+ try {
+ ConfigurationDescriptor tmp = new ConfigurationDescriptor();
+ tmp.getConfigurationProperty().add(new
JAXBElement<ConfigurationProperty>(getTagName(def), ConfigurationProperty.class,
def));
+ ConfigurationDefinition configDef =
ConfigurationMetadataParser.parse(null, tmp);
+
+ return configDef.getPropertyDefinitions().values().iterator().next();
+ } catch (InvalidPluginDescriptorException e) {
+ throw new IllegalArgumentException(e);
+ }
}
- return ret;
+ private static Property convert(PropertyDefinition definition,
ComplexValueDescriptor value) {
+ Property ret = null;
+
+ if (value instanceof ComplexValueSimpleDescriptor) {
+ ret = new PropertySimple(value.getPropertyName(),
((ComplexValueSimpleDescriptor) value).getValue());
+ } else if (value instanceof ComplexValueListDescriptor) {
+ ComplexValueListDescriptor listValue = (ComplexValueListDescriptor)
value;
+
+ PropertyDefinitionList listDefinition = (PropertyDefinitionList)
definition;
+
+ PropertyList list = new PropertyList(value.getPropertyName());
+
+ for(JAXBElement<?> val : listValue.getComplexValue()) {
+ Property child = convert(listDefinition.getMemberDefinition(),
(ComplexValueDescriptor) val.getValue());
+
+ list.add(child);
+ }
+ ret = list;
+ } else if (value instanceof ComplexValueMapDescriptor) {
+ ComplexValueMapDescriptor mapValue = (ComplexValueMapDescriptor) value;
+
+ PropertyMap map = new PropertyMap(value.getPropertyName());
+ PropertyDefinitionMap mapDefinition = (PropertyDefinitionMap)
definition;
+
+ for(JAXBElement<?> val : mapValue.getComplexValue()) {
+ ComplexValueDescriptor childDesc = (ComplexValueDescriptor)
val.getValue();
+
+ PropertyDefinition childDefinition =
mapDefinition.get(childDesc.getPropertyName());
+
+ Property child = convert(childDefinition, childDesc);
+ map.put(child);
+ }
+
+ ret = map;
+ }
+
+ if (ret.getName() == null) {
+ ret.setName(definition.getName());
+ }
+
+ return ret;
+ }
}
- private static ComplexValueMapDescriptor convertMapValue(PropertyMap prop) {
- ComplexValueMapDescriptor ret = new ComplexValueMapDescriptor();
- ret.setPropertyName(prop.getName());
-
- for (Property el : prop.getMap().values()) {
- ComplexValueDescriptor value = convertValue(el);
- addToJAXBElementList(ret.getComplexValue(), Object.class, value,
getTagName(value));
- }
-
- return ret;
+ /**
+ * A configuration instance is a combination of a configuration definition and a
concrete
+ * configuration instance with defined values. This is used during the config
synchronization
+ * to output the default configuration of an importer directly in the export file so
that the
+ * users have an easy way of modifying that configuration.
+ *
+ * @param definition
+ * @param configuration
+ * @return
+ */
+ public static ConfigurationInstanceDescriptor
createConfigurationInstance(ConfigurationDefinition definition,
+ Configuration configuration) {
+ return ToDescriptor.createConfigurationInstance(definition, configuration);
}
- private static <T> void addToJAXBElementList(List<JAXBElement<? extends
T>> list, Class<T> baseClass, T property, QName tagName) {
- JAXBElement<? extends T> el = new JAXBElement<T>(tagName, baseClass,
property);
- list.add(el);
+ public static ConfigurationAndDefinition
createConfigurationAndDefinition(ConfigurationInstanceDescriptor descriptor) {
+ return
ToConfigurationAndDefinition.createConfigurationAndDefinition(descriptor);
}
}
diff --git
a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtilTest.java
b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtilTest.java
index 2105e7f..02cd29a 100644
---
a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtilTest.java
+++
b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ConfigurationInstanceDescriptorUtilTest.java
@@ -21,8 +21,10 @@ package org.rhq.enterprise.server.xmlschema;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotNull;
import java.io.IOException;
+import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -30,6 +32,7 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.commons.logging.Log;
@@ -39,10 +42,12 @@ import org.testng.annotations.Test;
import org.rhq.core.clientapi.descriptor.configuration.MapProperty;
import org.rhq.core.clientapi.descriptor.configuration.SimpleProperty;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
@@ -73,10 +78,12 @@ public class ConfigurationInstanceDescriptorUtilTest {
}
private static final Marshaller CONFIGURATION_INSTANCE_MARSHALLER;
+ private static final Unmarshaller CONFIGURATION_INSTANCE_UNMARSHALLER;
static {
try {
JAXBContext context =
JAXBContext.newInstance(StandaloneConfigurationInstance.class);
CONFIGURATION_INSTANCE_MARSHALLER = context.createMarshaller();
+ CONFIGURATION_INSTANCE_UNMARSHALLER = context.createUnmarshaller();
} catch (Exception e) {
throw new IllegalStateException("Failed to initialize the configuration
instance marshaller.", e);
}
@@ -216,6 +223,211 @@ public class ConfigurationInstanceDescriptorUtilTest {
//TODO implement
}
+ public void testReverseSimplePropertyConversion() throws Exception {
+ String xml = "" +
+ "<standaloneConfigurationInstance
xmlns:ci='urn:xmlns:rhq-configuration-instance'
xmlns:c='urn:xmlns:rhq-configuration'>" +
+ " <ci:simple-property value='42' name='my-name'
type='integer'/>" +
+ "</standaloneConfigurationInstance>";
+
+ ConfigurationInstanceDescriptor descriptor = (ConfigurationInstanceDescriptor)
CONFIGURATION_INSTANCE_UNMARSHALLER.unmarshal(new StringReader(xml));
+
+ ConfigurationInstanceDescriptorUtil.ConfigurationAndDefinition ccd =
ConfigurationInstanceDescriptorUtil.createConfigurationAndDefinition(descriptor);
+
+ ConfigurationDefinition def = ccd.definition;
+ Configuration conf = ccd.configuration;
+
+ assertEquals(def.getPropertyDefinitions().size(), 1, "Unexpected number of
defined properties");
+ assertEquals(conf.getProperties().size(), 1, "Unexpected number of
properties");
+
+ PropertyDefinition propDef = def.get("my-name");
+ Property prop = conf.get("my-name");
+
+ assertNotNull(propDef, "Could not find the expected property
definition");
+ assertNotNull(prop, "Could not find the expected property");
+
+ assertEquals(propDef.getClass(), PropertyDefinitionSimple.class, "Unexpected
type of the property definition");
+ assertEquals(prop.getClass(), PropertySimple.class, "Unexpecetd type of the
property");
+
+ PropertyDefinitionSimple simpleDef = (PropertyDefinitionSimple) propDef;
+ PropertySimple simpleProp = (PropertySimple) prop;
+
+ assertEquals(simpleDef.getType(), PropertySimpleType.INTEGER, "Unexpected
type of the simple property definition");
+ assertEquals(simpleProp.getIntegerValue(), Integer.valueOf(42), "Unexpected
value of the simple property");
+ }
+
+ public void testReverseListPropertyConversion() throws Exception {
+ String xml = "" +
+ "<standaloneConfigurationInstance
xmlns:ci='urn:xmlns:rhq-configuration-instance'
xmlns:c='urn:xmlns:rhq-configuration'>" +
+ " <ci:list-property name='list'>" +
+ " <c:simple-property name='member'
type='integer'/>" +
+ " <ci:values>" +
+ " <ci:simple-value value='1'/>" +
+ " <ci:simple-value value='2'/>" +
+ " <ci:simple-value value='3'/>" +
+ " </ci:values>" +
+ " </ci:list-property>" +
+ "</standaloneConfigurationInstance>";
+
+ ConfigurationInstanceDescriptor descriptor = (ConfigurationInstanceDescriptor)
CONFIGURATION_INSTANCE_UNMARSHALLER.unmarshal(new StringReader(xml));
+
+ ConfigurationInstanceDescriptorUtil.ConfigurationAndDefinition ccd =
ConfigurationInstanceDescriptorUtil.createConfigurationAndDefinition(descriptor);
+
+ ConfigurationDefinition def = ccd.definition;
+ Configuration conf = ccd.configuration;
+
+ assertEquals(def.getPropertyDefinitions().size(), 1, "Unexpected number of
defined properties");
+ assertEquals(conf.getProperties().size(), 1, "Unexpected number of
properties");
+
+ PropertyDefinition propDef = def.get("list");
+ Property prop = conf.get("list");
+
+ assertNotNull(propDef, "Could not find the expected property
definition");
+ assertNotNull(prop, "Could not find the expected property");
+
+ assertEquals(propDef.getClass(), PropertyDefinitionList.class, "Unexpected
type of the property definition");
+ assertEquals(prop.getClass(), PropertyList.class, "Unexpecetd type of the
property");
+
+ PropertyDefinitionList listDef = (PropertyDefinitionList) propDef;
+ PropertyList listProp = (PropertyList) prop;
+
+ PropertyDefinition memberDef = listDef.getMemberDefinition();
+ assertEquals(memberDef.getClass(), PropertyDefinitionSimple.class,
"Unexpected type of the list member property definition");
+
+ PropertyDefinitionSimple memberSimpleDef = (PropertyDefinitionSimple) memberDef;
+ assertEquals(memberSimpleDef.getName(), "member");
+ assertEquals(memberSimpleDef.getType(), PropertySimpleType.INTEGER);
+
+ assertEquals(listProp.getList().size(), 3, "Unexpected number of list
members");
+
+ for(int i = 0; i < 3; ++i) {
+ Property memberProp = listProp.getList().get(i);
+ assertEquals(memberProp.getClass(), PropertySimple.class, "Unexpected
type of the property in the list on index " + i);
+ assertEquals(memberProp.getName(), "member");
+ assertEquals(((PropertySimple)memberProp).getIntegerValue(),
Integer.valueOf(i + 1));
+ }
+ }
+
+ public void testReverseMapPropertyConversion() throws Exception {
+ String xml = "" +
+ "<standaloneConfigurationInstance
xmlns:ci='urn:xmlns:rhq-configuration-instance'
xmlns:c='urn:xmlns:rhq-configuration'>" +
+ " <ci:map-property name='map'>" +
+ " <c:simple-property name='m1'
type='integer'/>" +
+ " <c:simple-property name='m2'
type='string'/>" +
+ " <ci:values>" +
+ " <ci:simple-value property-name='m1'
value='1'/>" +
+ " <ci:simple-value property-name='m2'
value='v'/>" +
+ " </ci:values>" +
+ " </ci:map-property>" +
+ "</standaloneConfigurationInstance>";
+
+ ConfigurationInstanceDescriptor descriptor = (ConfigurationInstanceDescriptor)
CONFIGURATION_INSTANCE_UNMARSHALLER.unmarshal(new StringReader(xml));
+
+ ConfigurationInstanceDescriptorUtil.ConfigurationAndDefinition ccd =
ConfigurationInstanceDescriptorUtil.createConfigurationAndDefinition(descriptor);
+
+ ConfigurationDefinition def = ccd.definition;
+ Configuration conf = ccd.configuration;
+
+ assertEquals(def.getPropertyDefinitions().size(), 1, "Unexpected number of
defined properties");
+ assertEquals(conf.getProperties().size(), 1, "Unexpected number of
properties");
+
+ PropertyDefinition propDef = def.get("map");
+ Property prop = conf.get("map");
+
+ assertNotNull(propDef, "Could not find the expected property
definition");
+ assertNotNull(prop, "Could not find the expected property");
+
+ assertEquals(propDef.getClass(), PropertyDefinitionMap.class, "Unexpected
type of the property definition");
+ assertEquals(prop.getClass(), PropertyMap.class, "Unexpecetd type of the
property");
+
+ PropertyDefinitionMap mapDef = (PropertyDefinitionMap) propDef;
+ PropertyMap mapProp = (PropertyMap) prop;
+
+ assertEquals(mapDef.getPropertyDefinitions().size(), 2, "Unexpected number
of map member definitions");
+ assertEquals(mapProp.getMap().size(), 2, "Unexpected number of map
members");
+
+ PropertyDefinition m1Def = mapDef.get("m1");
+ PropertyDefinition m2Def = mapDef.get("m2");
+ Property m1Prop = mapProp.get("m1");
+ Property m2Prop = mapProp.get("m2");
+
+ assertEquals(m1Def.getClass(), PropertyDefinitionSimple.class);
+ assertEquals(m2Def.getClass(), PropertyDefinitionSimple.class);
+ assertEquals(m1Prop.getClass(), PropertySimple.class);
+ assertEquals(m2Prop.getClass(), PropertySimple.class);
+
+ PropertyDefinitionSimple m1SimpleDef = (PropertyDefinitionSimple) m1Def;
+ PropertyDefinitionSimple m2SimpleDef = (PropertyDefinitionSimple) m2Def;
+ PropertySimple m1SimpleProp = (PropertySimple) m1Prop;
+ PropertySimple m2SimpleProp = (PropertySimple) m2Prop;
+
+ assertEquals(m1SimpleDef.getName(), "m1");
+ assertEquals(m2SimpleDef.getName(), "m2");
+ assertEquals(m1SimpleDef.getType(), PropertySimpleType.INTEGER);
+ assertEquals(m2SimpleDef.getType(), PropertySimpleType.STRING);
+
+ assertEquals(m1SimpleProp.getName(), "m1");
+ assertEquals(m2SimpleProp.getName(), "m2");
+ assertEquals(m1SimpleProp.getIntegerValue(), Integer.valueOf(1));
+ assertEquals(m2SimpleProp.getStringValue(), "v");
+ }
+
+ public void testReverseListOfMapsConversion() throws Exception {
+ String xml = "" +
+ "<standaloneConfigurationInstance
xmlns:ci='urn:xmlns:rhq-configuration-instance'
xmlns:c='urn:xmlns:rhq-configuration'>" +
+ " <ci:list-property name='list'>" +
+ " <c:map-property name='map'>" +
+ " <c:simple-property name='m1'
type='integer'/>" +
+ " <c:simple-property name='m2'
type='string'/>" +
+ " </c:map-property>" +
+ " <ci:values>" +
+ " <ci:map-value>" +
+ " <ci:simple-value property-name='m1'
value='1'/>" +
+ " <ci:simple-value property-name='m2'
value='m1'/>" +
+ " </ci:map-value>" +
+ " <ci:map-value>" +
+ " <ci:simple-value property-name='m1'
value='2'/>" +
+ " <ci:simple-value property-name='m2'
value='m2'/>" +
+ " </ci:map-value>" +
+ " </ci:values>" +
+ " </ci:list-property>" +
+ "</standaloneConfigurationInstance>";
+
+ ConfigurationInstanceDescriptor descriptor = (ConfigurationInstanceDescriptor)
CONFIGURATION_INSTANCE_UNMARSHALLER.unmarshal(new StringReader(xml));
+
+ ConfigurationInstanceDescriptorUtil.ConfigurationAndDefinition ccd =
ConfigurationInstanceDescriptorUtil.createConfigurationAndDefinition(descriptor);
+
+ ConfigurationDefinition def = ccd.definition;
+ Configuration conf = ccd.configuration;
+
+ assertEquals(def.getPropertyDefinitions().size(), 1, "Unexpected number of
defined properties");
+ assertEquals(conf.getProperties().size(), 1, "Unexpected number of
properties");
+
+ PropertyDefinitionList listDef = (PropertyDefinitionList)
def.get("list");
+ PropertyList listProp = (PropertyList) conf.get("list");
+
+ PropertyDefinitionMap mapDef = (PropertyDefinitionMap)
listDef.getMemberDefinition();
+ PropertyDefinitionSimple m1Def = (PropertyDefinitionSimple)
mapDef.get("m1");
+ PropertyDefinitionSimple m2Def = (PropertyDefinitionSimple)
mapDef.get("m2");
+
+ assertEquals(mapDef.getName(), "map");
+ assertEquals(m1Def.getType(), PropertySimpleType.INTEGER);
+ assertEquals(m2Def.getType(), PropertySimpleType.STRING);
+
+ assertEquals(listProp.getList().size(), 2, "Unexpected number of maps in the
list");
+
+ PropertyMap firstMapValue = (PropertyMap) listProp.getList().get(0);
+ PropertyMap secondMapValue = (PropertyMap) listProp.getList().get(1);
+
+ assertEquals(firstMapValue.getName(), "map");
+ assertEquals(secondMapValue.getName(), "map");
+
+ assertEquals(firstMapValue.getSimpleValue("m1", null), "1",
"Unexpected value of m1 property in the first map.");
+ assertEquals(firstMapValue.getSimpleValue("m2", null), "m1",
"Unexpected value of m2 property in the first map.");
+
+ assertEquals(secondMapValue.getSimpleValue("m1", null), "2",
"Unexpected value of m1 property in the second map.");
+ assertEquals(secondMapValue.getSimpleValue("m2", null), "m2",
"Unexpected value of m2 property in the second map.");
+ }
+
private static void logInstance(String message, ConfigurationInstanceDescriptor
instance) throws JAXBException,
IOException {
StringWriter wrt = new StringWriter();