diff options
Diffstat (limited to 'java')
10 files changed, 675 insertions, 115 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties index d393614191..8e9ee3720c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties @@ -1,13 +1,198 @@ +# +# 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. +# +# LogMessages used within the Java Broker as originally defined on the wiki: +# +# http://cwiki.apache.org/confluence/display/qpid/Status+Update+Design#StatusUpdateDesign-InitialStatusMessages +# +# Technical Notes: +# This is a standard Java Properties file so white space is respected at the +# end of the lines. This file is processed in a number of ways. +# 1) ResourceBundle +# This file is loaded through a ResourceBundle named LogMessages. the en_US +# addition to the file is the localisation. Additional localisations can be +# provided and will automatically be selected based on the <locale> value in +# the config.xml. The default is en_US. +# +# 2) MessasgeFormat +# Each entry is prepared with the Java Core MessageFormat methods. Therefore +# most functionality you can do via MessageFormat can be done here: +# +# http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html +# +# The cavet here is that only default String and number FormatTypes can be used. +# This is due to the processing described in 3 below. If support for date, time +# or choice is requried then the GenerateLogMessages class should be updated to +# provide support. +# +# Format Note: +# As mentioned earlier white space in this file is very important. One thing +# in particular to note is the way MessageFormat peforms its replacements. +# The replacement text will totally replace the {xxx} section so there will be +# no addtion of white space or removal e.g. +# MSG = Text----{0}---- +# When given parameter 'Hello' result in text: +# Text----Hello---- +# +# For simple arguments this is expected however when using Style formats then +# it can be a little unexepcted. In particular a common pattern is used for +# number replacements : {0,number,#}. This is used in the Broker to display an +# Integer simply as the Integer with no formating. e.g new Integer(1234567) +# becomes the String "1234567" which is can be contrasted with the pattern +# without a style format field : {0,number} which becomes string "1,234,567". +# +# What you may not expect is that {0,number, #} would produce the String " 1234567" +# note the space after the ',' here /\ has resulted in a space /\ in +# the output. +# +# More details on the SubformatPattern can be found on the API link above. +# +# 3) GenerateLogMessage/Velocity Macro +# This is the first and final stage of processing that this file goes through. +# 1) Class Generation: +# The GenerateLogMessage processes this file and uses the velocity Macro +# to create classes with static methods to perform the logging and give us +# compile time validation. +# +# 2) Property Processing: +# During the class generation the message properties ({x}) are identified +# and used to create the method signature. +# +# 3) Option Processing: +# The Classes perform final formatting of the messages at runtime based on +# optional parameters that are defined within the message. Optional +# paramters are enclosed in square brackets e.g. [optional]. +# +# To provide fixed log messages as required by the Technical Specification: +# http://cwiki.apache.org/confluence/display/qpid/Operational+Logging+-+Status+Update+-+Technical+Specification#OperationalLogging-StatusUpdate-TechnicalSpecification-Howtoprovidefixedlogmessages +# +# This file is processed by Velocity to create a number of classes that contain +# static methods that provide LogMessages in the code to provide compile time +# validation. +# +# For details of what processing is done see GenerateLogMessages. +# +# What a localiser or developer need know is the following: +# +# The Property structure is important is it defines how the class and methods +# will be built. +# +# Class Generation: +# ================= +# +# Each class of messages will be split in to their own <Class>Messages.java +# Currently the following classes are created and are populated with the +# messages that bear their 3-digit type identifier: +# +# Class | Type +# ---------------------|-------- +# Broker | BKR +# ManagementConsole | MNG +# VirtualHost | VHT +# MessageStore | MST +# Connection | CON +# Channel | CHN +# Queue | QUE +# Exchange | EXH +# Binding | BND +# Subscription | SUB +# +# Property Processing: +# ==================== +# +# Each property is then processed by the GenerateLogMessages class to identify +# The number and type of parameters, {x} entries. Parameters are defaulted to +# String types but the use of FormatType number (e.g.{0,number}) will result +# in a Number type being used. These parameters are then used to build the +# method parameter list. e.g: +# Property: +# BRK-1003 = Shuting down : {0} port {1,number,#} +# becomes Method: +# public static LogMessage BRK_1003(String param1, Number param2) +# +# This improves our compile time validation of log message content and +# ensures that change in the message format does not accidentally cause +# erroneous messages. +# +# Option Processing: +# ==================== +# +# Options are identified in the log message as being surrounded by square +# brackets ([ ]). These optional values can themselves contain paramters +# however nesting of options is not permitted. Identification is performed on +# first matchings so give the message: +# Msg = Log Message [option1] [option2] +# Two options will be identifed and enabled to select text 'option1 and +# 'option2'. +# +# The nesting of a options is not supported and will provide +# unexpected results. e.g. Using Message: +# Msg = Log Message [option1 [sub-option2]] +# +# The options will be 'option1 [sub-option2' and 'sub-option2'. The first +# option includes the second option as the nesting is not detected. +# +# The detected options are presented in the method signature as boolean options +# numerically identified by their position in the message. e.g. +# Property: +# CON-1001 = Open : Client ID {0} [: Protocol Version : {1}] +# becomes Method: +# public static LogMessage CON_1001(String param1, String param2, boolean opt1) +# +# The value of 'opt1' will show/hide the option in the message. Note that +# 'param2' is still required however a null value can be used if the optional +# section is not desired. +# +# Again here the importance of white space needs to be highlighted. +# Looking at the QUE-1001 message as an example. The first thought on how this +# would look would be as follows: +# QUE-1001 = Create : Owner: {0} [AutoDelete] [Durable] [Transient] [Priority: {1,number,#}] +# Each option is correctly defined so the text that is defined will appear when +# selected. e.g. 'AutoDelete'. However, what may not be immediately apparent is +# the white space. Using the above definition of QUE-1001 if we were to print +# the message with only the Priority option displayed it would appear as this: +# "Create : Owner: guest Priority: 1" +# Note the spaces here /\ This is because only the text between the brackets +# has been removed. +# +# Each option needs to include white space to correctly format the message. So +# the correct definition of QUE-1001 is as follows: +# QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}] +# Note that white space is included with each option and there is no extra +# white space between the options. As a result the output with just Priority +# enabled is as follows: +# "Create : Owner: guest Priority: 1" +# +# The final processing that is done in the generation is the conversion of the +# property name. As a '-' is an illegal character in the method name it is +# converted to '_' This processing gives the final method signature as follows: +# <Class>Message.<Type>_<Number>(<parmaters>,<options>) +# #Broker # 0 - Version # 1 = Build BRK-1001 = Startup : Version: {0} Build: {1} # 0 - Transport # 1 - Port -BRK-1002 = Starting : Listening on {0} port {1, number, #} +BRK-1002 = Starting : Listening on {0} port {1,number,#} # 0 - Transport # 1 - Port -BRK-1003 = Shuting down : {0} port {1, number, #} +BRK-1003 = Shuting down : {0} port {1,number,#} BRK-1004 = Ready BRK-1005 = Stopped # 0 - path @@ -19,10 +204,10 @@ BRK-1007 = Using logging configuration : {0} MNG-1001 = Startup # 0 - Service # 1 - Port -MNG-1002 = Starting : {0} : Listening on port {1, number, #} +MNG-1002 = Starting : {0} : Listening on port {1,number,#} # 0 - Service # 1 - Port -MNG-1003 = Shuting down : {0} : port {1, number, #} +MNG-1003 = Shuting down : {0} : port {1,number,#} MNG-1004 = Ready MNG-1005 = Stopped # 0 - Path @@ -39,20 +224,18 @@ MST-1001 = Created : {0} # 0 - path MST-1002 = Store location : {0} MST-1003 = Closed -MST-1004 = Recovery Start # 0 - queue name -MST-1005 = Recovery Start : {0} +MST-1004 = Recovery Start[ : {0}] # 0 - count # 1 - queue count -MST-1006 = Recovered {0,number} messages for queue {1} -MST-1007 = Recovery Complete +MST-1005 = Recovered {0,number} messages for queue {1} # 0 - queue name -MST-1008 = Recovery Complete : {0} +MST-1006 = Recovery Complete[ : {0}] #Connection # 0 - Client id # 1 - Protocol Version -CON-1001 = Open : Client ID {0} : Protocol Version : {1} +CON-1001 = Open : Client ID {0}[ : Protocol Version : {1}] CON-1002 = Close #Channel @@ -64,19 +247,20 @@ CHN-1003 = Close #Queue # 0 - owner -QUE-1001 = Create : Owner:{0} [AutoDelete] [Durable|Transient] [Priority:<levels>] +# 1 - priority +QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}] QUE-1002 = Deleted #Exchange # 0 - type # 1 - name -EXH-1001 = Create : [Durable] Type:{0} Name:{1} +EXH-1001 = Create :[ Durable] Type: {0} Name: {1} EXH-1002 = Deleted #Binding -BND-1001 = Create [: Arguments : <key=value>] +BND-1001 = Create[ : Arguments : {0}] BND-1002 = Deleted #Subscription -SUB-1001 = Create : [Durable] [Arguments : <key=value>] +SUB-1001 = Create[ : Durable][ : Arguments : {0}] SUB-1002 = Close diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java index 6589695146..17a9d6c591 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java @@ -81,24 +81,35 @@ public abstract class AbstractTestMessages extends TestCase { assertEquals("Log has incorrect message count", 1, logs.size()); - String log = String.valueOf(logs.get(0)); + //We trim() here as we don't care about extra white space at the end of the log message + // but we do care about the ability to easily check we don't have unexpected text at + // the end. + String log = String.valueOf(logs.get(0)).trim(); - int index = log.indexOf(_logSubject.toString()); + // Simple switch to print out all the logged messages + //System.err.println(log); - assertTrue("Unable to locate Subject:" + log, index != -1); + int msgIndex = log.indexOf(_logSubject.toString())+_logSubject.toString().length(); - String message = log.substring(index + _logSubject.toString().length()); + assertTrue("Unable to locate Subject:" + log, msgIndex != -1); + + String message = log.substring(msgIndex); assertTrue("Message does not start with tag:" + tag + ":" + message, message.startsWith(tag)); // Test that the expected items occur in order. - index = 0; + int index = 0; for (String text : expected) { index = message.indexOf(text, index); assertTrue("Message does not contain expected (" + text + ") text :" + message, index != -1); + index = index + text.length(); } + + //Check there is nothing left on the log message + assertEquals("Message has more text. '" + log.substring(msgIndex + index) + "'", + log.length(), msgIndex + index); } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java index a12d14239d..b2182bb1b2 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java @@ -25,9 +25,9 @@ import java.util.List; public class BindingMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001_NoArgs() { - _logMessage = BindingMessages.BND_1001(); + _logMessage = BindingMessages.BND_1001(null, false); List<Object> log = performLog(); String[] expected = {"Create"}; @@ -35,6 +35,18 @@ public class BindingMessagesTest extends AbstractTestMessages validateLogMessage(log, "BND-1001", expected); } + public void testMessage1001_Args() + { + String arguments = "arguments"; + + _logMessage = BindingMessages.BND_1001(arguments, true); + List<Object> log = performLog(); + + String[] expected = {"Create", ": Arguments :", arguments}; + + validateLogMessage(log, "BND-1001", expected); + } + public void testMessage1002() { _logMessage = BindingMessages.BND_1002(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java index 8723c48476..eb76029a5c 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java @@ -24,12 +24,12 @@ import java.util.List; public class ConnectionMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001_WithProtocolVersion() { String clientID = "client"; String protocolVersion = "8-0"; - _logMessage = ConnectionMessages.CON_1001(clientID, protocolVersion); + _logMessage = ConnectionMessages.CON_1001(clientID, protocolVersion, true); List<Object> log = performLog(); String[] expected = {"Open :", "Client ID", clientID, @@ -38,6 +38,19 @@ public class ConnectionMessagesTest extends AbstractTestMessages validateLogMessage(log, "CON-1001", expected); } + public void testMessage1001_NoProtocolVersion() + { + String clientID = "client"; + + _logMessage = ConnectionMessages.CON_1001(clientID, null, false); + List<Object> log = performLog(); + + String[] expected = {"Open :", "Client ID", clientID}; + + validateLogMessage(log, "CON-1001", expected); + } + + public void testMessage1002() { _logMessage = ConnectionMessages.CON_1002(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java index 46a911fdc6..831ede3e0c 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java @@ -27,7 +27,7 @@ import java.util.List; public class ExchangeMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001_Transient() { // Get the Default Exchange on the Test Vhost for testing Exchange exchange = ApplicationRegistry.getInstance(). @@ -37,7 +37,7 @@ public class ExchangeMessagesTest extends AbstractTestMessages String type = exchange.getType().toString(); String name = exchange.getName().toString(); - _logMessage = ExchangeMessages.EXH_1001(type, name); + _logMessage = ExchangeMessages.EXH_1001(type, name, false); List<Object> log = performLog(); String[] expected = {"Create :", "Type:", type, "Name:", name}; @@ -45,6 +45,25 @@ public class ExchangeMessagesTest extends AbstractTestMessages validateLogMessage(log, "EXH-1001", expected); } + public void testMessage1001_Persistent() + { + // Get the Default Exchange on the Test Vhost for testing + Exchange exchange = ApplicationRegistry.getInstance(). + getVirtualHostRegistry().getVirtualHost("test"). + getExchangeRegistry().getDefaultExchange(); + + String type = exchange.getType().toString(); + String name = exchange.getName().toString(); + + _logMessage = ExchangeMessages.EXH_1001(type, name, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Durable", "Type:", type, "Name:", name}; + + validateLogMessage(log, "EXH-1001", expected); + } + + public void testMessage1002() { _logMessage = ExchangeMessages.EXH_1002(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java index e1ae93b869..e02993b840 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java @@ -61,7 +61,7 @@ public class MessageStoreMessagesTest extends AbstractTestMessages public void testMessage1004() { - _logMessage = MessageStoreMessages.MST_1004(); + _logMessage = MessageStoreMessages.MST_1004(null,false); List<Object> log = performLog(); String[] expected = {"Recovery Start"}; @@ -69,24 +69,24 @@ public class MessageStoreMessagesTest extends AbstractTestMessages validateLogMessage(log, "MST-1004", expected); } - public void testMessage1005() + public void testMessage1004_withQueue() { String queueName = "testQueue"; - _logMessage = MessageStoreMessages.MST_1005(queueName); + _logMessage = MessageStoreMessages.MST_1004(queueName, true); List<Object> log = performLog(); String[] expected = {"Recovery Start :", queueName}; - validateLogMessage(log, "MST-1005", expected); + validateLogMessage(log, "MST-1004", expected); } - public void testMessage1006() + public void testMessage1005() { String queueName = "testQueue"; Integer messasgeCount = 2000; - _logMessage = MessageStoreMessages.MST_1006(messasgeCount, queueName); + _logMessage = MessageStoreMessages.MST_1005(messasgeCount, queueName); List<Object> log = performLog(); // Here we use MessageFormat to ensure the messasgeCount of 2000 is @@ -95,29 +95,29 @@ public class MessageStoreMessagesTest extends AbstractTestMessages MessageFormat.format("{0,number}", messasgeCount), "messages for queue", queueName}; - validateLogMessage(log, "MST-1006", expected); + validateLogMessage(log, "MST-1005", expected); } - public void testMessage1007() + public void testMessage1006() { - _logMessage = MessageStoreMessages.MST_1007(); + _logMessage = MessageStoreMessages.MST_1006(null,false); List<Object> log = performLog(); String[] expected = {"Recovery Complete"}; - validateLogMessage(log, "MST-1007", expected); + validateLogMessage(log, "MST-1006", expected); } - public void testMessage1008() + public void testMessage1006_withQueue() { String queueName = "testQueue"; - _logMessage = MessageStoreMessages.MST_1008(queueName); + _logMessage = MessageStoreMessages.MST_1006(queueName, true); List<Object> log = performLog(); String[] expected = {"Recovery Complete :", queueName}; - validateLogMessage(log, "MST-1008", expected); + validateLogMessage(log, "MST-1006", expected); } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java index 4ba00ea6e4..2f53d0aff5 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java @@ -24,14 +24,114 @@ import java.util.List; public class QueueMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001ALL() { String owner = "guest"; + Integer priority = 3; - _logMessage = QueueMessages.QUE_1001(owner); + _logMessage = QueueMessages.QUE_1001(owner, priority, true, true, true, true); List<Object> log = performLog(); - String[] expected = {"Create :", "Owner:", owner}; + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Durable", "Transient", "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDelete() + { + String owner = "guest"; + + _logMessage = QueueMessages.QUE_1001(owner, null, true, false, false, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete"}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001Priority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, false, false, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeletePriority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, true, false, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteTransient() + { + String owner = "guest"; + + _logMessage = QueueMessages.QUE_1001(owner, null, true, false, true, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Transient"}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteTransientPriority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, true, false, true, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Transient", "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteDurable() + { + String owner = "guest"; + + _logMessage = QueueMessages.QUE_1001(owner, null, true, true, false, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Durable"}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteDurablePriority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, true, true, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Durable", "Priority:", + String.valueOf(priority)}; validateLogMessage(log, "QUE-1001", expected); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java index 1bb96e1e33..80ebcc79cd 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java @@ -24,17 +24,41 @@ import java.util.List; public class SubscriptionMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001ALL() { + String arguments = "arguments"; - _logMessage = SubscriptionMessages.SUB_1001(); + _logMessage = SubscriptionMessages.SUB_1001(arguments, true, true); List<Object> log = performLog(); - String[] expected = {"Create :"}; + String[] expected = {"Create :", "Durable", "Arguments :", arguments}; validateLogMessage(log, "SUB-1001", expected); } + public void testMessage1001Durable() + { + _logMessage = SubscriptionMessages.SUB_1001(null, true, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Durable"}; + + validateLogMessage(log, "SUB-1001", expected); + } + + public void testMessage1001Arguments() + { + String arguments = "arguments"; + + _logMessage = SubscriptionMessages.SUB_1001(arguments, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :","Arguments :", arguments}; + + validateLogMessage(log, "SUB-1001", expected); + } + + public void testMessage1002() { _logMessage = SubscriptionMessages.SUB_1002(); diff --git a/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java b/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java index cc0565031f..ea0946f6d6 100644 --- a/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java +++ b/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java @@ -30,6 +30,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Properties; import java.util.ResourceBundle; @@ -210,15 +211,20 @@ public class GenerateLogMessages * type checking during compilation whilst allowing the log message to * maintain formatting controls. * + * OPTIONS + * * The returned hashMap contains the following structured data: * * - name - ClassName ('Broker') - * list - methodName ('BRK_1001') - * - name ('BRK-1001') - * - format ('Startup : Version: {0} Build: {1}') - * - parameters (list) - * - type ('String'|'Number') - * - name ('param1') + * - list[logEntryData] - methodName ('BRK_1001') + * - name ('BRK-1001') + * - format ('Startup : Version: {0} Build: {1}') + * - parameters (list) + * - type ('String'|'Number') + * - name ('param1') + * - options (list) + * - name ('opt1') + * - value ('AutoDelete') * * @param messsageName the name to give the Class e.g. 'Broker' * @param messageKey the 3-digit key to extract the messages e.g. 'BRK' @@ -228,7 +234,7 @@ public class GenerateLogMessages private HashMap<String, Object> prepareType(String messsageName, String messageKey) throws InvalidTypeException { // Load the LogMessages Resource Bundle - ResourceBundle _messages = ResourceBundle.getBundle("org.apache.qpid.server.logging.messages.LogMessages"); + ResourceBundle _messages = ResourceBundle.getBundle("org.apache.qpid.server.logging.messages.LogMessages", Locale.US); Enumeration<String> messageKeys = _messages.getKeys(); @@ -265,79 +271,187 @@ public class GenerateLogMessages // Javadoc of the method. logEntryData.put("format", logMessage); - // Split the string on the start brace '{' this will give us the - // details for each parameter that this message contains. - String[] parametersString = logMessage.split("\\{"); - // Taking an example of 'Text {n[,type]} text {m} more text {p}' - // This would give us: - // 0 - Text - // 1 - n[,type]} text - // 2 - m} more text - // 3 - p} - - // Create the parameter list for this item - List<HashMap<String, String>> parameters = new LinkedList<HashMap<String, String>>(); + // Add the parameters for this message + logEntryData.put("parameters", extractParameters(logMessage)); - // Add the parameter list to this log entry data - logEntryData.put("parameters", parameters); + //Add the options for this messagse + logEntryData.put("options", extractOptions(logMessage)); - // Add the data to the list of messages + //Add this entry to the list for this class logMessageList.add(logEntryData); + } + } - // Check that we have some parameters to process - // Skip 0 as that will not be the first entry - // Text {n[,type]} text {m} more text {p} - if (parametersString.length > 1) - { - for (int index = 1; index < parametersString.length; index++) - { - // Use a HashMap to store the type,name of the parameter - // for easy retrieval in the macro template - HashMap<String, String> parameter = new HashMap<String, String>(); + return messageTypeData; + } - // Check for any properties of the parameter : - // e.g. {0} vs {0,number} vs {0,number,xxxx} - int typeIndex = parametersString[index].indexOf(","); + /** + * This method is responsible for extracting the options form the given log + * message and providing a HashMap with the expected data: + * - options (list) + * - name ('opt1') + * - value ('AutoDelete') + * + * The options list that this method provides must contain HashMaps that + * have two entries. A 'name' and a 'value' these strings are important as + * they are used in LogMessage.vm to extract the stored String during + * processing of the template. + * + * The 'name' is a unique string that is used to name the boolean parameter + * and refer to it later in the method body. + * + * The 'value' is used to provide documentation in the generated class to + * aid readability. + * + * @param logMessage the message from the properties file + * @return list of option data + */ + private List<HashMap<String, String>> extractOptions(String logMessage) + { + // Split the string on the start brace '{' this will give us the + // details for each parameter that this message contains. + // NOTE: Simply splitting on '[' prevents the use of nested options. + // Currently there is no demand for nested options + String[] optionString = logMessage.split("\\["); + // Taking an example of: + // 'Text {n,type,format} [option] text {m} [option with param{p}] more' + // This would give us: + // 0 - Text {n,type,format} + // 1 - option] text {m} + // 2 - option with param{p}] more + + // Create the parameter list for this item + List<HashMap<String, String>> options = new LinkedList<HashMap<String, String>>(); + + // Check that we have some parameters to process + // Skip 0 as that will not be the first entry + // Text {n,type,format} [option] text {m} [option with param{p}] more + if (optionString.length > 1) + { + for (int index = 1; index < optionString.length; index++) + { + // Use a HashMap to store the type,name of the parameter + // for easy retrieval in the macro template + HashMap<String, String> option = new HashMap<String, String>(); - // The parameter type - String type; + // Locate the end of the Option + // NOTE: it is this simple matching on the first ']' that + // prevents the nesting of options. + // Currently there is no demand for nested options + int end = optionString[index].indexOf("]"); - //Be default all types are Strings - if (typeIndex == -1) - { - type = "String"; - } - else - { - //Check string ',....}' for existence of number - // to identify this parameter as an integer - // This allows for a style value to be present - // Only check the text inside the braces '{}' - int typeIndexEnd = parametersString[index].indexOf("}", typeIndex); - String typeString = parametersString[index].substring(typeIndex, typeIndexEnd); - if (typeString.contains("number")) - { - type = "Number"; - } - else - { - throw new InvalidTypeException("Invalid type(" + typeString + ") index (" + parameter.size() + ") in message:" + logMessage); - } + // The parameter type + String value = optionString[index].substring(0, end); - } + // Simply name the parameters by index. + option.put("name", "opt" + index); + + //Store the value e.g. AutoDelete + // We trim as we don't need to include any whitespace that is + // used for formating. This is only used to aid readability of + // of the generated code. + option.put("value", value.trim()); - //Store the data - parameter.put("type", type); - // Simply name the parameters by index. - parameter.put("name", "param" + index); + options.add(option); + } + } - parameters.add(parameter); + return options; + } + + /** + * This method is responsible for extract the parameters that are requried + * for this log message. The data is returned in a HashMap that has the + * following structure: + * - parameters (list) + * - type ('String'|'Number') + * - name ('param1') + * + * The parameters list that is provided must contain HashMaps that have the + * two named entries. A 'type' and a 'name' these strings are importans as + * they are used in LogMessage.vm to extract and the stored String during + * processing of the template + * + * The 'type' and 'name' values are used to populate the method signature. + * This is what gives us the compile time validation of log messages. + * + * The 'name' must be unique as there may be many parameters. The value is + * also used in the method body to pass the values through to the + * MessageFormat class for formating the log message. + * + * @param logMessage the message from the properties file + * @return list of option data + * @throws InvalidTypeException if the FormatType is specified and is not 'number' + */ + private List<HashMap<String, String>> extractParameters(String logMessage) + throws InvalidTypeException + { + // Split the string on the start brace '{' this will give us the + // details for each parameter that this message contains. + String[] parametersString = logMessage.split("\\{"); + // Taking an example of 'Text {n[,type]} text {m} more text {p}' + // This would give us: + // 0 - Text + // 1 - n[,type]} text + // 2 - m} more text + // 3 - p} + + // Create the parameter list for this item + List<HashMap<String, String>> parameters = new LinkedList<HashMap<String, String>>(); + + // Check that we have some parameters to process + // Skip 0 as that will not be the first entry + // Text {n[,type]} text {m} more text {p} + if (parametersString.length > 1) + { + for (int index = 1; index < parametersString.length; index++) + { + // Use a HashMap to store the type,name of the parameter + // for easy retrieval in the macro template + HashMap<String, String> parameter = new HashMap<String, String>(); + + // Check for any properties of the parameter : + // e.g. {0} vs {0,number} vs {0,number,xxxx} + int typeIndex = parametersString[index].indexOf(","); + + + // The parameter type + String type; + + //Be default all types are Strings + if (typeIndex == -1) + { + type = "String"; + } + else + { + //Check string ',....}' for existence of number + // to identify this parameter as an integer + // This allows for a style value to be present + // Only check the text inside the braces '{}' + int typeIndexEnd = parametersString[index].indexOf("}", typeIndex); + String typeString = parametersString[index].substring(typeIndex, typeIndexEnd); + if (typeString.contains("number")) + { + type = "Number"; } + else + { + throw new InvalidTypeException("Invalid type(" + typeString + ") index (" + parameter.size() + ") in message:" + logMessage); + } + } + + //Store the data + parameter.put("type", type); + // Simply name the parameters by index. + parameter.put("name", "param" + index); + + parameters.add(parameter); } } - return messageTypeData; + return parameters; } /** diff --git a/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm b/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm index 6656763ab9..917901a18b 100644 --- a/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm +++ b/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm @@ -33,7 +33,10 @@ import java.util.ResourceBundle; * This file is based on the content of LogMessages.properties * * It is generated so that we can provide compile time validation of the - * message parameters + * message parameters. + * + * DO NOT EDIT DIRECTLY THIS FILE IS GENERATED. + * */ public class ${type.name}Messages { @@ -51,25 +54,105 @@ public class ${type.name}Messages _formatter.setLocale(currentLocale); } +## +## The list stored under key 'list' in the 'type' HashMap contains all the +## log messages that this class should contain. So for each entry in the list +## this template will create a new log method. +## #foreach( $message in ${type.list} ) /** * Log a ${type.name} message of the Format: - * <pre>${message.format}</pre> + * <pre>${message.format}</pre> + * Optional values are contained in [square brackets] and are numbered + * sequentially in the method call. + * */ +## There is a lot in the method header here. To make it more readable/understandable +## This is the same text laid out to be easier to read: +## public static LogMessage ${message.methodName} ( +## #foreach($parameter in ${message.parameters}) +## ${parameter.type} ${parameter.name} +## #if (${velocityCount} != ${message.parameters.size()} ) +## , +## #end +## #end +## #if(${message.parameters.size()} > 0 && ${message.options.size()} > 0) +## , +## #end +## #foreach($option in ${message.options}) +## boolean ${option.name} +## #if (${velocityCount} != ${message.options.size()} ) +## , +## #end +## #end +## ) +## +## What is going on is that we set the method name based on the HashMap lookup +## for 'methodName' Then for each entry(another HashMap) in the list stored +## in the HashMap under 'parameters' build the argument list of from the 'type' +## and 'name' values. Ensuring that we add a ', ' between each entry. +## +## However, check that we are not at the last entry of the list as we don't +## want to add ', ' at then end. +## +## Before we go on to the options we perform a check to see if we had any +## parameters. If we did and we have options to add then we add ', ' to keep +## the syntax correct. +## +## We then go on to the options that are again retrieved from the top HashMap +## with key 'options'. For each option a boolean argument is created and the +## name is retrieved from the option HashMap with key 'name' +## public static LogMessage ${message.methodName}(#foreach($parameter in ${message.parameters})${parameter.type} ${parameter.name}#if (${velocityCount} != ${message.parameters.size()} ), #end -#end) +#end#if(${message.parameters.size()} > 0 && ${message.options.size()} > 0), #end#foreach($option in ${message.options})boolean ${option.name}#if (${velocityCount} != ${message.options.size()} ), #end#end) { final Object[] messageArguments = {#foreach($parameter in ${message.parameters})${parameter.name}#if (${velocityCount} != ${message.parameters.size()} ), #end#end}; - _formatter.applyPattern(_messages.getString("${message.name}")); + + ## If we have some options then we need to build the message based + ## on those values so only provide that logic if we need it. +#if(${message.options.size()} > 0) + String rawMessage = _formatter.format(messageArguments); + + StringBuffer msg =new StringBuffer("${message.name} : "); + + // Split the formatted message up on the option values so we can + // rebuild the message based on the configured options. + String[] parts = rawMessage.split("\\["); + msg.append(parts[0]); + + int end; + if (parts.length > 1) + { + ## For Each Optional value check if it has been enabled and then + ## append it to the log. +#foreach($option in ${message.options}) + + // Add Option : ${option.value} + end = parts[${velocityCount}].indexOf(']'); + if (${option.name}) + { + msg.append(parts[${velocityCount}].substring(0, end)); + } + + // Use 'end + 1' to remove the ']' from the output + msg.append(parts[${velocityCount}].substring(end + 1)); +#end + } + + final String message = msg.toString(); +#else + ## If we have no options then we can just format and set the log + final String message = "${message.name} : " + _formatter.format(messageArguments); +#end + return new LogMessage() { public String toString() { - return "${message.name} : " + _formatter.format(messageArguments); + return message; } }; - } #end |
