/* * 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.activemq.artemis.core.config.impl; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration; import org.apache.activemq.artemis.core.config.Configuration; import org.apache.activemq.artemis.core.config.FileDeploymentManager; import org.apache.activemq.artemis.core.config.HAPolicyConfiguration; import org.apache.activemq.artemis.core.config.WildcardConfiguration; import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration; import org.apache.activemq.artemis.core.deployers.impl.FileConfigurationParser; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec; import org.junit.Assert; import org.junit.Test; public class FileConfigurationParserTest extends ActiveMQTestBase { /** * These "InvalidConfigurationTest*.xml" files are modified copies of {@value * ConfigurationTest-full-config.xml}, so just diff it for changes, e.g. * <p> * <pre> * diff ConfigurationTest-full-config.xml InvalidConfigurationTest4.xml * </pre> * * @throws Exception */ @Test public void testSchemaValidation() throws Exception { for (int i = 0; i < 7; i++) { String filename = "InvalidConfigurationTest" + i + ".xml"; FileConfiguration fc = new FileConfiguration(); FileDeploymentManager deploymentManager = new FileDeploymentManager(filename); deploymentManager.addDeployable(fc); try { deploymentManager.readConfiguration(); fail("parsing should have failed for " + filename); } catch (java.lang.IllegalStateException e) { Throwable cause = e.getCause(); assertTrue("must have been org.xml.sax.SAXParseException", cause instanceof org.xml.sax.SAXParseException); } } } @Test public void testDivertRoutingNameIsNotRequired() throws Exception { String filename = "divertRoutingNameNotRequired.xml"; FileConfiguration fc = new FileConfiguration(); FileDeploymentManager deploymentManager = new FileDeploymentManager(filename); deploymentManager.addDeployable(fc); deploymentManager.readConfiguration(); } @Test public void testParsingClusterConnectionURIs() throws Exception { FileConfigurationParser parser = new FileConfigurationParser(); String configStr = firstPart + "<cluster-connections>\n" + " <cluster-connection-uri name=\"my-cluster\" address=\"multicast://my-discovery-group?messageLoadBalancingType=STRICT;retryInterval=333;connectorName=netty-connector;maxHops=1\"/>\n" + "</cluster-connections>\n" + lastPart; ByteArrayInputStream input = new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)); Configuration config = parser.parseMainConfig(input); Assert.assertEquals(1, config.getClusterConfigurations().size()); Assert.assertEquals("my-discovery-group", config.getClusterConfigurations().get(0).getDiscoveryGroupName()); Assert.assertEquals(333, config.getClusterConfigurations().get(0).getRetryInterval()); } @Test public void testWildcardConfiguration() throws Exception { FileConfigurationParser parser = new FileConfigurationParser(); String configStr = firstPart + "<wildcard-addresses>\n<enabled>true</enabled>\n<delimiter>/</delimiter>\n<any-words>></any-words></wildcard-addresses>" + lastPart; ByteArrayInputStream input = new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)); Configuration config = parser.parseMainConfig(input); WildcardConfiguration wildCard = config.getWildcardConfiguration(); assertEquals('/', wildCard.getDelimiter()); assertTrue(wildCard.isEnabled()); assertEquals('>', wildCard.getAnyWords()); assertEquals('*', wildCard.getSingleWord()); } @Test public void testParsingHaSharedStoreWaitForActivation() throws Exception { FileConfigurationParser parser = new FileConfigurationParser(); String configStr = firstPart + "<ha-policy><shared-store><master><wait-for-activation>false</wait-for-activation></master></shared-store></ha-policy>" + lastPart; ByteArrayInputStream input = new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)); Configuration config = parser.parseMainConfig(input); HAPolicyConfiguration haConfig = config.getHAPolicyConfiguration(); assertTrue(haConfig instanceof SharedStoreMasterPolicyConfiguration); SharedStoreMasterPolicyConfiguration masterConfig = (SharedStoreMasterPolicyConfiguration) haConfig; assertFalse(masterConfig.isWaitForActivation()); } @Test public void testParsingDefaultServerConfig() throws Exception { FileConfigurationParser parser = new FileConfigurationParser(); String configStr = firstPart + lastPart; ByteArrayInputStream input = new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)); Configuration config = parser.parseMainConfig(input); String clusterPassword = config.getClusterPassword(); assertEquals(ActiveMQDefaultConfiguration.getDefaultClusterPassword(), clusterPassword); //if we add cluster-password, it should be default plain text String clusterPasswordPart = "<cluster-password>helloworld</cluster-password>"; configStr = firstPart + clusterPasswordPart + lastPart; config = parser.parseMainConfig(new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8))); assertEquals("helloworld", config.getClusterPassword()); //if we add mask, it should be able to decode correctly DefaultSensitiveStringCodec codec = new DefaultSensitiveStringCodec(); String mask = (String) codec.encode("helloworld"); String maskPasswordPart = "<mask-password>true</mask-password>"; clusterPasswordPart = "<cluster-password>" + mask + "</cluster-password>"; configStr = firstPart + clusterPasswordPart + maskPasswordPart + lastPart; config = parser.parseMainConfig(new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8))); assertEquals("helloworld", config.getClusterPassword()); //if we change key, it should be able to decode correctly codec = new DefaultSensitiveStringCodec(); Map<String, String> prop = new HashMap<>(); prop.put("key", "newkey"); codec.init(prop); mask = (String) codec.encode("newpassword"); clusterPasswordPart = "<cluster-password>" + mask + "</cluster-password>"; String codecPart = "<password-codec>" + "org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec" + ";key=newkey</password-codec>"; configStr = firstPart + clusterPasswordPart + maskPasswordPart + codecPart + lastPart; config = parser.parseMainConfig(new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8))); assertEquals("newpassword", config.getClusterPassword()); } private static String firstPart = "<core xmlns=\"urn:activemq:core\">" + "\n" + "<name>ActiveMQ.main.config</name>" + "\n" + "<log-delegate-factory-class-name>org.apache.activemq.artemis.integration.logging.Log4jLogDelegateFactory</log-delegate-factory-class-name>" + "\n" + "<bindings-directory>${jboss.server.data.dir}/activemq/bindings</bindings-directory>" + "\n" + "<journal-directory>${jboss.server.data.dir}/activemq/journal</journal-directory>" + "\n" + "<journal-min-files>10</journal-min-files>" + "\n" + "<large-messages-directory>${jboss.server.data.dir}/activemq/largemessages</large-messages-directory>" + "\n" + "<paging-directory>${jboss.server.data.dir}/activemq/paging</paging-directory>" + "\n" + "<connectors>" + "\n" + "<connector name=\"netty\">tcp://localhost:61616</connector>" + "\n" + "<connector name=\"netty-throughput\">tcp://localhost:5545</connector>" + "\n" + "<connector name=\"in-vm\">vm://0</connector>" + "\n" + "</connectors>" + "\n" + "<acceptors>" + "\n" + "<acceptor name=\"netty\">tcp://localhost:5545</acceptor>" + "\n" + "<acceptor name=\"netty-throughput\">tcp://localhost:5545</acceptor>" + "\n" + "<acceptor name=\"in-vm\">vm://0</acceptor>" + "\n" + "</acceptors>" + "\n" + "<security-settings>" + "\n" + "<security-setting match=\"#\">" + "\n" + "<permission type=\"createNonDurableQueue\" roles=\"guest\"/>" + "\n" + "<permission type=\"deleteNonDurableQueue\" roles=\"guest\"/>" + "\n" + "<permission type=\"createDurableQueue\" roles=\"guest\"/>" + "\n" + "<permission type=\"deleteDurableQueue\" roles=\"guest\"/>" + "\n" + "<permission type=\"consume\" roles=\"guest\"/>" + "\n" + "<permission type=\"send\" roles=\"guest\"/>" + "\n" + "</security-setting>" + "\n" + "</security-settings>" + "\n" + "<address-settings>" + "\n" + "<address-setting match=\"#\">" + "\n" + "<dead-letter-address>DLQ\n</dead-letter-address>" + "\n" + "<expiry-address>ExpiryQueue\n</expiry-address>" + "\n" + "<redelivery-delay>0\n</redelivery-delay>" + "\n" + "<max-size-bytes>10485760\n</max-size-bytes>" + "\n" + "<message-counter-history-day-limit>10</message-counter-history-day-limit>" + "\n" + "<address-full-policy>BLOCK</address-full-policy>" + "\n" + "</address-setting>" + "\n" + "</address-settings>" + "\n"; private static String lastPart = "</core>"; }