Hi Francesco Have you considered using the MetaTypeReader from Felix' MetyType implementation[0]? I've used it before and found it easy enough to use.
It's only a test dependency, and you don't need to worry about your implementation being in sync with the spec/Felix' implementation. Regards Julian [0] https://github.com/apache/felix/blob/trunk/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java On Mon, Jul 2, 2018 at 4:57 PM, <f...@apache.org> wrote: > Author: frm > Date: Mon Jul 2 14:57:25 2018 > New Revision: 1834852 > > URL: http://svn.apache.org/viewvc?rev=1834852&view=rev > Log: > OAK-6770 - Test the metatype information descriptors > > Added: > > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/MetatypeInformation.java > (with props) > Modified: > > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreFactoryTest.java > > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreMonitorServiceTest.java > > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceTest.java > > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceTest.java > > Added: > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/MetatypeInformation.java > URL: > http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/MetatypeInformation.java?rev=1834852&view=auto > ============================================================================== > --- > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/MetatypeInformation.java > (added) > +++ > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/MetatypeInformation.java > Mon Jul 2 14:57:25 2018 > @@ -0,0 +1,267 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you under the Apache License, Version 2.0 (the > + * "License"); you may not use this file except in compliance > + * with the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, > + * software distributed under the License is distributed on an > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > + * KIND, either express or implied. See the License for the > + * specific language governing permissions and limitations > + * under the License. > + */ > + > +package org.apache.jackrabbit.oak.segment.osgi; > + > +import java.io.InputStream; > +import java.util.HashSet; > +import java.util.Set; > + > +import javax.xml.parsers.DocumentBuilder; > +import javax.xml.parsers.DocumentBuilderFactory; > + > +import org.w3c.dom.Document; > +import org.w3c.dom.Element; > +import org.w3c.dom.NodeList; > + > +class MetatypeInformation { > + > + static MetatypeInformation open(InputStream stream) throws Exception { > + DocumentBuilderFactory factory = > DocumentBuilderFactory.newInstance(); > + DocumentBuilder builder = factory.newDocumentBuilder(); > + Document document = builder.parse(stream); > + return new MetatypeInformation(document.getDocumentElement()); > + } > + > + private static boolean hasAttribute(Element element, String name, String > value) { > + return element.hasAttribute(name) && > element.getAttribute(name).equals(value); > + } > + > + private final Element root; > + > + private MetatypeInformation(Element root) { > + this.root = root; > + } > + > + ObjectClassDefinition getObjectClassDefinition(String id) { > + return new ObjectClassDefinition(id); > + } > + > + class ObjectClassDefinition { > + > + private final String id; > + > + private ObjectClassDefinition(String id) { > + this.id = id; > + } > + > + HasAttributeDefinition hasAttributeDefinition(String id) { > + return new HasAttributeDefinition(this.id, id); > + } > + > + } > + > + class HasAttributeDefinition { > + > + private final String ocd; > + > + private final String id; > + > + private String type; > + > + private String defaultValue; > + > + private String cardinality; > + > + private String[] options; > + > + private HasAttributeDefinition(String ocd, String id) { > + this.ocd = ocd; > + this.id = id; > + } > + > + HasAttributeDefinition withStringType() { > + this.type = "String"; > + return this; > + } > + > + HasAttributeDefinition withLongType() { > + this.type = "Long"; > + return this; > + } > + > + HasAttributeDefinition withDoubleType() { > + this.type = "Double"; > + return this; > + } > + > + HasAttributeDefinition withFloatType() { > + this.type = "Float"; > + return this; > + } > + > + HasAttributeDefinition withIntegerType() { > + this.type = "Integer"; > + return this; > + } > + > + HasAttributeDefinition withByteType() { > + this.type = "Byte"; > + return this; > + } > + > + HasAttributeDefinition withCharType() { > + this.type = "Char"; > + return this; > + } > + > + HasAttributeDefinition withBooleanType() { > + this.type = "Boolean"; > + return this; > + } > + > + HasAttributeDefinition withShortType() { > + this.type = "Short"; > + return this; > + } > + > + HasAttributeDefinition withDefaultValue(String defaultValue) { > + this.defaultValue = defaultValue; > + return this; > + } > + > + HasAttributeDefinition withCardinality(String cardinality) { > + this.cardinality = cardinality; > + return this; > + } > + > + HasAttributeDefinition withOptions(String... options) { > + this.options = options; > + return this; > + } > + > + boolean check() { > + NodeList ocds = root.getElementsByTagName("OCD"); > + for (int i = 0; i < ocds.getLength(); i++) { > + Element ocd = (Element) ocds.item(i); > + if (hasAttribute(ocd, "id", this.ocd)) { > + return checkOCD(ocd); > + } > + } > + return false; > + } > + > + private boolean checkOCD(Element ocd) { > + NodeList ads = ocd.getElementsByTagName("AD"); > + for (int i = 0; i < ads.getLength(); i++) { > + Element ad = (Element) ads.item(i); > + if (hasAttribute(ad, "id", id)) { > + return checkAD(ad); > + } > + } > + return false; > + } > + > + private boolean checkAD(Element ad) { > + if (type != null && !hasAttribute(ad, "type", type)) { > + return false; > + } > + if (defaultValue != null && !hasAttribute(ad, "default", > defaultValue)) { > + return false; > + } > + if (cardinality != null && !hasAttribute(ad, "cardinality", > cardinality)) { > + return false; > + } > + if (options != null) { > + Set<String> optionValues = new HashSet<>(); > + > + NodeList optionElements = ad.getElementsByTagName("Option"); > + for (int i = 0; i < optionElements.getLength(); i++) { > + Element optionElement = (Element) optionElements.item(i); > + optionValues.add(optionElement.getAttribute("value")); > + } > + > + if (options.length != optionValues.size()) { > + return false; > + } > + > + for (String option : options) { > + if (!optionValues.contains(option)) { > + return false; > + } > + } > + } > + return true; > + } > + > + } > + > + HasDesignate hasDesignate() { > + return new HasDesignate(); > + } > + > + class HasDesignate { > + > + private String pid; > + > + private String factoryPid; > + > + private String reference; > + > + private HasDesignate() { > + // Prevent instantiation outside of this class. > + } > + > + HasDesignate withPid(String pid) { > + this.pid = pid; > + return this; > + } > + > + HasDesignate withFactoryPid(String factoryPid) { > + this.factoryPid = factoryPid; > + return this; > + } > + > + HasDesignate withReference(String reference) { > + this.reference = reference; > + return this; > + } > + > + boolean check() { > + NodeList designates = root.getElementsByTagName("Designate"); > + for (int i = 0; i < designates.getLength(); i++) { > + if (checkDesignate((Element) designates.item(i))) { > + return true; > + } > + } > + return false; > + } > + > + private boolean checkDesignate(Element element) { > + if (pid != null && !hasAttribute(element, "pid", pid)) { > + return false; > + } > + if (factoryPid != null && !hasAttribute(element, "factoryPid", > factoryPid)) { > + return false; > + } > + if (reference != null) { > + NodeList objects = element.getElementsByTagName("Object"); > + for (int i = 0; i < objects.getLength(); i++) { > + if (hasAttribute((Element) objects.item(i), "ocdref", > reference)) { > + return true; > + } > + } > + return false; > + } > + return true; > + } > + > + } > + > +} > > Propchange: > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/MetatypeInformation.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreFactoryTest.java > URL: > http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreFactoryTest.java?rev=1834852&r1=1834851&r2=1834852&view=diff > ============================================================================== > --- > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreFactoryTest.java > (original) > +++ > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreFactoryTest.java > Mon Jul 2 14:57:25 2018 > @@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.segmen > > import static org.junit.Assert.assertTrue; > > +import > org.apache.jackrabbit.oak.segment.osgi.MetatypeInformation.ObjectClassDefinition; > import org.junit.Test; > > public class SegmentNodeStoreFactoryTest { > @@ -69,6 +70,37 @@ public class SegmentNodeStoreFactoryTest > .withBind("bindStatisticsProvider") > .withUnbind("unbindStatisticsProvider") > .check()); > + } > + > + @Test > + public void testMetatypeInformation() throws Exception { > + MetatypeInformation mi = > MetatypeInformation.open(getClass().getResourceAsStream("/OSGI-INF/metatype/org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory.xml")); > + assertTrue(mi.hasDesignate() > + > .withPid("org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory") > + > .withFactoryPid("org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory") > + > .withReference("org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory") > + .check()); > > + ObjectClassDefinition ocd = > mi.getObjectClassDefinition("org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory"); > + assertTrue(ocd.hasAttributeDefinition("role") > + .withStringType() > + .check()); > + assertTrue(ocd.hasAttributeDefinition("customBlobStore") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("customBlobStore") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("customSegmentStore") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("registerDescriptors") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > } > + > } > > Modified: > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreMonitorServiceTest.java > URL: > http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreMonitorServiceTest.java?rev=1834852&r1=1834851&r2=1834852&view=diff > ============================================================================== > --- > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreMonitorServiceTest.java > (original) > +++ > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreMonitorServiceTest.java > Mon Jul 2 14:57:25 2018 > @@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.segmen > > import static org.junit.Assert.assertTrue; > > +import > org.apache.jackrabbit.oak.segment.osgi.MetatypeInformation.ObjectClassDefinition; > import org.junit.Test; > > public class SegmentNodeStoreMonitorServiceTest { > @@ -41,4 +42,20 @@ public class SegmentNodeStoreMonitorServ > .withUnbind("unbindSnsStatsMBean") > .check()); > } > + > + @Test > + public void testMetatypeInformation() throws Exception { > + MetatypeInformation mi = > MetatypeInformation.open(getClass().getResourceAsStream("/OSGI-INF/metatype/org.apache.jackrabbit.oak.segment.SegmentNodeStoreMonitorService.xml")); > + assertTrue(mi.hasDesignate() > + > .withPid("org.apache.jackrabbit.oak.segment.SegmentNodeStoreMonitorService") > + > .withReference("org.apache.jackrabbit.oak.segment.SegmentNodeStoreMonitorService") > + .check()); > + > + ObjectClassDefinition ocd = > mi.getObjectClassDefinition("org.apache.jackrabbit.oak.segment.SegmentNodeStoreMonitorService"); > + assertTrue(ocd.hasAttributeDefinition("commitsTrackerWriterGroups") > + .withStringType() > + .withCardinality("2147483647") > + .check()); > + > + } > } > > Modified: > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceTest.java > URL: > http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceTest.java?rev=1834852&r1=1834851&r2=1834852&view=diff > ============================================================================== > --- > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceTest.java > (original) > +++ > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceTest.java > Mon Jul 2 14:57:25 2018 > @@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.segmen > > import static org.junit.Assert.assertTrue; > > +import > org.apache.jackrabbit.oak.segment.osgi.MetatypeInformation.ObjectClassDefinition; > import org.junit.Test; > > public class SegmentNodeStoreServiceTest { > @@ -141,4 +142,105 @@ public class SegmentNodeStoreServiceTest > .withUnbind("unbindStatisticsProvider") > .check()); > } > + > + @Test > + public void testMetatypeInformation() throws Exception { > + MetatypeInformation mi = > MetatypeInformation.open(getClass().getResourceAsStream("/OSGI-INF/metatype/org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.xml")); > + assertTrue(mi.hasDesignate() > + > .withPid("org.apache.jackrabbit.oak.segment.SegmentNodeStoreService") > + > .withReference("org.apache.jackrabbit.oak.segment.SegmentNodeStoreService") > + .check()); > + > + ObjectClassDefinition ocd = > mi.getObjectClassDefinition("org.apache.jackrabbit.oak.segment.SegmentNodeStoreService"); > + assertTrue(ocd.hasAttributeDefinition("repository.home") > + .withStringType() > + .check()); > + assertTrue(ocd.hasAttributeDefinition("tarmk.mode") > + .withStringType() > + .check()); > + assertTrue(ocd.hasAttributeDefinition("tarmk.size") > + .withIntegerType() > + .withDefaultValue("256") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("segmentCache.size") > + .withIntegerType() > + .withDefaultValue("256") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("stringCache.size") > + .withIntegerType() > + .withDefaultValue("256") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("templateCache.size") > + .withIntegerType() > + .withDefaultValue("64") > + .check()); > + > assertTrue(ocd.hasAttributeDefinition("stringDeduplicationCache.size") > + .withIntegerType() > + .withDefaultValue("15000") > + .check()); > + > assertTrue(ocd.hasAttributeDefinition("templateDeduplicationCache.size") > + .withIntegerType() > + .withDefaultValue("3000") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("nodeDeduplicationCache.size") > + .withIntegerType() > + .withDefaultValue("1048576") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("pauseCompaction") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("compaction.retryCount") > + .withIntegerType() > + .withDefaultValue("5") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("compaction.force.timeout") > + .withIntegerType() > + .withDefaultValue("60") > + .check()); > + > assertTrue(ocd.hasAttributeDefinition("compaction.sizeDeltaEstimation") > + .withLongType() > + .withDefaultValue("1073741824") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("compaction.disableEstimation") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + > assertTrue(ocd.hasAttributeDefinition("compaction.retainedGenerations") > + .withIntegerType() > + .withDefaultValue("2") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("compaction.memoryThreshold") > + .withIntegerType() > + .withDefaultValue("15") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("compaction.progressLog") > + .withLongType() > + .withDefaultValue("-1") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("standby") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("customBlobStore") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("customSegmentStore") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("repository.backup.dir") > + .withStringType() > + .check()); > + assertTrue(ocd.hasAttributeDefinition("blobGcMaxAgeInSecs") > + .withLongType() > + .withDefaultValue("86400") > + .check()); > + > assertTrue(ocd.hasAttributeDefinition("blobTrackSnapshotIntervalInSecs") > + .withLongType() > + .withDefaultValue("43200") > + .check()); > + } > + > } > > Modified: > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceTest.java > URL: > http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceTest.java?rev=1834852&r1=1834851&r2=1834852&view=diff > ============================================================================== > --- > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceTest.java > (original) > +++ > jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceTest.java > Mon Jul 2 14:57:25 2018 > @@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.segmen > > import static org.junit.Assert.assertTrue; > > +import > org.apache.jackrabbit.oak.segment.osgi.MetatypeInformation.ObjectClassDefinition; > import org.junit.Test; > > public class StandbyStoreServiceTest { > @@ -75,4 +76,52 @@ public class StandbyStoreServiceTest { > .check()); > } > > + @Test > + public void testMetatypeInformation() throws Exception { > + MetatypeInformation mi = > MetatypeInformation.open(getClass().getResourceAsStream("/OSGI-INF/metatype/org.apache.jackrabbit.oak.segment.standby.store.StandbyStoreService.xml")); > + assertTrue(mi.hasDesignate() > + > .withPid("org.apache.jackrabbit.oak.segment.standby.store.StandbyStoreService") > + > .withReference("org.apache.jackrabbit.oak.segment.standby.store.StandbyStoreService") > + .check()); > + > + ObjectClassDefinition ocd = > mi.getObjectClassDefinition("org.apache.jackrabbit.oak.segment.standby.store.StandbyStoreService"); > + > assertTrue(ocd.hasAttributeDefinition("org.apache.sling.installer.configuration.persist") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("mode") > + .withStringType() > + .withDefaultValue("primary") > + .withOptions("primary", "standby") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("port") > + .withIntegerType() > + .withDefaultValue("8023") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("primary.host") > + .withStringType() > + .withDefaultValue("127.0.0.1") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("interval") > + .withIntegerType() > + .withDefaultValue("5") > + .check()); > + > assertTrue(ocd.hasAttributeDefinition("primary.allowed-client-ip-ranges") > + .withStringType() > + .withCardinality("2147483647") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("secure") > + .withBooleanType() > + .withDefaultValue("false") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("standby.readtimeout") > + .withIntegerType() > + .withDefaultValue("60000") > + .check()); > + assertTrue(ocd.hasAttributeDefinition("standby.autoclean") > + .withBooleanType() > + .withDefaultValue("true") > + .check()); > + } > + > } > >