diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java index 7609217c9b1b..361624c01749 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java @@ -58,6 +58,7 @@ import org.apache.activemq.artemis.cli.commands.queue.UpdateQueue; import org.apache.activemq.artemis.cli.commands.activation.ActivationSequenceList; import org.apache.activemq.artemis.cli.commands.tools.HelpData; +import org.apache.activemq.artemis.cli.commands.tools.InitLogging; import org.apache.activemq.artemis.cli.commands.tools.PrintData; import org.apache.activemq.artemis.cli.commands.tools.RecoverMessages; import org.apache.activemq.artemis.cli.commands.tools.journal.CompactJournal; @@ -226,7 +227,7 @@ private static Cli.CliBuilder builder(File artemisInstance) { withDefaultCommand(HelpData.class).withCommands(RecoverMessages.class, PrintData.class, XmlDataExporter.class, XmlDataImporter.class, DecodeJournal.class, EncodeJournal.class, CompactJournal.class); builder.withGroup("user").withDescription("default file-based user management (add|rm|list|reset) (example ./artemis user list)"). withDefaultCommand(HelpUser.class).withCommands(ListUser.class, AddUser.class, RemoveUser.class, ResetUser.class); - builder = builder.withCommands(Run.class, Stop.class, Kill.class, PerfJournal.class); + builder = builder.withCommands(Run.class, Stop.class, Kill.class, PerfJournal.class, InitLogging.class); } else { builder.withGroup("data").withDescription("data tools group (print|recover) (example ./artemis data print)"). withDefaultCommand(HelpData.class).withCommands(RecoverMessages.class, PrintData.class); diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java index 7aa2d7a75fa6..09fd0d76379b 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java @@ -556,8 +556,8 @@ public Object execute(ActionContext context) throws Exception { /** * This method is made public for the testsuite */ - public InputStream openStream(String source) { - return this.getClass().getResourceAsStream(source); + public static InputStream openStream(String source) { + return Create.class.getResourceAsStream(source); } /** @@ -585,8 +585,8 @@ private File createDirectory(String name, File root) { public Object run(ActionContext context) throws Exception { - IS_WINDOWS = System.getProperty("os.name").toLowerCase().trim().startsWith("win"); - IS_CYGWIN = IS_WINDOWS && "cygwin".equals(System.getenv("OSTYPE")); + IS_WINDOWS = isWin(); + IS_CYGWIN = isCygwin(); setupJournalType(); @@ -799,9 +799,9 @@ public Object run(ActionContext context) throws Exception { filters.put("${java-memory}", javaMemory); if (allowAnonymous) { - write(ETC_LOGIN_CONFIG_WITH_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false); + write(ETC_LOGIN_CONFIG_WITH_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false, force, encoding); } else { - write(ETC_LOGIN_CONFIG_WITHOUT_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false); + write(ETC_LOGIN_CONFIG_WITHOUT_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false, force, encoding); } writeEtc(ETC_ARTEMIS_ROLES_PROPERTIES, etcFolder, filters, false); @@ -930,6 +930,14 @@ public Object run(ActionContext context) throws Exception { return null; } + public static boolean isCygwin() { + return isWin() && "cygwin".equals(System.getenv("OSTYPE")); + } + + public static boolean isWin() { + return System.getProperty("os.name").toLowerCase().trim().startsWith("win"); + } + private String getConnectors(HashMap filters) throws IOException { if (staticNode != null) { StringWriter stringWriter = new StringWriter(); @@ -1149,17 +1157,17 @@ private String path(File value) throws IOException { } private void write(String source, HashMap filters, boolean unixTarget) throws Exception { - write(source, new File(directory, source), filters, unixTarget); + write(source, new File(directory, source), filters, unixTarget, force, encoding); } private void writeEtc(String source, File etcFolder, HashMap filters, boolean unixTarget) throws Exception { - write("etc/" + source, new File(etcFolder, source), filters, unixTarget); + write("etc/" + source, new File(etcFolder, source), filters, unixTarget, force, encoding); } - private void write(String source, + public static void write(String source, File target, - HashMap filters, - boolean unixTarget) throws Exception { + Map filters, + boolean unixTarget, boolean force, String encoding) throws Exception { if (target.exists() && !force) { throw new CLIException(String.format("The file '%s' already exists. Use --force to overwrite.", target)); } @@ -1168,7 +1176,7 @@ private void write(String source, // and then writing out in the new target encoding.. Let's also replace \n with the values // that is correct for the current platform. - String separator = unixTarget && IS_CYGWIN ? "\n" : System.getProperty("line.separator"); + String separator = unixTarget && isCygwin() ? "\n" : System.getProperty("line.separator"); content = content.replaceAll("\\r?\\n", Matcher.quoteReplacement(separator)); ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes(encoding)); try (FileOutputStream fout = new FileOutputStream(target)) { @@ -1176,14 +1184,14 @@ private void write(String source, } } - private String applyFilters(String content, Map filters) throws IOException { + private static String applyFilters(String content, Map filters) throws IOException { if (filters != null) { for (Map.Entry entry : filters.entrySet()) { try { content = replace(content, entry.getKey(), entry.getValue()); } catch (Throwable e) { - getActionContext().out.println("Error on " + entry.getKey()); + ActionContext.system().err.println("Error on " + entry.getKey()); e.printStackTrace(); System.exit(-1); } @@ -1192,7 +1200,7 @@ private String applyFilters(String content, Map filters) throws return content; } - private String readTextFile(String source, Map filters) throws IOException { + private static String readTextFile(String source, Map filters) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try (InputStream in = openStream(source)) { copy(in, out); @@ -1212,11 +1220,11 @@ private void write(String source) throws IOException { } } - private String replace(String content, String key, String value) { + private static String replace(String content, String key, String value) { return content.replaceAll(Pattern.quote(key), Matcher.quoteReplacement(value)); } - private void copy(InputStream is, OutputStream os) throws IOException { + private static void copy(InputStream is, OutputStream os) throws IOException { byte[] buffer = new byte[1024 * 4]; int c = is.read(buffer); while (c >= 0) { diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java index 62dc89e855b0..a2c42d88e44b 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java @@ -26,6 +26,7 @@ import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration; import org.apache.activemq.artemis.api.core.Pair; import org.apache.activemq.artemis.cli.Artemis; +import org.apache.activemq.artemis.cli.commands.tools.InitLogging; import org.apache.activemq.artemis.cli.commands.tools.LockAbstract; import org.apache.activemq.artemis.cli.factory.BrokerFactory; import org.apache.activemq.artemis.cli.factory.jmx.ManagementFactory; @@ -75,6 +76,8 @@ public static void setEmbedded(boolean embedded) { public Object execute(ActionContext context) throws Exception { super.execute(context); + InitLogging.verifyOlderLogging(new File(getBrokerInstance())); + AtomicReference serverActivationFailed = new AtomicReference<>(); try { BrokerDTO broker = getBrokerDTO(); diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/InitLogging.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/InitLogging.java new file mode 100644 index 000000000000..e85aeb180490 --- /dev/null +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/InitLogging.java @@ -0,0 +1,90 @@ +/* + * 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.cli.commands.tools; + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.invoke.MethodHandles; +import java.util.Collections; + +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import org.apache.activemq.artemis.cli.commands.ActionAbstract; +import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.Create; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(name = "init-logging", description = "Initialize a default log4j configuration") +public class InitLogging extends ActionAbstract { + + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + public static final String OLD_LOG_NAME = "logging.properties"; + + @Option(name = "--force", description = "Overwrite configuration at destination directory") + private boolean force; + + @Override + public Object execute(ActionContext context) throws Exception { + super.execute(context); + + initLogging(force, new File(getBrokerInstance())); + + return null; + } + + + public static void initLogging(boolean force, File brokerInstance) throws Exception { + File etc = new File(brokerInstance, "etc"); + File newLogging = new File(etc, Create.ETC_LOG4J2_PROPERTIES); + + if (!force && newLogging.exists()) { + System.err.println("A configuration file " + newLogging.getAbsolutePath() + " already exists! Use the option -f if you want to re-initialize it"); + return; + } + + Create.write("etc/" + Create.ETC_LOG4J2_PROPERTIES, newLogging, Collections.emptyMap(), false, force, "utf-8"); + } + + public static void verifyOlderLogging(File fileInstance) throws Exception { + File etc = new File(fileInstance, "etc"); + File newLogging = new File(etc, Create.ETC_LOG4J2_PROPERTIES); + File oldLogging = new File(etc, OLD_LOG_NAME); + + if (oldLogging.exists() && !newLogging.exists()) { + logger.warn("Logging not initialized!"); + StringWriter out = new StringWriter(); + PrintWriter writer = new PrintWriter(out); + writer.println("It seems you are migrating a previous version of an artemis instance without the new log4j configuration"); + writer.println(); + writer.printf("A new logging configuration is being created at %s", newLogging.getAbsolutePath()); + writer.println(); + writer.printf("The older configuration file %s should be manually removed.", oldLogging.getAbsolutePath()); + ActionContext.system().out.println(out); + + initLogging(false, fileInstance); + } + + if (oldLogging.exists()) { + ActionContext.system().out.printf("The old logging configuration file %s should be removed", oldLogging.getAbsolutePath()); + } + } + + +} \ No newline at end of file diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java index a136e2704803..091686454a99 100644 --- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java @@ -26,6 +26,7 @@ import javax.jms.TextMessage; import org.apache.activemq.artemis.api.core.QueueConfiguration; +import org.apache.activemq.artemis.cli.commands.tools.InitLogging; import org.apache.activemq.artemis.json.JsonArray; import org.apache.activemq.artemis.json.JsonObject; import javax.xml.parsers.DocumentBuilder; @@ -184,6 +185,19 @@ public void testSimpleCreate() throws Exception { Artemis.main("create", instance1.getAbsolutePath(), "--silent", "--no-fsync", "--no-autotune"); } + @Test + public void checkLogging() throws Exception { + File instance1 = new File(temporaryFolder.getRoot(), "instance1"); + Artemis.main("create", instance1.getAbsolutePath(), "--silent", "--no-fsync", "--no-autotune"); + File etc = new File(instance1, "etc"); + File newLogging = new File(etc, Create.ETC_LOG4J2_PROPERTIES); + File oldLogging = new File(etc, InitLogging.OLD_LOG_NAME); + Assert.assertTrue(newLogging.renameTo(oldLogging)); + Assert.assertFalse(newLogging.exists()); + InitLogging.verifyOlderLogging(instance1); + Assert.assertTrue(newLogging.exists()); + } + @Test public void testCreateDB() throws Exception {