blob: c6936b3dac6f7fc1648357b6aa8734c16a3241fd [file] [log] [blame]
/*
* 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.geode.internal.config;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.List;
import java.util.Set;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.apache.geode.cache.configuration.CacheConfig;
import org.apache.geode.cache.configuration.CacheElement;
import org.apache.geode.cache.configuration.GatewayReceiverConfig;
import org.apache.geode.cache.configuration.RegionConfig;
import org.apache.geode.internal.lang.SystemPropertyHelper;
import org.apache.geode.management.configuration.RegionType;
public class JAXBServiceTest {
private String xml;
private CacheConfig unmarshalled;
private JAXBService service;
private JAXBService service2;
@Rule
public RestoreSystemProperties restore = new RestoreSystemProperties();
@Before
public void setUp() {
service = new JAXBService(CacheConfig.class, ElementOne.class, ElementTwo.class);
service.validateWithLocalCacheXSD();
service2 = new JAXBService(CacheConfig.class);
service2.validateWithLocalCacheXSD();
}
@Test
public void getPackagesToScanWithoutSystemProperty() {
Set<String> packages = JAXBService.getPackagesToScan();
assertThat(packages).containsExactly("*");
}
@Test
public void getPackagesToScanWithSystemProperty() {
System.setProperty("geode." + SystemPropertyHelper.PACKAGES_TO_SCAN,
"org.apache.geode,io.pivotal");
Set<String> packages = JAXBService.getPackagesToScan();
assertThat(packages).containsExactly("org.apache.geode", "io.pivotal");
}
@Test
public void testCacheMarshall() {
CacheConfig cacheConfig = new CacheConfig();
setBasicValues(cacheConfig);
xml = service.marshall(cacheConfig);
System.out.println(xml);
// cache has the default namespace
assertThat(xml).contains("xmlns=\"http://geode.apache.org/schema/cache\"");
assertThat(xml).contains(
"xsi:schemaLocation=\"http://geode.apache.org/schema/cache http://geode.apache.org/schema/cache/cache-1.0.xsd\"");
assertThat(xml).contains("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
assertThat(xml).contains("</cache>");
unmarshalled = service.unMarshall(xml);
}
@Test
public void invalidXmlShouldFail() {
CacheConfig cacheConfig = new CacheConfig();
// missing version attribute
assertThatThrownBy(() -> service.marshall(cacheConfig))
.hasStackTraceContaining("Attribute 'version' must appear on element 'cache'");
}
@Test
public void testCacheOneMarshall() {
CacheConfig cache = new CacheConfig();
setBasicValues(cache);
cache.getCustomCacheElements().add(new ElementOne("test"));
xml = service.marshall(cache);
System.out.println(xml);
// cache has the default namespace
assertThat(xml).contains("xmlns=\"http://geode.apache.org/schema/cache\"");
assertThat(xml).contains("custom-one>");
}
@Test
public void testMixMarshall() {
CacheConfig cache = new CacheConfig();
setBasicValues(cache);
cache.getCustomCacheElements().add(new ElementOne("testOne"));
xml = service.marshall(cache);
System.out.println(xml);
assertThat(xml).contains("custom-one>");
unmarshalled = service2.unMarshall(xml);
unmarshalled.getCustomCacheElements().add(new ElementTwo("testTwo"));
// xml generated wtih CacheConfigTwo has both elements in there.
xml = service.marshall(unmarshalled);
System.out.println(xml);
assertThat(xml).contains("custom-one>");
assertThat(xml).contains("custom-two>");
assertThat(xml).containsPattern("xmlns=\"http://geode.apache.org/schema/cache\"");
assertThat(xml).containsPattern("xmlns:ns\\d=\"http://geode.apache.org/schema/CustomOne\"");
assertThat(xml).containsPattern("xmlns:ns\\d=\"http://geode.apache.org/schema/CustomTwo\"");
}
@Test
public void xmlWithCustomElementsCanBeUnMarshalledByAnotherService() {
CacheConfig cache = new CacheConfig();
setBasicValues(cache);
cache.getCustomCacheElements().add(new ElementOne("test"));
cache.getCustomCacheElements().add(new ElementTwo("test"));
String prettyXml = service.marshall(cache);
System.out.println(prettyXml);
CacheConfig cacheConfig = service2.unMarshall(prettyXml);
List elements = cacheConfig.getCustomCacheElements();
assertThat(elements.get(0)).isNotInstanceOf(ElementOne.class);
assertThat(elements.get(1)).isNotInstanceOf(ElementTwo.class);
String uglyXml = service2.marshall(cacheConfig);
System.out.println(uglyXml);
assertThat(uglyXml).isNotEqualTo(prettyXml);
// the xml can be unmarshalled correctly by the first service
String newXml = service.marshall(service.unMarshall(uglyXml));
assertThat(newXml).isEqualTo(prettyXml);
}
@Test
public void unmarshallPartialElement() {
String xml = "<region name=\"one\">\n"
+ " <region-attributes scope=\"distributed-ack\" data-policy=\"replicate\"/>\n"
+ " </region>";
RegionConfig config = service2.unMarshall(xml, RegionConfig.class);
assertThat(config.getName()).isEqualTo("one");
}
@Test
public void unmarshallAnyElement() {
String xml = "<region name=\"one\">\n"
+ " <region-attributes scope=\"distributed-ack\" data-policy=\"replicate\"/>\n"
+ " <custom:any xmlns:custom=\"http://geode.apache.org/schema/custom\" id=\"any\"/>"
+ " </region>";
RegionConfig config = service2.unMarshall(xml, RegionConfig.class);
assertThat(config.getName()).isEqualTo("one");
assertThat(config.getCustomRegionElements()).hasSize(1);
}
@Test
public void unmarshallIgnoresUnknownProperties() {
// say xml has a type attribute that is removed in the new version
String existingXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<cache version=\"1.0\" xsi:schemaLocation=\"http://geode.apache.org/schema/cache "
+ "http://geode.apache.org/schema/cache/cache-1.0.xsd\" "
+ "xmlns=\"http://geode.apache.org/schema/cache\" "
+ "xmlns:ns2=\"http://geode.apache.org/schema/CustomOne\" "
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" + " <ns2:custom-one>\n"
+ " <ns2:id>one</ns2:id>\n" + " <ns2:type>onetype</ns2:type>\n"
+ " <ns2:value>onevalue</ns2:value>\n" + " </ns2:custom-one>\n" + "</cache>";
CacheConfig cacheConfig = service.unMarshall(existingXML);
List elements = cacheConfig.getCustomCacheElements();
assertThat(elements.get(0)).isInstanceOf(ElementOne.class);
}
@Test
public void marshalOlderNameSpace() {
String xml =
"<cache xsi:schemaLocation=\"http://schema.pivotal.io/gemfire/cache http://schema.pivotal.io/gemfire/cache/cache-8.1.xsd\"\n"
+
" version=\"8.1\"\n" +
" xmlns=\"http://schema.pivotal.io/gemfire/cache\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
" <region name=\"one\">\n" +
" <region-attributes scope=\"distributed-ack\" data-policy=\"replicate\"/>\n" +
" </region>\n" +
"</cache>";
CacheConfig cacheConfig = service2.unMarshall(xml);
assertThat(cacheConfig.getRegions()).hasSize(1);
assertThat(cacheConfig.getRegions().get(0).getName()).isEqualTo("one");
}
@Test
public void marshallNoNameSpace() {
String xml = "<cache version=\"1.0\">\n" +
" <region name=\"one\">\n" +
" <region-attributes scope=\"distributed-ack\" data-policy=\"replicate\"/>\n" +
" </region>\n" +
"</cache>";
CacheConfig cacheConfig = service2.unMarshall(xml);
assertThat(cacheConfig.getRegions()).hasSize(1);
assertThat(cacheConfig.getRegions().get(0).getName()).isEqualTo("one");
}
private void setBasicValues(CacheConfig cache) {
GatewayReceiverConfig receiver = new GatewayReceiverConfig();
receiver.setBindAddress("localhost");
receiver.setEndPort("8080");
receiver.setManualStart(false);
receiver.setStartPort("6000");
RegionConfig region = new RegionConfig();
region.setName("testRegion");
region.setType(RegionType.REPLICATE);
cache.setCopyOnRead(true);
cache.setGatewayReceiver(receiver);
cache.setVersion("1.0");
cache.getRegions().add(region);
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"id", "value"})
@XmlRootElement(name = "custom-one", namespace = "http://geode.apache.org/schema/CustomOne")
public static class ElementOne extends CacheElement {
@XmlElement(name = "id", namespace = "http://geode.apache.org/schema/CustomOne")
private String id;
@XmlElement(name = "value", namespace = "http://geode.apache.org/schema/CustomOne")
private String value;
public ElementOne() {
// nothing
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public ElementOne(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
public void setId(String value) {
id = value;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"id", "value"})
@XmlRootElement(name = "custom-two", namespace = "http://geode.apache.org/schema/CustomTwo")
public static class ElementTwo extends CacheElement {
@XmlElement(name = "id", namespace = "http://geode.apache.org/schema/CustomTwo")
private String id;
@XmlElement(name = "value", namespace = "http://geode.apache.org/schema/CustomTwo")
private String value;
public ElementTwo() {
// nothing
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public ElementTwo(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
public void setId(String value) {
id = value;
}
}
}